Compare commits
187 Commits
debian/1.5
...
debian/lat
Author | SHA1 | Date |
---|---|---|
Jonas Smedegaard | 0ea9928830 | |
Jonas Smedegaard | c270ddb719 | |
Jonas Smedegaard | 438d62ce7c | |
Jonas Smedegaard | 98cb3656e8 | |
Jonas Smedegaard | 572c919417 | |
Jonas Smedegaard | c08bef0a7f | |
Jonas Smedegaard | 205941ae82 | |
Jonas Smedegaard | 8d1aee7be7 | |
Jonas Smedegaard | 49b48ca081 | |
Joao Azevedo | e68e594824 | |
Joao Azevedo | 02633098cd | |
Joao Azevedo | 607d66eacf | |
Jonas Smedegaard | 4d1112fa6f | |
Jonas Smedegaard | 2fe6b6edbf | |
Jonas Smedegaard | 896b40a689 | |
Jonas Smedegaard | 46b5c47f1c | |
Jonas Smedegaard | b317241f69 | |
Jonas Smedegaard | 46189709b2 | |
Joao Azevedo | b1e9e28b21 | |
Joao Azevedo | 401b323d79 | |
Joao Azevedo | d9ef53d5e4 | |
Joao Azevedo | 5793a37819 | |
Joao Azevedo | 97ba8ef723 | |
Joao Azevedo | d3ea13e54e | |
Joao Azevedo | 83c95e2dd3 | |
Jonas Smedegaard | 96080d09ea | |
Jonas Smedegaard | 173347e839 | |
Jonas Smedegaard | 2fc7443c7e | |
Jonas Smedegaard | 990bd45fc2 | |
Jonas Smedegaard | f04507e70d | |
João Azevedo | dce6ad2b7e | |
Jonas Smedegaard | ac0bc67fb0 | |
Jonas Smedegaard | e9616bad84 | |
Jonas Smedegaard | 9672db0cd3 | |
Jonas Smedegaard | e11228cf77 | |
Jonas Smedegaard | 1fdc215aff | |
Jonas Smedegaard | 0184c3385a | |
Jonas Smedegaard | 7ee81214af | |
Jonas Smedegaard | 00fd4dd934 | |
Jonas Smedegaard | c42a2612fc | |
Jonas Smedegaard | 09a674a13f | |
Jonas Smedegaard | 0858593426 | |
Jonas Smedegaard | e98850b7a5 | |
Jonas Smedegaard | e35961252e | |
Jonas Smedegaard | f8f0ddec27 | |
Jonas Smedegaard | 199ad5b24d | |
Jonas Smedegaard | 84102327d5 | |
Jonas Smedegaard | 96a4801af7 | |
Jonas Smedegaard | fc19a86e83 | |
Jonas Smedegaard | d3526b3a96 | |
Jonas Smedegaard | cbdafe2783 | |
Jonas Smedegaard | d72ec5241c | |
Jonas Smedegaard | 4fff221b94 | |
Jonas Smedegaard | d9ffe16513 | |
Jonas Smedegaard | 629b069e0b | |
Jonas Smedegaard | 02d72e2fbe | |
Jonas Smedegaard | 0139dc3440 | |
Jonas Smedegaard | 4e50cab599 | |
Jonas Smedegaard | 73336f6a5a | |
Jonas Smedegaard | be77943a00 | |
Jonas Smedegaard | fd832ff9a2 | |
Jonas Smedegaard | 6674f63d2f | |
Jonas Smedegaard | 58a357cc52 | |
Jonas Smedegaard | 612b1d2d2a | |
Jonas Smedegaard | da7996df58 | |
Jonas Smedegaard | b986fd87e3 | |
Jonas Smedegaard | e1df01ef96 | |
Jonas Smedegaard | df08e36fc0 | |
Jonas Smedegaard | 04e752b84e | |
Jonas Smedegaard | b62cbf7e60 | |
Jonas Smedegaard | ff5dc93d5b | |
Jonas Smedegaard | fac5c460cc | |
Jonas Smedegaard | 0ca2baaf33 | |
Jonas Smedegaard | 142ff5e66e | |
Jonas Smedegaard | 4ec6fd12db | |
Jonas Smedegaard | 73412b147f | |
Jonas Smedegaard | 59a2637307 | |
Jonas Smedegaard | b0da99eb22 | |
Jonas Smedegaard | 979892df3a | |
Jonas Smedegaard | 015be34169 | |
Tino Mettler | b9c153ddf3 | |
Jonas Smedegaard | 693ba4c3fe | |
Tino Mettler | 22449d72c0 | |
Patrick Ohly | 238f9368c2 | |
Patrick Ohly | 971da5408f | |
Patrick Ohly | 6fc5f4703b | |
Patrick Ohly | 9b7a9ed7ef | |
Patrick Ohly | bf14e33977 | |
Patrick Ohly | 28ee02b0eb | |
Patrick Ohly | d4ed6cae5b | |
Patrick Ohly | 3968562049 | |
Patrick Ohly | e132410296 | |
Patrick Ohly | 0a64fbadcc | |
Milan Crha | c656bc4a08 | |
Patrick Ohly | dc88a596b3 | |
Patrick Ohly | b4f8743bfc | |
Patrick Ohly | 420c44ea6b | |
Patrick Ohly | 2bc0535881 | |
Patrick Ohly | 90c3ca329d | |
Patrick Ohly | 54d5f08d76 | |
Patrick Ohly | 798c2f4d09 | |
Patrick Ohly | 7cf0dd5217 | |
Patrick Ohly | 64c62b53b4 | |
Patrick Ohly | 516d8258ca | |
deloptes | 57d357afee | |
Patrick Ohly | a6b490ef83 | |
Patrick Ohly | 051b8ac8d2 | |
Patrick Ohly | 8f7fc79007 | |
Patrick Ohly | f9ca9e34de | |
Milan Crha | edb458dfcb | |
Patrick Ohly | a3bb1fba4a | |
Patrick Ohly | afd10b27e2 | |
Patrick Ohly | b2b1f2f161 | |
Patrick Ohly | 0e5ee4f41a | |
Patrick Ohly | e88bfa6214 | |
Patrick Ohly | 7d527c6dd8 | |
Patrick Ohly | 85edb458f4 | |
Patrick Ohly | b8cbd5358f | |
Patrick Ohly | 02a711f143 | |
Patrick Ohly | 74f0d01f33 | |
Patrick Ohly | ae4969cfa3 | |
Patrick Ohly | 6217ba0bd1 | |
Patrick Ohly | 67147853f7 | |
Patrick Ohly | 2fa3c3335a | |
Patrick Ohly | d0c08bf0dd | |
Patrick Ohly | bce7526da1 | |
Patrick Ohly | 623397c674 | |
Patrick Ohly | e95ac67d4b | |
Patrick Ohly | 39bf3f1291 | |
Patrick Ohly | 3729a239fc | |
Patrick Ohly | 618e8b9d71 | |
Patrick Ohly | 8713809b35 | |
Patrick Ohly | 3dc1514ab9 | |
Patrick Ohly | 04f8ac0454 | |
Patrick Ohly | 2705d06fa6 | |
Patrick Ohly | e3783d3039 | |
Patrick Ohly | 068e8d0ae3 | |
Patrick Ohly | e773bc9a69 | |
Patrick Ohly | 25442ad2e6 | |
Patrick Ohly | 7014e5bb67 | |
Patrick Ohly | 9c00b725f9 | |
Patrick Ohly | 55cb5ad46f | |
Patrick Ohly | d5a7d38029 | |
Patrick Ohly | 3cd62b3e41 | |
Patrick Ohly | edf1314def | |
Milan Crha | 75dff12823 | |
Patrick Ohly | 3bd97cc795 | |
Patrick Ohly | fb8e527afc | |
Patrick Ohly | 407f213a7f | |
Patrick Ohly | c78bcbb076 | |
Patrick Ohly | 8378272412 | |
Patrick Ohly | 77a9a450d2 | |
Patrick Ohly | 1216bdaebc | |
Patrick Ohly | b649bf454c | |
Patrick Ohly | ba95bce198 | |
Patrick Ohly | e39167a9d8 | |
Patrick Ohly | 749a889bf2 | |
Patrick Ohly | 1bf4ce81b1 | |
Patrick Ohly | 83fe101576 | |
Patrick Ohly | c077579240 | |
Patrick Ohly | b7dbeeac49 | |
Patrick Ohly | 3afdbaf651 | |
Patrick Ohly | 8d6d960153 | |
Patrick Ohly | 2747426b7c | |
Patrick Ohly | 1126b65b6a | |
Patrick Ohly | 0db56499c2 | |
Patrick Ohly | d7a591dc73 | |
Patrick Ohly | 88619eb58c | |
Patrick Ohly | 52a3457037 | |
Patrick Ohly | 7e4bdb5b07 | |
Patrick Ohly | 60de1423aa | |
Patrick Ohly | 0abc7d8251 | |
Patrick Ohly | b71ed933a8 | |
Patrick Ohly | 55c7eba954 | |
Patrick Ohly | 0c59f20b91 | |
Patrick Ohly | 62387107f9 | |
Patrick Ohly | 77335c8d82 | |
Patrick Ohly | 3a79a8d398 | |
Patrick Ohly | f797987710 | |
Patrick Ohly | bd6adff9a5 | |
Patrick Ohly | 11e5e94ac2 | |
Patrick Ohly | 4fe4b6dd14 | |
Patrick Ohly | 8ce962a3bd | |
Patrick Ohly | 705a5c66a8 | |
Patrick Ohly | 3325aebbff | |
Patrick Ohly | 7b7660af60 | |
Patrick Ohly | d5ecc1b468 |
11
HACKING
11
HACKING
|
@ -44,9 +44,10 @@ The test framework also requires CPPUnit:
|
||||||
|
|
||||||
For the GUI and its D-Bus based service backend:
|
For the GUI and its D-Bus based service backend:
|
||||||
apt-get install xsltproc \
|
apt-get install xsltproc \
|
||||||
|
libdbus-glib-1-dev \
|
||||||
libglib2.0-dev \
|
libglib2.0-dev \
|
||||||
libgtk2.0-dev libglade2-dev \
|
libgtk2.0-dev libglade2-dev \
|
||||||
libgnome-keyring-dev \
|
libsecret-1-dev \
|
||||||
libgconf2-dev libgnomevfs2-dev
|
libgconf2-dev libgnomevfs2-dev
|
||||||
|
|
||||||
Optional packages for GUI:
|
Optional packages for GUI:
|
||||||
|
@ -78,8 +79,8 @@ It depends on:
|
||||||
Checking out the Source
|
Checking out the Source
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
SyncEvolution is hosted on moblin.org. Anonymous access is via
|
SyncEvolution is hosted on freedesktop.org. Anonymous access is via
|
||||||
git clone git://git.moblin.org/syncevolution.git
|
git clone git://anongit.freedesktop.org/SyncEvolution/syncevolution
|
||||||
|
|
||||||
Before using sources checked out from Subversion, invoke "sh
|
Before using sources checked out from Subversion, invoke "sh
|
||||||
autogen.sh" with appropriate autotools packages installed.
|
autogen.sh" with appropriate autotools packages installed.
|
||||||
|
@ -93,9 +94,9 @@ faster compilation) and will bundle the Synthesis sources in source
|
||||||
|
|
||||||
The upstream Synthesis source code is here:
|
The upstream Synthesis source code is here:
|
||||||
git://www.synthesis.ch/libsynthesis.git
|
git://www.synthesis.ch/libsynthesis.git
|
||||||
The staging area for patches developed as part of Moblin are
|
The staging area for patches developed as part of SyncEvolution are
|
||||||
in the following repository:
|
in the following repository:
|
||||||
git://git.moblin.org/libsynthesis.git
|
git://anongit.freedesktop.org/SyncEvolution/libsynthesis
|
||||||
|
|
||||||
The intention is to include all these patches upstream to
|
The intention is to include all these patches upstream to
|
||||||
prevent forking the code. If you want to get patches included
|
prevent forking the code. If you want to get patches included
|
||||||
|
|
29
Makefile.am
29
Makefile.am
|
@ -16,14 +16,8 @@ endif
|
||||||
|
|
||||||
SUBDIRS += .
|
SUBDIRS += .
|
||||||
|
|
||||||
# choose D-Bus implementation
|
|
||||||
if COND_GIO_GDBUS
|
|
||||||
gdbus_dir = $(top_srcdir)/src/gdbusxx
|
gdbus_dir = $(top_srcdir)/src/gdbusxx
|
||||||
gdbus_build_dir = src/gdbusxx
|
gdbus_build_dir = src/gdbusxx
|
||||||
else
|
|
||||||
gdbus_dir = $(top_srcdir)/src/gdbus
|
|
||||||
gdbus_build_dir = src/gdbus
|
|
||||||
endif
|
|
||||||
|
|
||||||
disted_docs =
|
disted_docs =
|
||||||
distbin_docs =
|
distbin_docs =
|
||||||
|
@ -132,7 +126,7 @@ TYPE_rpm = -R
|
||||||
# - same for kdepimlibs5 -> libakonadi-kde4
|
# - same for kdepimlibs5 -> libakonadi-kde4
|
||||||
# - kdebase-runtime became kde-runtime in Debian Wheezy
|
# - kdebase-runtime became kde-runtime in Debian Wheezy
|
||||||
REQUIRES_SED_KDE = -e 's/kdelibs5 ([^,]*),/kdelibs5 | libkdeui5,/g' -e 's/kdepimlibs5 ([^,]*),/kdepimlibs5 | libakonadi-kde4,/g' -e 's/kdebase-runtime/kdebase-runtime | kde-runtime/g'
|
REQUIRES_SED_KDE = -e 's/kdelibs5 ([^,]*),/kdelibs5 | libkdeui5,/g' -e 's/kdepimlibs5 ([^,]*),/kdepimlibs5 | libakonadi-kde4,/g' -e 's/kdebase-runtime/kdebase-runtime | kde-runtime/g'
|
||||||
REQUIRES_deb = --requires="'$(shell set -x; cd checkinstall/dist; LD_LIBRARY_PATH=$(distdir)/usr/lib:$(distdir)/usr/lib/syncevolution dpkg-shlibdeps -L$(srcdir)/src/shlibs.local --ignore-missing-info -O $$(for i in $$(find $(distdir) -type f -perm /u+x | grep -v -e client-test -e lib/syncevolution/backends/); do if file $$i | grep ELF >/dev/null; then echo $$i; fi; done) | sed $(REQUIRES_SED_KDE) -e 's/[^=]*=//')$(REQUIRES_deb_neon)$(REQUIRES_deb_ical)'"
|
REQUIRES_deb = --requires="'$(shell set -x; cd checkinstall/dist; LD_LIBRARY_PATH=$(distdir)/usr/lib:$(distdir)/usr/lib/syncevolution dpkg-shlibdeps -L$(EXTRA_SHLIBS_LOCAL) --ignore-missing-info -O $$(for i in $$(find $(distdir) -type f -perm /u+x | grep -v -e client-test -e lib/syncevolution/backends/); do if file $$i | grep ELF >/dev/null; then echo $$i; fi; done) | sed $(REQUIRES_SED_KDE) -e 's/[^=]*=//')$(REQUIRES_deb_neon)'"
|
||||||
if NEON_COMPATIBILITY
|
if NEON_COMPATIBILITY
|
||||||
# --enable-neon-compatibility in src/backends/webdav:
|
# --enable-neon-compatibility in src/backends/webdav:
|
||||||
# replace dependencies from linking with hard-coded dlopen() dependencies
|
# replace dependencies from linking with hard-coded dlopen() dependencies
|
||||||
|
@ -140,9 +134,6 @@ REQUIRES_deb_neon = , libneon27 (>= 0.29.0) | libneon27-gnutls (>= 0.29.0)
|
||||||
else
|
else
|
||||||
REQUIRES_deb_neon =
|
REQUIRES_deb_neon =
|
||||||
endif
|
endif
|
||||||
if ENABLE_ICAL
|
|
||||||
REQUIRES_deb_ical = , libical0 | libical1 | libical1a | libical2
|
|
||||||
endif
|
|
||||||
VERSION_deb = 1:$(STABLE_VERSION)$(VERSION)
|
VERSION_deb = 1:$(STABLE_VERSION)$(VERSION)
|
||||||
VERSION_rpm = `echo $(VERSION) | sed -e s/-/_/g`
|
VERSION_rpm = `echo $(VERSION) | sed -e s/-/_/g`
|
||||||
RELEASE = 2
|
RELEASE = 2
|
||||||
|
@ -179,6 +170,7 @@ deb rpm : checkinstall/dist/$(distdir) checkinstall/dist/debian/control
|
||||||
$(TYPE_$@) \
|
$(TYPE_$@) \
|
||||||
$(REQUIRES_$@) \
|
$(REQUIRES_$@) \
|
||||||
--fstrans=yes \
|
--fstrans=yes \
|
||||||
|
--install=no \
|
||||||
--strip=no \
|
--strip=no \
|
||||||
--pkgversion=$(VERSION_$@) \
|
--pkgversion=$(VERSION_$@) \
|
||||||
--pkgrelease=$(RELEASE) \
|
--pkgrelease=$(RELEASE) \
|
||||||
|
@ -200,7 +192,8 @@ deb rpm : checkinstall/dist/$(distdir) checkinstall/dist/debian/control
|
||||||
PLATFORM_DEB_VERSION = $(VERSION_deb)
|
PLATFORM_DEB_VERSION = $(VERSION_deb)
|
||||||
PLATFORM_DEB_RELEASE = 1
|
PLATFORM_DEB_RELEASE = 1
|
||||||
if ENABLE_MODULES
|
if ENABLE_MODULES
|
||||||
deb : syncevolution-kde-deb
|
# Not supported anymore.
|
||||||
|
# deb : syncevolution-kde-deb
|
||||||
deb : syncevolution-evolution-deb
|
deb : syncevolution-evolution-deb
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -220,6 +213,7 @@ SYNCEVOLUTION_evolution_DEB_ARGS = \
|
||||||
--conflicts=syncevolution-foobar \
|
--conflicts=syncevolution-foobar \
|
||||||
--replaces=syncevolution-foobar
|
--replaces=syncevolution-foobar
|
||||||
SYNCEVOLUTION_evolution_DEB_REQUIRES = \
|
SYNCEVOLUTION_evolution_DEB_REQUIRES = \
|
||||||
|
, evolution-data-server \
|
||||||
, $(EXTRA_BACKENDS_EBOOK_REQUIRES) \
|
, $(EXTRA_BACKENDS_EBOOK_REQUIRES) \
|
||||||
, $(EXTRA_BACKENDS_ECAL_REQUIRES)
|
, $(EXTRA_BACKENDS_ECAL_REQUIRES)
|
||||||
|
|
||||||
|
@ -238,7 +232,7 @@ syncevolution-%-deb: checkinstall/dist/$(distdir) checkinstall/dist/debian/contr
|
||||||
$(SYNCEVOLUTION_$*_DEB_ARGS) \
|
$(SYNCEVOLUTION_$*_DEB_ARGS) \
|
||||||
--pkgname=syncevolution-$* \
|
--pkgname=syncevolution-$* \
|
||||||
--pkgarch=all \
|
--pkgarch=all \
|
||||||
--requires="'$(shell set -x; cd checkinstall/dist; LD_LIBRARY_PATH=$(distdir)/usr/lib:$(distdir)/usr/lib/syncevolution dpkg-shlibdeps -L$(srcdir)/src/shlibs.local --ignore-missing-info -O $$(for i in $(patsubst %,$(distdir)/usr/lib/syncevolution/backends/%.so,$(PLATFORM_FILES_$*)); do if file $$i | grep ELF >/dev/null; then echo $$i; fi; done) | sed $(REQUIRES_SED_KDE) -e 's/[^=]*=//'), $(PKGNAME) (= $(VERSION_deb)-$(RELEASE))$(SYNCEVOLUTION_$*_DEB_REQUIRES)'" \
|
--requires="'$(shell set -x; cd checkinstall/dist; LD_LIBRARY_PATH=$(distdir)/usr/lib:$(distdir)/usr/lib/syncevolution dpkg-shlibdeps -L$(EXTRA_SHLIBS_LOCAL) --ignore-missing-info -O $$(for i in $(patsubst %,$(distdir)/usr/lib/syncevolution/backends/%.so,$(PLATFORM_FILES_$*)); do if file $$i | grep ELF >/dev/null; then echo $$i; fi; done) | sed $(REQUIRES_SED_KDE) -e 's/[^=]*=//'), $(PKGNAME) (= $(VERSION_deb)-$(RELEASE))$(SYNCEVOLUTION_$*_DEB_REQUIRES)'" \
|
||||||
--maintainer="'Patrick Ohly <patrick.ohly@gmx.de>'" \
|
--maintainer="'Patrick Ohly <patrick.ohly@gmx.de>'" \
|
||||||
--pkgsource='http://syncevolution.org' \
|
--pkgsource='http://syncevolution.org' \
|
||||||
--pkggroup='$*' \
|
--pkggroup='$*' \
|
||||||
|
@ -351,9 +345,10 @@ RUN_SYNCEVOLUTION_CHECK=die if $$?; return $$buffer;
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# patch README.rst properties on-the-fly
|
# patch README.rst properties on-the-fly
|
||||||
|
if COND_CMDLINE
|
||||||
README.patched.rst: README.rst src/syncevolution
|
README.patched.rst: README.rst src/syncevolution
|
||||||
$(AM_V_GEN)perl -e '$$syncfound=0; $$sourcefound=0; $$res=0;' \
|
$(AM_V_GEN)perl -e '$$syncfound=0; $$sourcefound=0; $$res=0;' \
|
||||||
-e 'sub run { $$cmd = shift; $$buffer = `env LD_LIBRARY_PATH=src/syncevo/.libs:src/gdbus/.libs:src/gdbusxx/.libs:src/build-synthesis/src/.libs:$$ENV{LD_LIBRARY_PATH} $$cmd`; $(RUN_SYNCEVOLUTION_CHECK) }' \
|
-e 'sub run { $$cmd = shift; $$buffer = `env LD_LIBRARY_PATH=src/syncevo/.libs:src/gdbusxx/.libs:src/build-synthesis/src/.libs:$$ENV{LD_LIBRARY_PATH} $$cmd`; $(RUN_SYNCEVOLUTION_CHECK) }' \
|
||||||
-e 'while (<>) {' \
|
-e 'while (<>) {' \
|
||||||
-e 's/^:Version: .*/:Version: $(VERSION)/;' \
|
-e 's/^:Version: .*/:Version: $(VERSION)/;' \
|
||||||
-e 's/:Date: .*/":Date: " . `date +%Y-%m-%d`/e;' \
|
-e 's/:Date: .*/":Date: " . `date +%Y-%m-%d`/e;' \
|
||||||
|
@ -365,6 +360,14 @@ README.patched.rst: README.rst src/syncevolution
|
||||||
-e 'die "<<source-property>> tag not in README.rst?!" unless $$sourcefound;' \
|
-e 'die "<<source-property>> tag not in README.rst?!" unless $$sourcefound;' \
|
||||||
-e 'exit $$res;' \
|
-e 'exit $$res;' \
|
||||||
$< >$@
|
$< >$@
|
||||||
|
else
|
||||||
|
# Simpler version without inserting the actual sync and datastore properties.
|
||||||
|
README.patched.rst: README.rst
|
||||||
|
$(AM_V_GEN)perl -p \
|
||||||
|
-e 's/^:Version: .*/:Version: $(VERSION)/;' \
|
||||||
|
-e 's/:Date: .*/":Date: " . `date +%Y-%m-%d`/e;' \
|
||||||
|
$< >$@
|
||||||
|
endif
|
||||||
CLEANFILES += README.patched.rst
|
CLEANFILES += README.patched.rst
|
||||||
|
|
||||||
# produce man pages
|
# produce man pages
|
||||||
|
|
83
NEWS
83
NEWS
|
@ -1,3 +1,86 @@
|
||||||
|
SyncEvolution 1.5.3 -> 2.0.0, 21.03.2021
|
||||||
|
========================================
|
||||||
|
|
||||||
|
This release modernizes the code base and removes usage of out-dated
|
||||||
|
libraries and APIs. All Python scripts require Python 3. The major
|
||||||
|
version bump reflects that this release is not just a minor bug fix.
|
||||||
|
However, no new features were added.
|
||||||
|
|
||||||
|
Binaries on syncevolution.org get built for distros >= Ubuntu Bionic
|
||||||
|
and Debian Buster. Testing is now based on Docker containers instead
|
||||||
|
of a custom schroot solution, so adding testing against other distros
|
||||||
|
will be easier in the future. Compilation on Fedora Rawhide was
|
||||||
|
already added.
|
||||||
|
|
||||||
|
Some features are no longer built and thus untested:
|
||||||
|
- ActiveSync
|
||||||
|
- KDE
|
||||||
|
|
||||||
|
The code is still there, but needs help from interested developers to
|
||||||
|
ensure that it really works. It may get removed in a future version if
|
||||||
|
there is no interest.
|
||||||
|
|
||||||
|
|
||||||
|
SyncEvolution 1.5.2 -> 1.5.3, 03.01.2018
|
||||||
|
========================================
|
||||||
|
|
||||||
|
Maintenance release. syncevolution.org binaries are now getting
|
||||||
|
compiled for distros >= Ubuntu Xenial 16.04 LTS. Usage of deprecated
|
||||||
|
libraries (GNOME keyring) and APIs (SoupAsyncSession) was
|
||||||
|
replaced. libical v3 is supported.
|
||||||
|
|
||||||
|
The code now compiles more cleanly with recent compilers and depends
|
||||||
|
on C++11 support.
|
||||||
|
|
||||||
|
Details:
|
||||||
|
|
||||||
|
* EDS: more generic open retry handling
|
||||||
|
|
||||||
|
Recent EDS started to exhibit race conditions when opening a database (for
|
||||||
|
example, https://bugzilla.gnome.org/show_bug.cgi?id=791306). Opening was
|
||||||
|
already tried again for a certain known error in some old EDS version. Now it
|
||||||
|
is tried five times with a delay of one second for all errors.
|
||||||
|
|
||||||
|
* SoupTransportAgent: require libsoup 2.42, no deprecated methods
|
||||||
|
|
||||||
|
This allows us to get rid of deprecated function calls. We no longer
|
||||||
|
need to set a default proxy either, the newer libsoup does that itself
|
||||||
|
by default.
|
||||||
|
|
||||||
|
* C++: replace auto_ptr with unique_ptr, require C++11
|
||||||
|
|
||||||
|
auto_ptr has been deprecated for a while now. unique_ptr can
|
||||||
|
be taken for granted now, so use that instead.
|
||||||
|
|
||||||
|
* testing: work around Google CalDAV RECURRENCE-ID
|
||||||
|
|
||||||
|
Stand-alone events with RECURRENCE-ID get mangled by the server:
|
||||||
|
it converts the RECURRENCE-ID time to UTC. Reported in:
|
||||||
|
https://stackoverflow.com/questions/47811670/detached-recurrence-without-parent-event
|
||||||
|
|
||||||
|
* GNOME: replace gnome-keyring with libsecret (FDO #104219)
|
||||||
|
|
||||||
|
The GNOME keyring library has been obsoleted for a long time now,
|
||||||
|
long enough that the replacement libsecret is available on all
|
||||||
|
supported distros. Therefore we can switch unconditionally.
|
||||||
|
|
||||||
|
* libical: support libical v3 (FDO #104220)
|
||||||
|
|
||||||
|
libical v3 removes some deprecated functions (like icaltime_from_timet)
|
||||||
|
and removes the "is_utc" member from icaltimetype. The replacement
|
||||||
|
code works with old and new libical and thus needs no ifdefs.
|
||||||
|
|
||||||
|
Original author: Milan Crha
|
||||||
|
|
||||||
|
* syncevolution.org: fixed packaging (FDO #98014, FDO #100549)
|
||||||
|
|
||||||
|
The activesyncd package missing dependencies on libgnome-keyring0 and
|
||||||
|
libglib2.0-bin and therefore failed to work when installed on a minimal
|
||||||
|
system without those.
|
||||||
|
|
||||||
|
* various build and test fixes/workarounds
|
||||||
|
|
||||||
|
|
||||||
SyncEvolution 1.5.1 -> 1.5.2, 08.11.2016
|
SyncEvolution 1.5.1 -> 1.5.2, 08.11.2016
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ dist_noinst_SCRIPTS += build/gen-git-version.sh \
|
||||||
|
|
||||||
EXTRA_DIST += \
|
EXTRA_DIST += \
|
||||||
build/export-foreign-git.sh \
|
build/export-foreign-git.sh \
|
||||||
build/export-gdbus.sh \
|
|
||||||
build/export-synthesis-xml.sh \
|
build/export-synthesis-xml.sh \
|
||||||
build/gen-backends-am.sh \
|
build/gen-backends-am.sh \
|
||||||
build/gen-backends.sh \
|
build/gen-backends.sh \
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
#! /bin/sh
|
|
||||||
#
|
|
||||||
# Run this inside the top level of a clean
|
|
||||||
# syncevolution git repository. Pass the path
|
|
||||||
# to a gdbus repository (default: ../libgdbus).
|
|
||||||
#
|
|
||||||
# The script generates .patch files for all changes
|
|
||||||
# made in the current branch to files which are
|
|
||||||
# shared with gdbus. The resulting files can
|
|
||||||
# be imported with "git am".
|
|
||||||
|
|
||||||
set -e
|
|
||||||
set -x
|
|
||||||
|
|
||||||
`dirname $0`/export-foreign-git.sh "${1:-../libgdbus}" src src/gdbus \
|
|
||||||
src/gdbus/debug.c \
|
|
||||||
src/gdbus/debug.h \
|
|
||||||
src/gdbus/gdbus.h \
|
|
||||||
src/gdbus/mainloop.c \
|
|
||||||
src/gdbus/object.c \
|
|
||||||
src/gdbus/watch.c
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python3
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Converts source code (first parameter, can be - for stdin) to HTML
|
Converts source code (first parameter, can be - for stdin) to HTML
|
||||||
|
@ -29,8 +29,8 @@ try:
|
||||||
pygments.highlight(code, lexer, formatter, out)
|
pygments.highlight(code, lexer, formatter, out)
|
||||||
except:
|
except:
|
||||||
import cgi
|
import cgi
|
||||||
print >>sys.stderr, "source2html.py failed with pygments:", sys.exc_info()
|
print("source2html.py failed with pygments:", sys.exc_info(), file=sys.stderr)
|
||||||
print >>sys.stderr, "falling back to internal code"
|
print("falling back to internal code", file=sys.stderr)
|
||||||
|
|
||||||
out.write('''<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
out.write('''<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||||
<html>
|
<html>
|
||||||
|
|
145
configure.ac
145
configure.ac
|
@ -8,7 +8,7 @@ dnl Invoke autogen.sh to produce a configure script.
|
||||||
#
|
#
|
||||||
# Starting with the 1.1 release cycle, the rpm-style
|
# Starting with the 1.1 release cycle, the rpm-style
|
||||||
# .99 pseudo-version number is used to mark a pre-release.
|
# .99 pseudo-version number is used to mark a pre-release.
|
||||||
AC_INIT([syncevolution], [m4_esyscmd([build/gen-git-version.sh 1.5.2])])
|
AC_INIT([syncevolution], [m4_esyscmd([build/gen-git-version.sh 2.0.0])])
|
||||||
# STABLE_VERSION=1.0.1+
|
# STABLE_VERSION=1.0.1+
|
||||||
AC_SUBST(STABLE_VERSION)
|
AC_SUBST(STABLE_VERSION)
|
||||||
|
|
||||||
|
@ -62,6 +62,19 @@ dnl check for programs.
|
||||||
AC_PROG_CXX
|
AC_PROG_CXX
|
||||||
AC_PROG_MAKE_SET
|
AC_PROG_MAKE_SET
|
||||||
|
|
||||||
|
AC_PATH_PROGS(PYTHON, python3 python, "")
|
||||||
|
if test "x$PYTHON" = "x" ; then
|
||||||
|
AC_ERROR([python3 not found])
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl Use the most recent C++ standard that is supported by the code.
|
||||||
|
dnl We can fall back to older versions, but not below C++11.
|
||||||
|
dnl Akonadi/Qt don't work with C++17 yet, so we can't enable that.
|
||||||
|
AX_CXX_COMPILE_STDCXX_14(noext, optional)
|
||||||
|
if test "$HAVE_CXX14" -ne 1; then
|
||||||
|
AX_CXX_COMPILE_STDCXX_11(noext, mandatory)
|
||||||
|
fi
|
||||||
|
|
||||||
# Boost headers: boost/foreach.hpp is needed (1.33/Debian Etch
|
# Boost headers: boost/foreach.hpp is needed (1.33/Debian Etch
|
||||||
# doesn't have it, 1.34/Ubuntu 8.10 Hardy does). 1.35 is available
|
# doesn't have it, 1.34/Ubuntu 8.10 Hardy does). 1.35 is available
|
||||||
# as Debian Etch backport.
|
# as Debian Etch backport.
|
||||||
|
@ -70,8 +83,17 @@ AX_BOOST_BASE(1.34)
|
||||||
# TODO: Fix code to pass with -pedantic -Wextra.
|
# TODO: Fix code to pass with -pedantic -Wextra.
|
||||||
# -Wno-unknown-pragmas needed because icalstrdup.h
|
# -Wno-unknown-pragmas needed because icalstrdup.h
|
||||||
# currently uses the "#pragma }" trick. Should remove that.
|
# currently uses the "#pragma }" trick. Should remove that.
|
||||||
# Fix code to work without deprecated methods: G GDK GDK_PIXBUF CAIRO PANGO GTK
|
# -Wno-deprecated-declarations is needed everywhere (i.e. not just in certain
|
||||||
|
# modules, like SYNCEVO_WFLAGS_DEPRECATED) because EDS on Ubuntu Eon uses
|
||||||
|
# the deprecated GDateTime in its header, which we included through our
|
||||||
|
# EDS/libical wrapper even when not actually used.
|
||||||
DK_ARG_ENABLE_WARNINGS([SYNCEVO_WFLAGS],
|
DK_ARG_ENABLE_WARNINGS([SYNCEVO_WFLAGS],
|
||||||
|
[-Wall -Wno-unknown-pragmas],
|
||||||
|
[-Wall -Wno-unknown-pragmas -Wno-deprecated-declarations],
|
||||||
|
[])
|
||||||
|
|
||||||
|
# Fix code to work without deprecated methods: G GDK GDK_PIXBUF CAIRO PANGO GTK
|
||||||
|
DK_ARG_ENABLE_WARNINGS([SYNCEVO_WFLAGS_DEPRECATED],
|
||||||
[-Wall -Wno-unknown-pragmas -Wno-deprecated-declarations],
|
[-Wall -Wno-unknown-pragmas -Wno-deprecated-declarations],
|
||||||
[-Wall -Wno-unknown-pragmas -Wno-deprecated-declarations],
|
[-Wall -Wno-unknown-pragmas -Wno-deprecated-declarations],
|
||||||
[])
|
[])
|
||||||
|
@ -223,12 +245,9 @@ else
|
||||||
have_libcurl="no"
|
have_libcurl="no"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PKG_CHECK_MODULES(LIBSOUP, libsoup-gnome-2.4,
|
PKG_CHECK_MODULES(LIBSOUP, libsoup-2.4 >= 2.42,
|
||||||
[have_libsoup="yes"
|
have_libsoup="yes",
|
||||||
AC_DEFINE(HAVE_LIBSOUP_SOUP_GNOME_FEATURES_H, 1, [enable GNOME specific libsoup])],
|
have_libsoup="no")
|
||||||
[PKG_CHECK_MODULES(LIBSOUP, libsoup-2.4,
|
|
||||||
have_libsoup="yes",
|
|
||||||
have_libsoup="no")])
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(LIBOPENOBEX, openobex, have_obex="yes", have_obex="no")
|
PKG_CHECK_MODULES(LIBOPENOBEX, openobex, have_obex="yes", have_obex="no")
|
||||||
have_bluetooth="no"
|
have_bluetooth="no"
|
||||||
|
@ -477,6 +496,18 @@ AC_ARG_ENABLE(core,
|
||||||
enable_core="$enableval",
|
enable_core="$enableval",
|
||||||
enable_core="yes")
|
enable_core="yes")
|
||||||
AM_CONDITIONAL([COND_CORE], [test "$enable_core" = "yes"])
|
AM_CONDITIONAL([COND_CORE], [test "$enable_core" = "yes"])
|
||||||
|
AC_ARG_ENABLE(cmdline,
|
||||||
|
AS_HELP_STRING([--enable-cmdline],
|
||||||
|
[enables building the SyncEvolution command line tool, syncevolution]),
|
||||||
|
enable_cmdline="$enableval",
|
||||||
|
enable_cmdline="yes")
|
||||||
|
AM_CONDITIONAL([COND_CMDLINE], [test "$enable_cmdline" = "yes"])
|
||||||
|
AC_ARG_ENABLE(local-sync,
|
||||||
|
AS_HELP_STRING([--enable-local-sync],
|
||||||
|
[enables building the local synchronization support, in particular syncevo-local-sync]),
|
||||||
|
enable_local_sync="$enableval",
|
||||||
|
enable_local_sync="yes")
|
||||||
|
AM_CONDITIONAL([COND_LOCAL_SYNC], [test "$enable_local_sync" = "yes"])
|
||||||
|
|
||||||
AC_ARG_ENABLE(dbus-service,
|
AC_ARG_ENABLE(dbus-service,
|
||||||
AS_HELP_STRING([--enable-dbus-service=args],
|
AS_HELP_STRING([--enable-dbus-service=args],
|
||||||
|
@ -498,33 +529,15 @@ if test "$enable_dbus_service" != "no" && test "$enable_dbus_service" != "yes";
|
||||||
fi
|
fi
|
||||||
AC_SUBST(SYNCEVO_DBUS_SERVER_ARGS)
|
AC_SUBST(SYNCEVO_DBUS_SERVER_ARGS)
|
||||||
|
|
||||||
AC_ARG_WITH([gio-gdbus],
|
|
||||||
AS_HELP_STRING([--with-gio-gdbus],
|
|
||||||
[enables use of GIO's GDBus instead of the in-tree, Bluez gdbus.]),
|
|
||||||
with_gio_gdbus="$withval",
|
|
||||||
PKG_CHECK_EXISTS([gio-2.0 >= 2.30],
|
|
||||||
[with_gio_gdbus="yes"],
|
|
||||||
[with_gio_gdbus="no"]))
|
|
||||||
AM_CONDITIONAL([COND_GIO_GDBUS], [test "x$with_gio_gdbus" = "xyes"])
|
|
||||||
|
|
||||||
# We only need to check for dbus-1 if gio-gdbus is not used.
|
|
||||||
#
|
|
||||||
# Local sync depends on D-Bus communication between parent
|
# Local sync depends on D-Bus communication between parent
|
||||||
# and child process (works without a D-Bus daemon), and local
|
# and child process (works without a D-Bus daemon), and local
|
||||||
# sync is not an optional feature. Could be made one if
|
# sync is not an optional feature. Could be made one if
|
||||||
# someone is interested enough.
|
# someone is interested enough.
|
||||||
#
|
#
|
||||||
# Therefore, at the moment, either libdbus or gio-gdbus are needed
|
# Therefore, at the moment, gio-gdbus is needed
|
||||||
# unconditionally. glib is needed in all cases now.
|
# unconditionally. glib is needed in all cases now.
|
||||||
need_glib=yes
|
need_glib=yes
|
||||||
AS_IF([test "x$with_gio_gdbus" = "xyes"],
|
PKG_CHECK_MODULES([DBUS], [gio-2.0 >= 2.26])
|
||||||
[PKG_CHECK_MODULES([DBUS], [gio-2.0 >= 2.26])
|
|
||||||
AC_DEFINE([WITH_GIO_GDBUS],[],[Set if using GIO GDBus])],
|
|
||||||
[PKG_CHECK_MODULES(DBUS, dbus-1, dummy=yes,
|
|
||||||
AC_MSG_ERROR(libdbus-1 is required))
|
|
||||||
AC_CHECK_LIB(dbus-1, dbus_watch_get_unix_fd, dummy=yes,
|
|
||||||
AC_DEFINE(NEED_DBUS_WATCH_GET_UNIX_FD, 1,
|
|
||||||
[Define to 1 if you need the dbus_watch_get_unix_fd() function.]))])
|
|
||||||
|
|
||||||
if test "$enable_dbus_service" != "no"; then
|
if test "$enable_dbus_service" != "no"; then
|
||||||
if test -z "$XSLT"; then
|
if test -z "$XSLT"; then
|
||||||
|
@ -559,74 +572,7 @@ if test "$enable_dbus_service" != "no"; then
|
||||||
MLITE_LIBS=
|
MLITE_LIBS=
|
||||||
fi
|
fi
|
||||||
AC_DEFINE(DBUS_SERVICE, 1, [define if dbus service is enabled])
|
AC_DEFINE(DBUS_SERVICE, 1, [define if dbus service is enabled])
|
||||||
|
|
||||||
AC_ARG_ENABLE(dbus-service-pim,
|
|
||||||
AS_HELP_STRING([--enable-dbus-service-pim[=<locale>]],
|
|
||||||
[Enable implementation of org._01.pim D-Bus APIs (depends on libfolks),
|
|
||||||
using src/dbus/server/pim/locale-factory-<locale>.cpp to implement sorting
|
|
||||||
and searching. The default is <locale>=boost, which uses boost::locale.]),
|
|
||||||
[ enable_dbus_pim="$enableval" ],
|
|
||||||
[ enable_dbus_pim="no" ])
|
|
||||||
case "$enable_dbus_pim" in
|
|
||||||
no) ;;
|
|
||||||
*)
|
|
||||||
if test "$enable_dbus_pim" = "yes"; then
|
|
||||||
enable_dbus_pim=boost
|
|
||||||
fi
|
|
||||||
if ! test -r "$srcdir/src/dbus/server/pim/locale-factory-$enable_dbus_pim.cpp"; then
|
|
||||||
AC_MSG_ERROR([invalid value '$enable_dbus_pim' for --enable-dbus-service-pim, $srcdir/src/dbus/server/pim/locale-factory-$enable_dbus_pim.cpp does not exist or is not readable])
|
|
||||||
fi
|
|
||||||
PKG_CHECK_MODULES(FOLKS, [folks folks-eds])
|
|
||||||
AC_DEFINE(ENABLE_DBUS_PIM, 1, [org._01.pim D-Bus API enabled])
|
|
||||||
DBUS_PIM_PLUGIN=$enable_dbus_pim
|
|
||||||
AC_SUBST(DBUS_PIM_PLUGIN)
|
|
||||||
|
|
||||||
case "$enable_dbus_pim" in
|
|
||||||
boost)
|
|
||||||
AX_BOOST_LOCALE
|
|
||||||
# AX_BOOST_LOCALE incorrectly puts -L/... into LDFLAGS.
|
|
||||||
# That's broken because it then overrides the search path
|
|
||||||
# for *all* libraries in a link, not just for boost. Fix
|
|
||||||
# this by putting the LDFLAGS before the lib and leaving
|
|
||||||
# DBUS_PIM_PLUGIN_LDFLAGS empty (for now - might have to
|
|
||||||
# be revised if there ever are any boost flags which need
|
|
||||||
# to go to the start of the link line).
|
|
||||||
DBUS_PIM_PLUGIN_LIBS='$(BOOST_LDFLAGS) $(BOOST_LOCALE_LIB)'
|
|
||||||
DBUS_PIM_PLUGIN_LDFLAGS=
|
|
||||||
# We need to call ICU directly for the Han->Latin transformation.
|
|
||||||
PKG_CHECK_MODULES(ICU, [icu-uc icu-i18n])
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
AC_SUBST(DBUS_PIM_PLUGIN_CFLAGS)
|
|
||||||
AC_SUBST(DBUS_PIM_PLUGIN_LIBS)
|
|
||||||
AC_SUBST(DBUS_PIM_PLUGIN_LDFLAGS)
|
|
||||||
|
|
||||||
# http://code.google.com/p/libphonenumber/
|
|
||||||
AC_LANG(C++)
|
|
||||||
SAVED_CPPFLAGS=$CPPFLAGS
|
|
||||||
if test ! "$PHONENUMBERS_CFLAGS"; then
|
|
||||||
PHONENUMBERS_CFLAGS=-DI18N_PHONENUMBERS_USE_BOOST
|
|
||||||
fi
|
|
||||||
CPPFLAGS="$CPPFLAGS ${PHONENUMBERS_CFLAGS}"
|
|
||||||
AC_CHECK_HEADERS([phonenumbers/phonenumberutil.h])
|
|
||||||
SAVED_LIBS=$LIBS
|
|
||||||
if test ! "$PHONENUMBERS_LIBS"; then
|
|
||||||
PHONENUMBERS_LIBS=-lphonenumber
|
|
||||||
fi
|
|
||||||
LIBS="$LIBS $PHONENUMBERS_LIBS"
|
|
||||||
AC_LINK_IFELSE(
|
|
||||||
[AC_LANG_PROGRAM([#include <phonenumbers/phonenumberutil.h>],
|
|
||||||
[i18n::phonenumbers::PhoneNumberUtil::GetInstance()])],
|
|
||||||
[true],
|
|
||||||
[AC_ERROR([libphonebook not found, set PHONENUMBERS_CFLAGS and PHONENUMBERS_LIBS.])])
|
|
||||||
AC_SUBST(PHONENUMBERS_CFLAGS)
|
|
||||||
AC_SUBST(PHONENUMBERS_LIBS)
|
|
||||||
LIBS=$SAVED_LIBS
|
|
||||||
CPPFLAGS=$SAVED_CPPFLAGS
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
fi
|
||||||
AM_CONDITIONAL([COND_DBUS_PIM], [test "$enable_dbus_pim" != "no"])
|
|
||||||
|
|
||||||
AC_SUBST(DBUS_CFLAGS)
|
AC_SUBST(DBUS_CFLAGS)
|
||||||
AC_SUBST(DBUS_LIBS)
|
AC_SUBST(DBUS_LIBS)
|
||||||
|
@ -718,14 +664,6 @@ AC_SUBST(GUI_LIBS)
|
||||||
AC_SUBST(GUI_PROGRAMS)
|
AC_SUBST(GUI_PROGRAMS)
|
||||||
AC_SUBST(GUI_DESKTOP_FILES)
|
AC_SUBST(GUI_DESKTOP_FILES)
|
||||||
|
|
||||||
# C++ regular expression support is required often enough to make it
|
|
||||||
# mandatory.
|
|
||||||
PKG_CHECK_MODULES(PCRECPP, libpcrecpp,,
|
|
||||||
AC_CHECK_LIB(pcrecpp,main,
|
|
||||||
AC_SUBST(PCRECPP_LIBS,-lpcrecpp),
|
|
||||||
AC_MSG_ERROR([pcrecpp not found])
|
|
||||||
))
|
|
||||||
|
|
||||||
# need rst2man for man pages
|
# need rst2man for man pages
|
||||||
AC_ARG_WITH(rst2man,
|
AC_ARG_WITH(rst2man,
|
||||||
AS_HELP_STRING([--with-rst2man=<path to reStructuredText to man converter>],
|
AS_HELP_STRING([--with-rst2man=<path to reStructuredText to man converter>],
|
||||||
|
@ -1132,7 +1070,6 @@ echo "libical v1 timezone hack: $enable_icaltz_util"
|
||||||
echo "DBus service: $enable_dbus_service"
|
echo "DBus service: $enable_dbus_service"
|
||||||
echo "org._01.pim support in DBus service: $enable_dbus_pim"
|
echo "org._01.pim support in DBus service: $enable_dbus_pim"
|
||||||
echo "Notifications: $enable_notify"
|
echo "Notifications: $enable_notify"
|
||||||
echo "GIO GDBus: $with_gio_gdbus"
|
|
||||||
echo "GNOME keyring: $enable_gnome_keyring"
|
echo "GNOME keyring: $enable_gnome_keyring"
|
||||||
if test "$enable_gui" = "no"; then
|
if test "$enable_gui" = "no"; then
|
||||||
echo "UI (DBus client): no"
|
echo "UI (DBus client): no"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
syncevolution (1.3.99.7-1) unstable; urgency=high
|
syncevolution (1.3.99.7-1) unstable; urgency=high
|
||||||
|
|
||||||
* Akonadi support for KDE is now enabled. The support for GNOME and KDE
|
Akonadi support for KDE is now enabled. The support for GNOME and KDE
|
||||||
has been split into new packages named syncevolution-libs-gnome and
|
has been split into new packages named syncevolution-libs-gnome and
|
||||||
syncevolution-libs-kde. If you only want to use KDE, you can remove
|
syncevolution-libs-kde. If you only want to use KDE, you can remove
|
||||||
syncevolution-libs-gnome.
|
syncevolution-libs-gnome.
|
||||||
|
@ -9,7 +9,7 @@ syncevolution (1.3.99.7-1) unstable; urgency=high
|
||||||
|
|
||||||
syncevolution (1.2.99.1-1) unstable; urgency=low
|
syncevolution (1.2.99.1-1) unstable; urgency=low
|
||||||
|
|
||||||
* The sync format of existing configurations for Mobical (aka Everdroid)
|
The sync format of existing configurations for Mobical (aka Everdroid)
|
||||||
must be updated manually, because the server has encoding problems when
|
must be updated manually, because the server has encoding problems when
|
||||||
using vCard 3.0 (now the default for Evolution contacts):
|
using vCard 3.0 (now the default for Evolution contacts):
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ syncevolution (1.2.99.1-1) unstable; urgency=low
|
||||||
syncFormat=text/x-vcard \
|
syncFormat=text/x-vcard \
|
||||||
mobical addressbook
|
mobical addressbook
|
||||||
|
|
||||||
* The Funambol template explicitly enables usage of the
|
The Funambol template explicitly enables usage of the
|
||||||
"refresh-from-server" sync mode to avoid getting throttled with 417
|
"refresh-from-server" sync mode to avoid getting throttled with 417
|
||||||
'retry later' errors. The same must be added to existing configs
|
'retry later' errors. The same must be added to existing configs
|
||||||
manually:
|
manually:
|
||||||
|
@ -30,11 +30,11 @@ syncevolution (1.2.99.1-1) unstable; urgency=low
|
||||||
|
|
||||||
syncevolution (1.1.99.5a-1) experimental; urgency=low
|
syncevolution (1.1.99.5a-1) experimental; urgency=low
|
||||||
|
|
||||||
* This version of syncevolution introduces an irreversible change to the
|
This version of syncevolution introduces an irreversible change to the
|
||||||
config layout, see the --migrate option in the syncevolution man page.
|
config layout, see the --migrate option in the syncevolution man page.
|
||||||
Migration happens automatically at first invocation.
|
Migration happens automatically at first invocation.
|
||||||
|
|
||||||
* This version is only know to work with version 2.32.2 of evolution.
|
This version is only know to work with version 2.32.2 of evolution.
|
||||||
In particular, it probably won't work with the version of evolution in
|
In particular, it probably won't work with the version of evolution in
|
||||||
squeeze.
|
squeeze.
|
||||||
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
Building syncevolution for Debian
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
The source package needs no special instructions; the discussion here
|
|
||||||
is about working with the git repository.
|
|
||||||
|
|
||||||
Patches are exported based on debian/source/git-patches; each line is
|
|
||||||
an argument to git-format-patch. The variables $DEB_VERSION and
|
|
||||||
$UPSTREAM_VERSION are the Debian and upstream version being exported.
|
|
||||||
You can either use git-format-patch manually, or install gitpkg
|
|
||||||
version 0.17 or later.
|
|
||||||
|
|
||||||
1) To have the patches automatically exported at source package creation time
|
|
||||||
|
|
||||||
a) to setup gitpkg, run
|
|
||||||
|
|
||||||
% git config gitpkg.deb-export-hook /usr/share/gitpkg/hooks/quilt-patches-deb-export-hook
|
|
||||||
|
|
||||||
b) run
|
|
||||||
|
|
||||||
% gitpkg master
|
|
||||||
|
|
||||||
to make a source package.
|
|
||||||
|
|
||||||
2) To manually export patches, run
|
|
||||||
|
|
||||||
% ./debian/rules export-patches
|
|
||||||
|
|
||||||
The original source tarballs are stored in the git repo using
|
|
||||||
pristine-tar. You can (optionally) check out the current tarball by
|
|
||||||
|
|
||||||
git branch pristine-tar origin/pristine-tar
|
|
||||||
# UPSTREAM should be the current upstream version
|
|
||||||
pristine-tar checkout ../syncevolution_$(UPSTREAM).orig.tar.gz
|
|
||||||
|
|
||||||
-- David Bremner <bremner@debian.org>, Tue, 8 Mar 2011 19:34:24 -0400
|
|
|
@ -1,5 +1,3 @@
|
||||||
|
* add missing manpages for syncompare and syncevo-http-server
|
||||||
- add missing manpages for syncompare and syncevo-http-server
|
* fix FTPFS with g++ 11 without CXXFLAG -std=c++14;
|
||||||
- clean up src/syncevo/CmdLine.cpp(.orig|.rej)
|
see <https://gitlab.freedesktop.org/SyncEvolution/syncevolution/-/issues/167>
|
||||||
|
|
||||||
-- David Bremner <bremner@debian.org>, Thu, 11 Nov 2010 11:48:32 -0400
|
|
||||||
|
|
|
@ -1,3 +1,109 @@
|
||||||
|
syncevolution (2.0.0-2) experimental; urgency=medium
|
||||||
|
|
||||||
|
[ Jonas Smedegaard ]
|
||||||
|
* update copyright info:
|
||||||
|
+ fix consistently use field License-Grant (not Grant)
|
||||||
|
+ fix consistently use field Files (not bogus File)
|
||||||
|
+ fix add License section LGPL-2
|
||||||
|
+ tighten license-related lintian overrides
|
||||||
|
* fix have syncevolution-http depend on python3-gi
|
||||||
|
(not bogus python3-gobject:
|
||||||
|
earlier transitional package python-gobject pulled in python-gi)
|
||||||
|
* fix drop depending on python3-twisted-web:
|
||||||
|
bogus (transitioned to python3-twisted-core)
|
||||||
|
and used only by exerimental unused script
|
||||||
|
* tighten dh-missing to fail (not only warn) on missed files
|
||||||
|
+ list unversioned symlinks to shared objects as not-installed
|
||||||
|
+ list helper scripts for testing as not-installed
|
||||||
|
* fix install XDG startup files in syncevolution-dbus
|
||||||
|
* fix install SRV resolver script in syncevolution-common,
|
||||||
|
recommend adns-utils (or simpler fallbacks),
|
||||||
|
and have syncevolution-libs recommend syncevolution-common
|
||||||
|
* work around FTPFS with g++ 11 by setting CXXFLAG -std=c++14
|
||||||
|
|
||||||
|
[ Joao Azevedo ]
|
||||||
|
* list library syncactivesync.so as not installed
|
||||||
|
(to match upstream intent in unconventional build target)
|
||||||
|
* list TDEPIM libraries as not installed
|
||||||
|
(we no longer link against KDE libraries so unlikely to be useful)
|
||||||
|
* fix install libraries syncpbap providergoa
|
||||||
|
|
||||||
|
-- Jonas Smedegaard <dr@jones.dk> Wed, 03 Nov 2021 15:50:49 +0100
|
||||||
|
|
||||||
|
syncevolution (2.0.0-1) experimental; urgency=medium
|
||||||
|
|
||||||
|
[ upstream ]
|
||||||
|
* new release
|
||||||
|
|
||||||
|
[ Jonas Smedegaard ]
|
||||||
|
* isolate kfreebsd FTBFS fix as patch 1001,
|
||||||
|
and track package source with patches unapplied
|
||||||
|
* add git-buildpackage config:
|
||||||
|
+ use pristine-tar
|
||||||
|
+ sign tags
|
||||||
|
+ avoid any .git* files
|
||||||
|
+ use DEP-14 branches debian/latest upstream/latest
|
||||||
|
+ add usage comment
|
||||||
|
* drop obsolete *-dbg to *-dbgsym migration
|
||||||
|
* simplify rules;
|
||||||
|
stop explicitly build-depend on libtool automake pkg-config
|
||||||
|
(pulled in via autoreconf since debhelper compatibility level 10)
|
||||||
|
* use debhelper compatibility level 13 (not 11);
|
||||||
|
build-depend on debhelper-compat (not debhelper)
|
||||||
|
* relax to stop build-depend explicitly on g++:
|
||||||
|
required version satisfied by default
|
||||||
|
in all supported Debian releases
|
||||||
|
* drop ancient Breaks/Replaces hints
|
||||||
|
* stop link against KDE libraries (no longer supported upstream):
|
||||||
|
+ drop binary package syncevolution-libs-kde
|
||||||
|
+ stop build-depend on kdelibs5-dev kdepimlibs5-dev
|
||||||
|
* stop install library to support ActiveSync
|
||||||
|
(no longer supported upstream)
|
||||||
|
* use Python 3.x libraries:
|
||||||
|
+ build-depend on python3-docutils (not python-docutils)
|
||||||
|
+ have syncevolution-http depend on python3 python3-dbus
|
||||||
|
python3-gobject python3-openssl
|
||||||
|
python3-pygments python3-twisted-web
|
||||||
|
(not python python-dbus python-gobject
|
||||||
|
python-openssl python-twisted-web)
|
||||||
|
* stop build-depend on libpcre3-dev
|
||||||
|
* build-depend on libecal2.0-dev (not libecal1.2-dev)
|
||||||
|
* relax to build-depend unversioned on libsynthesis-dev:
|
||||||
|
required version satisfied in all supported Debian releases
|
||||||
|
* add patch 1002
|
||||||
|
to adjust whitespace as required for recent autotools
|
||||||
|
* fix install all pstream-provided gettext machine-object files
|
||||||
|
* install all upstream-provided README.* files
|
||||||
|
* install more example files
|
||||||
|
* improve install tracking with dh_missing:
|
||||||
|
package upstream-installed manpage (not source file)
|
||||||
|
* explicitly list files deliberately not installed
|
||||||
|
* stop install syncevolution-dbus example file dropped upstream
|
||||||
|
* update install paths
|
||||||
|
|
||||||
|
[ João Azevedo ]
|
||||||
|
* don't use install for syncevo-http-server.py
|
||||||
|
|
||||||
|
-- Jonas Smedegaard <dr@jones.dk> Tue, 05 Oct 2021 17:45:04 +0200
|
||||||
|
|
||||||
|
syncevolution (1.5.3-2) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Remove libgconf2-dev build-dep (Closes: #897258)
|
||||||
|
|
||||||
|
-- Tino Mettler <tino+debian@tikei.de> Thu, 21 Jun 2018 21:19:04 +0200
|
||||||
|
|
||||||
|
syncevolution (1.5.3-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* New upstream release
|
||||||
|
* Fix override_dh_makeshlibs to handle all packages with public shared libs
|
||||||
|
(Closes: #887043)
|
||||||
|
* Remove obsolete Conflicts:/Breaks:/Replaces: sync-ui (<<1.1+ds1-1~)
|
||||||
|
* Change debhelper compatibility to 11, which is recommended
|
||||||
|
* Bump standards version to 4.1.3, no changes needed
|
||||||
|
* Fix several lintian warnings
|
||||||
|
|
||||||
|
-- Tino Mettler <tino+debian@tikei.de> Sat, 13 Jan 2018 22:47:44 +0100
|
||||||
|
|
||||||
syncevolution (1.5.2-3) unstable; urgency=medium
|
syncevolution (1.5.2-3) unstable; urgency=medium
|
||||||
|
|
||||||
[ Patrick Ohly ]
|
[ Patrick Ohly ]
|
||||||
|
@ -7,12 +113,14 @@ syncevolution (1.5.2-3) unstable; urgency=medium
|
||||||
[ Tino Mettler ]
|
[ Tino Mettler ]
|
||||||
* Change build dependencies for libgtk and glade to use GTK3 for sync-ui
|
* Change build dependencies for libgtk and glade to use GTK3 for sync-ui
|
||||||
(Closes: #884162)
|
(Closes: #884162)
|
||||||
* Add Build-Dep on libjson-c-dev (Closes: #884170)
|
* Add Build-Dep on libjson-c-dev, enable and include oauth2 backend
|
||||||
|
(Closes: #884170)
|
||||||
|
|
||||||
* Handle C++ conversion operator name mangling in GCC 7 (Closes: #871284)
|
* Handle C++ conversion operator name mangling in GCC 7 (Closes: #871284)
|
||||||
* Build depend on libsecret-1-dev instead of deprecated libgnome-keyring-dev
|
* Build depend on libsecret-1-dev instead of deprecated libgnome-keyring-dev
|
||||||
(Closes: #867944)
|
(Closes: #867944)
|
||||||
|
|
||||||
-- Tino Mettler <tino+debian@tikei.de> Thu, 04 Jan 2018 12:24:58 +0100
|
-- Tino Mettler <tino+debian@tikei.de> Thu, 04 Jan 2018 22:21:57 +0100
|
||||||
|
|
||||||
syncevolution (1.5.2-2) unstable; urgency=medium
|
syncevolution (1.5.2-2) unstable; urgency=medium
|
||||||
|
|
||||||
|
@ -208,7 +316,7 @@ syncevolution (1.1.99.4+ds1-1) experimental; urgency=low
|
||||||
syncevolution (1.1.99.3+ds1-1) experimental; urgency=low
|
syncevolution (1.1.99.3+ds1-1) experimental; urgency=low
|
||||||
|
|
||||||
* New upstream (pre-release) version
|
* New upstream (pre-release) version
|
||||||
* Remove two s390 related patches, now contained in upstream
|
* Remove two s390 related patches, now contained in upstream
|
||||||
commit 63d76f874270cbafb2.
|
commit 63d76f874270cbafb2.
|
||||||
|
|
||||||
-- David Bremner <bremner@debian.org> Tue, 08 Mar 2011 16:05:30 -0400
|
-- David Bremner <bremner@debian.org> Tue, 08 Mar 2011 16:05:30 -0400
|
||||||
|
@ -224,7 +332,7 @@ syncevolution (1.1+ds1-5) unstable; urgency=low
|
||||||
|
|
||||||
syncevolution (1.1+ds1-4) experimental; urgency=low
|
syncevolution (1.1+ds1-4) experimental; urgency=low
|
||||||
|
|
||||||
* Remove build dependency on libopenobex1-dev on hurd-i386, because it is not
|
* Remove build dependency on libopenobex1-dev on hurd-i386, because it is not
|
||||||
available there. The package is already built without it on kfreebsd.
|
available there. The package is already built without it on kfreebsd.
|
||||||
* Explicitly translate between sysync::memSize and size_t. Thanks to
|
* Explicitly translate between sysync::memSize and size_t. Thanks to
|
||||||
Patrick Ohly for the patch.
|
Patrick Ohly for the patch.
|
||||||
|
@ -254,7 +362,7 @@ syncevolution (1.1+ds1-1) experimental; urgency=low
|
||||||
* Add -dbg package to hold debugging symbols
|
* Add -dbg package to hold debugging symbols
|
||||||
* Recommend evolution-data-server instead of evolution
|
* Recommend evolution-data-server instead of evolution
|
||||||
* Update Standards-Version to 3.9.1 (No changes).
|
* Update Standards-Version to 3.9.1 (No changes).
|
||||||
|
|
||||||
[ Thomas Bechtold ]
|
[ Thomas Bechtold ]
|
||||||
* Split source package into syncevolution-common, syncevolution and
|
* Split source package into syncevolution-common, syncevolution and
|
||||||
sync-ui.
|
sync-ui.
|
||||||
|
@ -276,7 +384,7 @@ syncevolution (1.0+ds1~beta2a-1) unstable; urgency=low
|
||||||
syncevolution (1.0+ds1~a1-2) experimental; urgency=low
|
syncevolution (1.0+ds1~a1-2) experimental; urgency=low
|
||||||
|
|
||||||
* Don't build depend on libopenobex1-dev on kfreebsd-*. This avoids
|
* Don't build depend on libopenobex1-dev on kfreebsd-*. This avoids
|
||||||
trying to compile bluetooth support, which relies on bluez
|
trying to compile bluetooth support, which relies on bluez
|
||||||
(Closes: #566940)
|
(Closes: #566940)
|
||||||
|
|
||||||
-- David Bremner <bremner@unb.ca> Tue, 26 Jan 2010 23:28:44 -0400
|
-- David Bremner <bremner@unb.ca> Tue, 26 Jan 2010 23:28:44 -0400
|
||||||
|
@ -304,6 +412,6 @@ syncevolution (0.9+ds1-2) unstable; urgency=low
|
||||||
|
|
||||||
syncevolution (0.9+ds1-1) unstable; urgency=low
|
syncevolution (0.9+ds1-1) unstable; urgency=low
|
||||||
|
|
||||||
* Initial release (Closes: #404942)
|
* Initial release (Closes: #404942)
|
||||||
|
|
||||||
-- David Bremner <bremner@unb.ca> Sun, 16 Aug 2009 23:53:47 -0300
|
-- David Bremner <bremner@unb.ca> Sun, 16 Aug 2009 23:53:47 -0300
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
Makefile.in
|
|
||||||
aclocal.m4
|
|
||||||
config.guess
|
|
||||||
config.h.in
|
|
||||||
config.sub
|
|
||||||
configure
|
|
||||||
configure.in
|
|
||||||
depcomp
|
|
||||||
install-sh
|
|
||||||
intltool-extract.in
|
|
||||||
intltool-merge.in
|
|
||||||
intltool-update.in
|
|
||||||
ltmain.sh
|
|
||||||
m4/intltool.m4
|
|
||||||
m4/libtool.m4
|
|
||||||
m4/ltoptions.m4
|
|
||||||
m4/ltsugar.m4
|
|
||||||
m4/ltversion.m4
|
|
||||||
m4/lt~obsolete.m4
|
|
||||||
missing
|
|
||||||
mkinstalldirs
|
|
||||||
po/Makefile.in.in
|
|
||||||
src/Makefile.am
|
|
||||||
src/Makefile.in
|
|
||||||
src/backends/addressbook/Makefile.in
|
|
||||||
src/backends/evolution/Makefile.in
|
|
||||||
src/backends/file/Makefile.in
|
|
||||||
src/backends/sqlite/Makefile.in
|
|
||||||
src/core/Makefile.in
|
|
||||||
src/dbus/Makefile.in
|
|
||||||
src/dbus/interfaces/Makefile.in
|
|
||||||
src/gtk-ui/Makefile.in
|
|
||||||
test/Makefile.in
|
|
|
@ -1 +0,0 @@
|
||||||
9
|
|
|
@ -1,32 +1,46 @@
|
||||||
Source: syncevolution
|
Source: syncevolution
|
||||||
Section: utils
|
Section: utils
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Maintainer: Tino Mettler <tino+debian@tikei.de>
|
Maintainer: Jonas Smedegaard <dr@jones.dk>
|
||||||
Build-Depends: debhelper (>= 9), autotools-dev, libedataserver1.2-dev,
|
Build-Depends:
|
||||||
libecal1.2-dev, libebook1.2-dev, libcurl4-gnutls-dev, libboost-dev,
|
debhelper-compat (= 13),
|
||||||
libsynthesis-dev (>=3.4.0.47.5),
|
intltool,
|
||||||
libtool, automake, intltool, pkg-config,
|
libboost-dev,
|
||||||
libglib2.0-dev, libgladeui-dev, libdbus-glib-1-dev, libgtk-3-dev,
|
libcppunit-dev,
|
||||||
libgconf2-dev,
|
libcurl4-gnutls-dev,
|
||||||
libsecret-1-dev,
|
libdbus-glib-1-dev,
|
||||||
xsltproc,
|
libebook1.2-dev,
|
||||||
libopenobex2-dev [linux-any], libnotify-dev,
|
libecal2.0-dev,
|
||||||
python-docutils, libical-dev, libneon27-gnutls-dev, libpcre3-dev,
|
libedataserver1.2-dev,
|
||||||
libcppunit-dev, kdepimlibs5-dev, kdelibs5-dev,
|
libgladeui-dev,
|
||||||
|
libglib2.0-dev,
|
||||||
|
libgtk-3-dev,
|
||||||
|
libical-dev,
|
||||||
libjson-c-dev,
|
libjson-c-dev,
|
||||||
g++ (>= 4:7)
|
libneon27-gnutls-dev,
|
||||||
Standards-Version: 3.9.8
|
libnotify-dev,
|
||||||
Homepage: http://www.syncevolution.org
|
libopenobex2-dev [linux-any],
|
||||||
Vcs-Git: git://anonscm.debian.org/collab-maint/syncevolution
|
libsecret-1-dev,
|
||||||
Vcs-Browser: https://anonscm.debian.org/cgit/collab-maint/syncevolution.git
|
libsynthesis-dev,
|
||||||
|
python3-docutils,
|
||||||
|
python3-pygments,
|
||||||
|
xsltproc,
|
||||||
|
Standards-Version: 4.6.0
|
||||||
|
Homepage: https://www.syncevolution.org/
|
||||||
|
Vcs-Git: https://salsa.debian.org/debian/syncevolution.git
|
||||||
|
Vcs-Browser: https://salsa.debian.org/debian/syncevolution
|
||||||
|
Rules-Requires-Root: no
|
||||||
|
|
||||||
Package: syncevolution
|
Package: syncevolution
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends},
|
Depends:
|
||||||
syncevolution-common (= ${source:Version}),
|
syncevolution-common (= ${source:Version}),
|
||||||
syncevolution-libs (= ${binary:Version})
|
syncevolution-libs (= ${binary:Version}),
|
||||||
Recommends: bluez
|
${misc:Depends},
|
||||||
Description: Sync personal information data using SyncML and CalDAV/CardDAV (CLI)
|
${shlibs:Depends},
|
||||||
|
Recommends:
|
||||||
|
bluez,
|
||||||
|
Description: Sync personal information data via SyncML/CalDAV/CardDAV (CLI)
|
||||||
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
||||||
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
||||||
to sync PIM data in Evolution, but a plain file storage is also supported.
|
to sync PIM data in Evolution, but a plain file storage is also supported.
|
||||||
|
@ -38,10 +52,14 @@ Description: Sync personal information data using SyncML and CalDAV/CardDAV (CLI
|
||||||
|
|
||||||
Package: sync-ui
|
Package: sync-ui
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, syncevolution-common (= ${source:Version}),
|
Depends:
|
||||||
syncevolution-dbus
|
syncevolution-common (= ${source:Version}),
|
||||||
Recommends: bluez
|
syncevolution-dbus,
|
||||||
Description: Sync personal information data using SyncML and CalDAV/CardDAV (GTK+ GUI)
|
${misc:Depends},
|
||||||
|
${shlibs:Depends},
|
||||||
|
Recommends:
|
||||||
|
bluez,
|
||||||
|
Description: Sync personal information data via SyncML/CalDAV/CardDAV (GTK+ GUI)
|
||||||
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
||||||
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
||||||
to sync PIM data in Evolution, but a plain file storage is also supported.
|
to sync PIM data in Evolution, but a plain file storage is also supported.
|
||||||
|
@ -53,10 +71,12 @@ Description: Sync personal information data using SyncML and CalDAV/CardDAV (GTK
|
||||||
|
|
||||||
Package: syncevolution-common
|
Package: syncevolution-common
|
||||||
Architecture: all
|
Architecture: all
|
||||||
Depends: ${misc:Depends}, libsynthesis0v5 (>= 3.4.0.47.5)
|
Depends:
|
||||||
Conflicts: sync-ui (<<1.1+ds1-1~), syncevolution (<<1.1+ds1-1~)
|
libsynthesis0v5 (>= 3.4.0.47.5),
|
||||||
Replaces: sync-ui (<<1.1+ds1-1~), syncevolution (<<1.1+ds1-1~)
|
${misc:Depends},
|
||||||
Description: Sync personal information data using SyncML and CalDAV/CardDAV (common files)
|
Recommends:
|
||||||
|
adns-tools | host | dnsutils,
|
||||||
|
Description: Sync personal information data via SyncML/CalDAV/CardDAV (common files)
|
||||||
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
||||||
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
||||||
to sync PIM data in Evolution, but a plain file storage is also supported.
|
to sync PIM data in Evolution, but a plain file storage is also supported.
|
||||||
|
@ -68,10 +88,13 @@ Description: Sync personal information data using SyncML and CalDAV/CardDAV (com
|
||||||
|
|
||||||
Package: syncevolution-libs
|
Package: syncevolution-libs
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: syncevolution-libs-gnome (= ${binary:Version}) |
|
Depends:
|
||||||
syncevolution-libs-kde (= ${binary:Version}),
|
syncevolution-libs-gnome (= ${binary:Version}),
|
||||||
${misc:Depends}, ${shlibs:Depends}
|
${misc:Depends},
|
||||||
Description: Sync personal information data using SyncML and CalDAV/CardDAV (backend libraries)
|
${shlibs:Depends},
|
||||||
|
Recommends:
|
||||||
|
syncevolution-common (= ${source:Version}),
|
||||||
|
Description: Sync personal information data via SyncML/CalDAV/CardDAV (backend libraries)
|
||||||
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
||||||
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
||||||
to sync PIM data in Evolution, but a plain file storage is also supported.
|
to sync PIM data in Evolution, but a plain file storage is also supported.
|
||||||
|
@ -83,11 +106,12 @@ Description: Sync personal information data using SyncML and CalDAV/CardDAV (bac
|
||||||
|
|
||||||
Package: syncevolution-libs-gnome
|
Package: syncevolution-libs-gnome
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${misc:Depends}, ${shlibs:Depends}
|
Depends:
|
||||||
Recommends: evolution-data-server
|
${misc:Depends},
|
||||||
Replaces: syncevolution-libs (<< 1.3.99.7)
|
${shlibs:Depends},
|
||||||
Breaks: syncevolution-libs (<< 1.3.99.7)
|
Recommends:
|
||||||
Description: Sync personal information data using SyncML and CalDAV/CardDAV (GNOME backend)
|
evolution-data-server,
|
||||||
|
Description: Sync personal information data via SyncML/CalDAV/CardDAV (GNOME backend)
|
||||||
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
||||||
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
||||||
to sync PIM data in Evolution, but a plain file storage is also supported.
|
to sync PIM data in Evolution, but a plain file storage is also supported.
|
||||||
|
@ -95,31 +119,17 @@ Description: Sync personal information data using SyncML and CalDAV/CardDAV (GNO
|
||||||
incremental synchronization of items are supported. SyncEvolution can act as
|
incremental synchronization of items are supported. SyncEvolution can act as
|
||||||
a SyncML/DAV client and SyncML server.
|
a SyncML/DAV client and SyncML server.
|
||||||
.
|
.
|
||||||
This package provides private libraries and plugins for Gnome.
|
This package provides private libraries and plugins for GNOME.
|
||||||
|
|
||||||
Package: syncevolution-libs-kde
|
|
||||||
Architecture: any
|
|
||||||
Depends: ${misc:Depends}, ${shlibs:Depends}
|
|
||||||
Replaces: syncevolution-libs (<< 1.3.99.7)
|
|
||||||
Breaks: syncevolution-libs (<< 1.3.99.7)
|
|
||||||
Description: Sync personal information data using SyncML and CalDAV/CardDAV (KDE backend)
|
|
||||||
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
|
||||||
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
|
||||||
to sync PIM data in Evolution, but a plain file storage is also supported.
|
|
||||||
Data exchange can happen via HTTP(S) and Bluetooth. Full, one-way and
|
|
||||||
incremental synchronization of items are supported. SyncEvolution can act as
|
|
||||||
a SyncML/DAV client and SyncML server.
|
|
||||||
.
|
|
||||||
This package provides private libraries and plugins for KDE.
|
|
||||||
|
|
||||||
Package: syncevolution-dbus
|
Package: syncevolution-dbus
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends},
|
Depends:
|
||||||
syncevolution-common (= ${source:Version}),
|
dbus,
|
||||||
syncevolution-libs (= ${binary:Version}), dbus
|
syncevolution-common (= ${source:Version}),
|
||||||
Replaces: sync-ui (<< 1.1+ds1-1)
|
syncevolution-libs (= ${binary:Version}),
|
||||||
Breaks: sync-ui (<< 1.1+ds1-1)
|
${misc:Depends},
|
||||||
Description: Sync personal information data using SyncML and CalDAV/CardDAV (D-Bus support)
|
${shlibs:Depends},
|
||||||
|
Description: Sync personal information data via SyncML/CalDAV/CardDAV (D-Bus support)
|
||||||
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
||||||
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
||||||
to sync PIM data in Evolution, but a plain file storage is also supported.
|
to sync PIM data in Evolution, but a plain file storage is also supported.
|
||||||
|
@ -131,9 +141,15 @@ Description: Sync personal information data using SyncML and CalDAV/CardDAV (D-B
|
||||||
|
|
||||||
Package: syncevolution-http
|
Package: syncevolution-http
|
||||||
Architecture: all
|
Architecture: all
|
||||||
Depends: ${misc:Depends}, syncevolution-dbus (>= ${source:Version}), python,
|
Depends:
|
||||||
python-dbus, dbus-x11, python-twisted-web, python-gobject, python-openssl
|
dbus-x11,
|
||||||
Description: Sync personal information data using SyncML and CalDAV/CardDAV (HTTP server)
|
python3,
|
||||||
|
python3-dbus,
|
||||||
|
python3-gi,
|
||||||
|
python3-openssl,
|
||||||
|
syncevolution-dbus (>= ${source:Version}),
|
||||||
|
${misc:Depends},
|
||||||
|
Description: Sync personal information data via SyncML/CalDAV/CardDAV (HTTP server)
|
||||||
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
||||||
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
||||||
to sync PIM data in Evolution, but a plain file storage is also supported.
|
to sync PIM data in Evolution, but a plain file storage is also supported.
|
||||||
|
@ -146,8 +162,12 @@ Description: Sync personal information data using SyncML and CalDAV/CardDAV (HTT
|
||||||
|
|
||||||
Package: libsyncevolution0
|
Package: libsyncevolution0
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, syncevolution-common (= ${source:Version}), dbus
|
Depends:
|
||||||
Description: Sync personal information data using SyncML and CalDAV/CardDAV (shared library)
|
dbus,
|
||||||
|
syncevolution-common (= ${source:Version}),
|
||||||
|
${misc:Depends},
|
||||||
|
${shlibs:Depends},
|
||||||
|
Description: Sync personal information data via SyncML/CalDAV/CardDAV (shared library)
|
||||||
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
||||||
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
||||||
to sync PIM data in Evolution, but a plain file storage is also supported.
|
to sync PIM data in Evolution, but a plain file storage is also supported.
|
||||||
|
@ -159,8 +179,12 @@ Description: Sync personal information data using SyncML and CalDAV/CardDAV (sha
|
||||||
|
|
||||||
Package: libsyncevo-dbus0
|
Package: libsyncevo-dbus0
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, syncevolution-common (= ${source:Version}), dbus
|
Depends:
|
||||||
Description: Sync personal information data using SyncML and CalDAV/CardDAV (shared D-Bus library)
|
dbus,
|
||||||
|
syncevolution-common (= ${source:Version}),
|
||||||
|
${misc:Depends},
|
||||||
|
${shlibs:Depends},
|
||||||
|
Description: Sync personal information data via SyncML/CalDAV/CardDAV (shared D-Bus library)
|
||||||
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
||||||
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
||||||
to sync PIM data in Evolution, but a plain file storage is also supported.
|
to sync PIM data in Evolution, but a plain file storage is also supported.
|
||||||
|
@ -172,10 +196,12 @@ Description: Sync personal information data using SyncML and CalDAV/CardDAV (sha
|
||||||
|
|
||||||
Package: libgdbussyncevo0
|
Package: libgdbussyncevo0
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, syncevolution-common (= ${source:Version}), dbus
|
Depends:
|
||||||
Replaces: syncevolution-libs (<< 1.2.99.1)
|
dbus,
|
||||||
Breaks: syncevolution-libs (<< 1.2.99.1)
|
syncevolution-common (= ${source:Version}),
|
||||||
Description: Sync personal information data using SyncML and CalDAV/CardDAV (shared gdbus library)
|
${misc:Depends},
|
||||||
|
${shlibs:Depends},
|
||||||
|
Description: Sync personal information data via SyncML/CalDAV/CardDAV (shared gdbus library)
|
||||||
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
SyncEvolution synchronizes contact, calendar and task items via SyncML and
|
||||||
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
CalDAV/CardDAV with other servers or devices. It uses the Evolution Data Server
|
||||||
to sync PIM data in Evolution, but a plain file storage is also supported.
|
to sync PIM data in Evolution, but a plain file storage is also supported.
|
||||||
|
|
|
@ -1,174 +1,280 @@
|
||||||
Source: http://downloads.syncevolution.org/syncevolution/sources/
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
git://git.moblin.org/syncevolution
|
Upstream-Name: SyncEvolution
|
||||||
|
Upstream-Contact: https://gitlab.freedesktop.org/SyncEvolution/syncevolution/-/issues
|
||||||
Currently the tarball is built from a tag in the moblin repo to avoid the
|
Source: https://gitlab.freedesktop.org/SyncEvolution/syncevolution/
|
||||||
embedded copy of libsynthesis. For details, see the get-orig-source rule
|
|
||||||
in debian/rules.
|
|
||||||
|
|
||||||
Files: *
|
Files: *
|
||||||
Copyright: © 2005-2009 Patrick Ohly <patrick.ohly@gmx.de>
|
Copyright:
|
||||||
License: LGPL2.1 | LGPL3
|
2012 BMW Car IT GmbH.
|
||||||
|
2016 Emanoil Kotsev <emanoil.kotsev@fincom.at>
|
||||||
|
2008 Funambol, Inc.
|
||||||
|
2009, 2011-2012 Intel Corporation
|
||||||
|
2009 m-otion communications GmbH <knipp@m-otion.com>
|
||||||
|
2005-2009 Patrick Ohly <patrick.ohly@gmx.de>
|
||||||
|
2011 Symbio, Ville Nummela
|
||||||
|
2004-2008 Synthesis AG
|
||||||
|
License-Grant:
|
||||||
|
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.
|
||||||
|
License: LGPL-2.1 or LGPL-3
|
||||||
|
Comment:
|
||||||
|
Files below <src/backends/webdav/*> lack licensing.
|
||||||
|
Licensing of those files is assumed same as generally for the project.
|
||||||
|
|
||||||
File: test/client-test.cpp
|
Files:
|
||||||
Copyright: © 2008-2009 Patrick Ohly <patrick.ohly@gmx.de>
|
build/xsl/*
|
||||||
© 2008 Funambol, Inc
|
Copyright:
|
||||||
License: LGPL2.1 | LGPL3
|
2003 Jiří Kosek
|
||||||
|
1999-2007 Norman Walsh
|
||||||
|
2011-2012 O'Reilly Media
|
||||||
|
2004-2007 Steve Ball
|
||||||
|
2005-2008 The DocBook Project
|
||||||
|
License: Expat~Docbook
|
||||||
|
Reference: build/xsl/COPYING
|
||||||
|
|
||||||
Files: src/core/LogRedirect.h src/core/SoupTransportAgent.cpp
|
Files: m4-repo/*.m4
|
||||||
src/core/TransportAgent.cpp src/core/TransportAgent.h
|
Copyright:
|
||||||
src/core/SynthesisEngine.cpp src/DBusSyncClient.cpp
|
2008 Benjamin Kosnik <bkoz@redhat.com>
|
||||||
src/syncevo-dbus-server.cpp src/core/CurlTransportAgent.h
|
2014-2015 Google Inc.
|
||||||
src/core/SoupTransportAgent.h src/core/CurlTransportAgent.cpp
|
2008 John Darrington <j.darrington@elvis.murdoch.edu.au>
|
||||||
src/DBusSyncClient.h src/syncevo-dbus-server.h src/dbus/* src/gtk-ui/*
|
2016 Krzesimir Nowak <qdlacz@gmail.com>
|
||||||
test/test.cpp
|
2015 Moritz Klammler <moritz@klammler.eu>
|
||||||
Copyright: © 2009 Intel Corporation
|
2015 Paul Norman <penorman@mac.com>
|
||||||
License: LGPL2.1 | LGPL3
|
2009 Peter Adolphs
|
||||||
|
2013 Roy Stogner <roystgnr@ices.utexas.edu>
|
||||||
|
2008 Thomas Porschberg <thomas@randspringer.de>
|
||||||
|
2012 Xiyue Deng <manphiz@gmail.com>
|
||||||
|
2012 Zack Weinberg <zackw@panix.com>
|
||||||
|
License: FSFAP
|
||||||
|
|
||||||
Files: src/backends/addressbook/AddressBookSource.cpp
|
Files:
|
||||||
src/backends/file/FileSyncSource.cpp src/core/EvolutionSyncSource.cpp
|
src/backends/akonadi/akonadisyncsource.cpp
|
||||||
src/client-test-app.cpp src/syncevolution.cpp
|
src/backends/akonadi/akonadisyncsource.h
|
||||||
src/core/EvolutionSyncClient.cpp src/core/EvolutionSmartPtr.h
|
src/backends/akonadi/contactssyncsource.cpp
|
||||||
src/core/EvolutionSyncClient.h src/core/EvolutionSyncSource.h
|
src/backends/akonadi/contactssyncsource.h
|
||||||
src/backends/evolution/EvolutionContactSource.h
|
src/backends/akonadi/eventssyncsource.cpp
|
||||||
src/backends/evolution/EvolutionContactSource.cpp
|
src/backends/akonadi/eventssyncsource.h
|
||||||
src/backends/evolution/EvolutionCalendarSource.cpp
|
src/backends/akonadi/notessyncsource.cpp
|
||||||
src/backends/evolution/EvolutionCalendarSource.h
|
src/backends/akonadi/notessyncsource.h
|
||||||
src/backends/evolution/EvolutionMemoSource.cpp
|
src/backends/akonadi/todossyncsource.cpp
|
||||||
src/backends/sqlite/SQLiteContactSource.cpp src/core/SynthesisEngine.h
|
src/backends/akonadi/todossyncsource.h
|
||||||
src/core/SyncEvolutionCmdline.cpp src/core/TrackingSyncSource.cpp
|
Copyright:
|
||||||
src/core/SyncEvolutionUtil.cpp src/core/FileConfigNode.cpp
|
2009 Sascha Peilicke <sasch.pe@gmx.de>
|
||||||
src/core/SyncEvolutionUtil.h src/core/SyncEvolutionConfig.cpp
|
License-Grant:
|
||||||
src/core/TrackingSyncSource.h src/core/SyncEvolutionConfig.h
|
This application is free software;
|
||||||
src/core/SyncML.h src/core/Logging.cpp src/core/LogStdout.h
|
you can redistribute it and/or modify it
|
||||||
src/core/Logging.h src/core/LogStdout.cpp src/core/SyncML.cpp
|
under the terms of the GNU Library General Public License
|
||||||
src/core/LogRedirect.cpp
|
as published by the Free Software Foundation;
|
||||||
Copyright: © 2009 Intel Corporation
|
either version 2 of the License, or (at your option) any later version.
|
||||||
© 2005-2009 Patrick Ohly <patrick.ohly@gmx.de>
|
|
||||||
License: LGPL2.1 | LGPL3
|
|
||||||
|
|
||||||
License: LGPL2.1 | LGPL3
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
Files: test/{ClientTest.cpp,ClientTest.h}
|
|
||||||
test/client-test-main.cpp
|
|
||||||
test/{test.h synccompare.pl}
|
|
||||||
Copyright: © 2008-2009 Patrick Ohly
|
|
||||||
© 2009 Intel Corporation
|
|
||||||
© 2008 Funambol Inc.
|
|
||||||
License: LGPL2.1 | LGPL3
|
|
||||||
They were contributed to the Funambol C++ client library under the
|
|
||||||
"docs/Sync4jContribution.pdf" agreement. They were maintained there by
|
|
||||||
Patrick and on February 17th 2009 copied back to SyncEvolution,
|
|
||||||
without any commits by other authors except for the license and
|
|
||||||
copyright changes applied by Funambol.
|
|
||||||
|
|
||||||
On March 25 2009 they were relicensed by Patrick Ohly, executing
|
|
||||||
the rights granted by the contributor agreement.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
|
|
||||||
This program 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 program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
|
||||||
more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License along with
|
|
||||||
this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
Files: test/Algorith/Diff.pm
|
|
||||||
Copyright:© 2000-2004 Ned Konz, Tye McQueen.
|
|
||||||
License: GPL-1+ | Artistic
|
|
||||||
This program is free software; you can redistribute it and/or modify it
|
|
||||||
under the same terms as Perl.
|
|
||||||
|
|
||||||
File: src/core/SynthesisDBPlugin.cpp
|
|
||||||
Copyright: © 2009 Intel Corporation
|
|
||||||
© 2004-2008 by Synthesis AG
|
|
||||||
License: LGPL2.1 | LGPL3
|
|
||||||
|
|
||||||
File: src/backends/evolution/e-cal-check-timezones.c
|
|
||||||
src/backends/evolution/e-cal-check-timezones.h
|
|
||||||
Copyright: © 2008 Novell, Inc
|
|
||||||
© 2009 Patrick Ohly <patrick.ohly@gmx.de>
|
|
||||||
License: LGPL-2+
|
License: LGPL-2+
|
||||||
This program 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 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Files:
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
test/Algorith/Diff.pm
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
Copyright:
|
||||||
Lesser General Public License for more details.
|
2000-2004 Ned Konz
|
||||||
|
2000-2004 Tye McQueen
|
||||||
|
License-Grant:
|
||||||
|
This program is free software;
|
||||||
|
you can redistribute it and/or modify it
|
||||||
|
under the same terms as Perl.
|
||||||
|
License: Artistic or GPL-1+
|
||||||
|
Comment:
|
||||||
|
Perl 5 is licensed under either the Artistic license
|
||||||
|
or the GNU General Public License version 1 or later.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
Files:
|
||||||
License along with this program; if not, write to the Free
|
src/syncevo/icaltz-util.c
|
||||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
src/syncevo/icaltz-util.h
|
||||||
Boston, MA 02110-1301, USA.
|
Copyright:
|
||||||
|
2007 Novell, Inc.
|
||||||
|
License-Grant:
|
||||||
|
This program is free software;
|
||||||
|
you can redistribute it and/or modify it
|
||||||
|
under the terms of version 2
|
||||||
|
of the GNU Lesser General Public License
|
||||||
|
as published by the Free Software Foundation.
|
||||||
|
License: LGPL-2
|
||||||
|
|
||||||
Foile: build/gen-changelog.pl
|
Files:
|
||||||
Copyright: © 2009 Emmanuele Bassi
|
src/gtk-ui/gtkinfobar.c
|
||||||
License: GPL1+|Artistic
|
src/gtk-ui/gtkinfobar.h
|
||||||
This program is free software. It can be distributed and/or modified under
|
Copyright:
|
||||||
the terms of Perl itself.
|
2005 Paolo Maggi
|
||||||
|
License-Grant:
|
||||||
|
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 of the License, or (at your option) any later version.
|
||||||
|
License: LGPL-2+
|
||||||
|
|
||||||
Files: debian/*
|
Files:
|
||||||
Copyright: © 2009 David Bremner
|
src/backends/tdepim/TDEPIMSyncSource.cpp
|
||||||
License: same as upstream, LGPL2.1 or LGPL3
|
src/backends/tdepim/TDEPIMSyncSource.h
|
||||||
|
Copyright:
|
||||||
|
2016 Emanoil Kotsev <emanoil.kotsev@fincom.at>
|
||||||
|
License-Grant:
|
||||||
|
This application is free software;
|
||||||
|
you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Library General Public License
|
||||||
|
as published by the Free Software Foundation;
|
||||||
|
either version 2 of the License, or (at your option) any later version.
|
||||||
|
License: LGPL-2+
|
||||||
|
|
||||||
|
Files:
|
||||||
|
src/backends/evolution/e-cal-check-timezones.c
|
||||||
|
src/backends/evolution/e-cal-check-timezones.h
|
||||||
|
Copyright:
|
||||||
|
2008 Novell, Inc
|
||||||
|
2009 Patrick Ohly <patrick.ohly@gmx.de>
|
||||||
|
License-Grant:
|
||||||
|
This program 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 of the License, or (at your option) any later version.
|
||||||
|
License: LGPL-2+
|
||||||
|
Comment:
|
||||||
|
The granted license does not exist at described version.
|
||||||
|
Licensing assumed to be GNU Library General Public License 2.0 or newer.
|
||||||
|
|
||||||
Files: src/gdbus/test/example.cpp
|
Files: src/dbus/interfaces/spec-to-docbook.xsl
|
||||||
Copyright: © 2009 Intel Corporation
|
Copyright: 2007, William Jon McCann
|
||||||
License: GPL-2
|
License-Grant:
|
||||||
This program is free software; you can redistribute it and/or modify
|
License: GPL
|
||||||
it under the terms of the GNU General Public License version 2 as
|
License: GPL-1+
|
||||||
published by the Free Software Foundation.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Files:
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
m4-repo/dk-warn.m4
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Copyright:
|
||||||
GNU General Public License for more details.
|
2004-2007 Daniel Elstner <daniel.kitta@gmail.com>
|
||||||
|
License-Grant:
|
||||||
|
danielk's Autostuff is free software;
|
||||||
|
you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation;
|
||||||
|
either version 2 of the License, or (at your option) any later version.
|
||||||
|
License: GPL-2+
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
Files:
|
||||||
along with this program; if not, write to the Free Software
|
m4-repo/autotroll.m4
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
autotroll.am
|
||||||
|
Copyright:
|
||||||
|
2006-2007, 2009-2010 Benoit Sigoure <benoit.sigoure@lrde.epita.fr>
|
||||||
|
License-Grant:
|
||||||
|
AutoTroll is free software;
|
||||||
|
you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation;
|
||||||
|
either version 2 of the License, or (at your option) any later version.
|
||||||
|
License: GPL-2+ with Autoconf-2.0~AutoTroll exception
|
||||||
|
In addition, as a special exception,
|
||||||
|
the copyright holders of AutoTroll give you unlimited permission
|
||||||
|
to copy, distribute and modify the configure scripts
|
||||||
|
that are the output of Autoconf
|
||||||
|
when processing the macros of AutoTroll.
|
||||||
|
You need not follow the terms of the GNU General Public License
|
||||||
|
when using or distributing such scripts,
|
||||||
|
even though portions of the text of AutoTroll appear in them.
|
||||||
|
The GNU General Public License (GPL) does govern
|
||||||
|
all other use of the material that constitutes AutoTroll.
|
||||||
|
.
|
||||||
|
This special exception to the GPL applies
|
||||||
|
to versions of AutoTroll released
|
||||||
|
by the copyright holders of AutoTroll.
|
||||||
|
Note that people who make
|
||||||
|
modified versions of AutoTroll are not obligated
|
||||||
|
to grant this special exception for their modified versions;
|
||||||
|
it is their choice whether to do so.
|
||||||
|
The GNU General Public License gives permission
|
||||||
|
to release a modified version without this exception;
|
||||||
|
this exception also makes it possible to release
|
||||||
|
a modified version which carries forward this exception.
|
||||||
|
|
||||||
Files: src/gdbusxx/test/example.cpp
|
Files:
|
||||||
Copyright: © 2009 Intel Corporation
|
build/gen-changelog.pl
|
||||||
License: GPL-2
|
Copyright:
|
||||||
This program is free software; you can redistribute it and/or modify
|
2009 Emmanuele Bassi <ebassi@gnome.org>
|
||||||
it under the terms of the GNU General Public License version 2 as
|
License-Grant:
|
||||||
published by the Free Software Foundation.
|
This program is free software.
|
||||||
|
It can be distributed and/or modified
|
||||||
|
under the terms of Perl itself.
|
||||||
|
License: GPL-1+ or Artistic
|
||||||
|
Comment:
|
||||||
|
Perl 5 is licensed under either the Artistic license
|
||||||
|
or the GNU General Public License version 1 or later.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Files:
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
debian/*
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Copyright:
|
||||||
GNU General Public License for more details.
|
2009 David Bremner
|
||||||
|
2021 Jonas Smedegaard <dr@jones.dk>
|
||||||
|
License-Grant:
|
||||||
|
This packaging is free software;
|
||||||
|
you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation;
|
||||||
|
version 3.
|
||||||
|
License: GPL-3
|
||||||
|
Reference: debian/copyright
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
License: Artistic
|
||||||
along with this program; if not, write to the Free Software
|
Reference: /usr/share/common-licenses/Artistic
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
On Debian systems, you can find the full license text for the LGPL2.1, LGPL3,
|
License: Expat~Docbook
|
||||||
GPL-2, GPL3 and Artistic Licenses at
|
Permission is hereby granted, free of charge,
|
||||||
/usr/share/common-licenses/{LGPL-2.1,LGPL-3,GPL-2,GPL-3,Artistic}
|
to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction,
|
||||||
|
including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software,
|
||||||
|
and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
.
|
||||||
|
The above copyright notice and this permission notice
|
||||||
|
shall be included in all copies or substantial portions of the Software.
|
||||||
|
.
|
||||||
|
Except as contained in this notice,
|
||||||
|
the names of individuals credited with contribution to this software
|
||||||
|
shall not be used in advertising or otherwise
|
||||||
|
to promote the sale, use or other dealings in this Software
|
||||||
|
without prior written authorization from the individuals in question.
|
||||||
|
.
|
||||||
|
Any stylesheet derived from this Software
|
||||||
|
that is publically distributed
|
||||||
|
will be identified with a different name
|
||||||
|
and the version strings in any derived Software will be changed
|
||||||
|
so that no possibility of confusion
|
||||||
|
between the derived package and this Software will exist.
|
||||||
|
|
||||||
|
License: FSFAP
|
||||||
|
Copying and distribution of this file,
|
||||||
|
with or without modification,
|
||||||
|
are permitted in any medium without royalty
|
||||||
|
provided the copyright notice and this notice are preserved
|
||||||
|
This file is offered as-is, without any warranty.
|
||||||
|
|
||||||
|
License: GPL-1+
|
||||||
|
Reference: /usr/share/common-licenses/GPL-1
|
||||||
|
|
||||||
|
License: GPL-2+
|
||||||
|
Reference: /usr/share/common-licenses/GPL-2
|
||||||
|
|
||||||
|
License: GPL-3
|
||||||
|
Reference: /usr/share/common-licenses/GPL-3
|
||||||
|
|
||||||
|
License: LGPL-2
|
||||||
|
Reference: /usr/share/common-licenses/LGPL-2
|
||||||
|
|
||||||
|
License: LGPL-2+
|
||||||
|
Reference: /usr/share/common-licenses/LGPL-2
|
||||||
|
|
||||||
|
License: LGPL-2.1
|
||||||
|
Reference: /usr/share/common-licenses/LGPL-2.1
|
||||||
|
|
||||||
|
License: LGPL-3
|
||||||
|
Reference: /usr/share/common-licenses/LGPL-3
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
licensecheck --check '.*' --recursive --copyright --deb-machine --ignore '^(debian/(changelog|copyright(_hints)?))$' --lines 0 -- * > debian/copyright_hints
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,14 @@
|
||||||
|
# clone this source: gbp clone $PKG_GIT_URL
|
||||||
|
# track upstream source: git remote add upstream-git $UPSTREAM_GIT_URL
|
||||||
|
# update this source: gbp pull
|
||||||
|
# update upstream source: git fetch upstream-git --tags
|
||||||
|
# import upstream release: gbp import-orig --upstream-vcs-tag=$VERSION --uscan
|
||||||
|
# build package: gbp buildpackage
|
||||||
|
# publish source release: gbp tag && gbp push
|
||||||
|
|
||||||
|
[DEFAULT]
|
||||||
|
pristine-tar = True
|
||||||
|
sign-tags = True
|
||||||
|
filter = */.git*
|
||||||
|
debian-branch = debian/latest
|
||||||
|
upstream-branch = upstream/latest
|
|
@ -0,0 +1,26 @@
|
||||||
|
# we provide no -dev package
|
||||||
|
usr/include/*/*.h
|
||||||
|
usr/lib/*/*.a
|
||||||
|
usr/lib/*/*.la
|
||||||
|
usr/lib/*/*.so
|
||||||
|
usr/lib/*/*/*/*.a
|
||||||
|
usr/lib/*/*/*/*.la
|
||||||
|
usr/lib/*/pkgconfig/*.pc
|
||||||
|
|
||||||
|
# covered in debian/copyright
|
||||||
|
usr/share/doc/syncevolution/COPYING
|
||||||
|
|
||||||
|
# relates to unsupported KDE options --enable-kwallet --enable-akonadi
|
||||||
|
usr/lib/*/syncevolution/backends/platformkde.so
|
||||||
|
usr/lib/*/syncevolution/backends/syncakonadi.so
|
||||||
|
usr/lib/*/syncevolution/backends/syncactivesync.so
|
||||||
|
|
||||||
|
# relates to unsupported KDE-derived Trinity Desktop Environment (TDE)
|
||||||
|
usr/lib/*/syncevolution/backends/synctdepimabc.so
|
||||||
|
usr/lib/*/syncevolution/backends/synctdepimcal.so
|
||||||
|
usr/lib/*/syncevolution/backends/synctdepimnotes.so
|
||||||
|
usr/lib/*/syncevolution/backends/platformtde.so
|
||||||
|
|
||||||
|
# helper scripts for testing
|
||||||
|
usr/bin/syncevo-phone-config
|
||||||
|
usr/bin/synclog2html
|
|
@ -1,48 +0,0 @@
|
||||||
From aabb99048290c0662629fe88588a80a0544fd8c5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Tino Mettler <tino+debian@tikei.de>
|
|
||||||
Date: Sun, 26 Oct 2014 12:54:31 +0100
|
|
||||||
Subject: [PATCH] Fix FTBFS on kfreebsd due to missing SOCK_CLOEXEC
|
|
||||||
|
|
||||||
Work around missing SOCK_CLOEXEC on kfreebsd by setting FD_CLOEXEC
|
|
||||||
afterwards.
|
|
||||||
---
|
|
||||||
src/gdbusxx/gdbus-cxx-bridge.cpp | 19 +++++++++++++++++++
|
|
||||||
1 file changed, 19 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/gdbusxx/gdbus-cxx-bridge.cpp b/src/gdbusxx/gdbus-cxx-bridge.cpp
|
|
||||||
index 238b52f0..4f259576 100644
|
|
||||||
--- a/src/gdbusxx/gdbus-cxx-bridge.cpp
|
|
||||||
+++ b/src/gdbusxx/gdbus-cxx-bridge.cpp
|
|
||||||
@@ -276,6 +276,10 @@ void DBusConnectionPtr::setDisconnect(const Disconnect_t &func)
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifndef SOCK_CLOEXEC
|
|
||||||
+#define SOCK_CLOEXEC 0
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
boost::shared_ptr<DBusServerCXX> DBusServerCXX::listen(const NewConnection_t &newConnection, DBusErrorCXX *)
|
|
||||||
{
|
|
||||||
// Create two fds connected via a two-way stream. The parent
|
|
||||||
@@ -286,6 +290,21 @@ boost::shared_ptr<DBusServerCXX> DBusServerCXX::listen(const NewConnection_t &ne
|
|
||||||
if (retval) {
|
|
||||||
SE_THROW(StringPrintf("socketpair: %s", strerror(errno)));
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ if(SOCK_CLOEXEC == 0) {
|
|
||||||
+ int flags;
|
|
||||||
+ int i;
|
|
||||||
+ for(i = 0; i < 2; i++) {
|
|
||||||
+ flags = fcntl(fds[i], F_GETFD);
|
|
||||||
+ if (flags == -1){
|
|
||||||
+ SE_THROW(StringPrintf("fcntl: %s", strerror(errno)));
|
|
||||||
+ }
|
|
||||||
+ flags |= FD_CLOEXEC;
|
|
||||||
+ if (fcntl(fds[i], F_SETFD, flags) == -1){
|
|
||||||
+ SE_THROW(StringPrintf("fcntl: %s", strerror(errno)));
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
GuardFD parentfd(fds[0]);
|
|
||||||
GuardFD childfd(fds[1]);
|
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
From 110e57f32fcae67634f6d0edd626ccc64748047e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Patrick Ohly <patrick.ohly@intel.com>
|
|
||||||
Date: Thu, 14 Dec 2017 07:46:32 -0800
|
|
||||||
Subject: [PATCH] libical: support libical v3
|
|
||||||
|
|
||||||
libical v3 removes some deprecated functions (like icaltime_from_timet)
|
|
||||||
and removes the "is_utc" member from icaltimetype. The replacement
|
|
||||||
code works with old and new libical and thus needs no ifdefs.
|
|
||||||
|
|
||||||
However, that struct is part of the ABI, which impacts the tricks that
|
|
||||||
syncevolution.org binaries use to get built against libical v2 and then
|
|
||||||
run with more recent libs like libical v3.
|
|
||||||
|
|
||||||
Depending on the platform ABI, it may still be okay, because the calling code
|
|
||||||
in SyncEvolution reserves and copies enough bytes for the icaltimetype
|
|
||||||
instances and because that code never directly accesses any member (is_date,
|
|
||||||
is_daylight, zone) whose offset changes.
|
|
||||||
|
|
||||||
Original author: Milan Crha <mcrha@redhat.com>
|
|
||||||
|
|
||||||
Slightly modified it so that icaltime_t.zone is not set.
|
|
||||||
|
|
||||||
Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
|
|
||||||
---
|
|
||||||
src/backends/webdav/CalDAVSource.cpp | 3 +--
|
|
||||||
src/syncevo/icaltz-util.c | 10 +++++-----
|
|
||||||
2 files changed, 6 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/backends/webdav/CalDAVSource.cpp b/src/backends/webdav/CalDAVSource.cpp
|
|
||||||
index fa16935a..9c4a1c8d 100644
|
|
||||||
--- a/src/backends/webdav/CalDAVSource.cpp
|
|
||||||
+++ b/src/backends/webdav/CalDAVSource.cpp
|
|
||||||
@@ -721,8 +721,7 @@ SubSyncSource::SubItemResult CalDAVSource::insertSubItem(const std::string &luid
|
|
||||||
eptr<icalcomponent> fullcal = event.m_calendar;
|
|
||||||
loadItem(event);
|
|
||||||
event.m_sequence++;
|
|
||||||
- lastmodtime = icaltime_from_timet(event.m_lastmodtime, false);
|
|
||||||
- lastmodtime.is_utc = 1;
|
|
||||||
+ lastmodtime = icaltime_from_timet_with_zone(event.m_lastmodtime, false, icaltimezone_get_utc_timezone());
|
|
||||||
event.m_calendar = fullcal;
|
|
||||||
for (icalcomponent *comp = icalcomponent_get_first_component(event.m_calendar, ICAL_VEVENT_COMPONENT);
|
|
||||||
comp;
|
|
||||||
diff --git a/src/syncevo/icaltz-util.c b/src/syncevo/icaltz-util.c
|
|
||||||
index 202a2cd9..abb9a758 100644
|
|
||||||
--- a/src/syncevo/icaltz-util.c
|
|
||||||
+++ b/src/syncevo/icaltz-util.c
|
|
||||||
@@ -224,7 +224,7 @@ find_transidx (time_t *transitions, ttinfo *types, int *trans_idx, long int num_
|
|
||||||
struct icaltimetype itime;
|
|
||||||
|
|
||||||
now = time (NULL);
|
|
||||||
- itime = icaltime_from_timet (now, 0);
|
|
||||||
+ itime = icaltime_from_timet_with_zone (now, 0, NULL);
|
|
||||||
itime.month = itime.day = 1;
|
|
||||||
itime.hour = itime.minute = itime.second = 0;
|
|
||||||
year_start = icaltime_as_timet(itime);
|
|
||||||
@@ -304,13 +304,13 @@ adjust_dtstart_day_to_rrule (icalcomponent *comp, struct icalrecurrencetype rule
|
|
||||||
icalrecur_iterator *iter;
|
|
||||||
|
|
||||||
now = time (NULL);
|
|
||||||
- itime = icaltime_from_timet (now, 0);
|
|
||||||
+ itime = icaltime_from_timet_with_zone (now, 0, NULL);
|
|
||||||
itime.month = itime.day = 1;
|
|
||||||
itime.hour = itime.minute = itime.second = 0;
|
|
||||||
year_start = icaltime_as_timet(itime);
|
|
||||||
|
|
||||||
comp_start = icalcomponent_get_dtstart (comp);
|
|
||||||
- start = icaltime_from_timet (year_start, 0);
|
|
||||||
+ start = icaltime_from_timet_with_zone (year_start, 0, NULL);
|
|
||||||
|
|
||||||
iter = icalrecur_iterator_new (rule, start);
|
|
||||||
iter_start = icalrecur_iterator_next (iter);
|
|
||||||
@@ -478,7 +478,7 @@ icaltzutil_fetch_timezone (const char *location)
|
|
||||||
trans = transitions [stdidx] + types [zp_idx].gmtoff;
|
|
||||||
else
|
|
||||||
trans = types [zp_idx].gmtoff;
|
|
||||||
- icaltime = icaltime_from_timet (trans, 0);
|
|
||||||
+ icaltime = icaltime_from_timet_with_zone (trans, 0, NULL);
|
|
||||||
dtstart = icaltime;
|
|
||||||
dtstart.year = 1970;
|
|
||||||
dtstart.minute = dtstart.second = 0;
|
|
||||||
@@ -520,7 +520,7 @@ icaltzutil_fetch_timezone (const char *location)
|
|
||||||
trans = transitions [dstidx] + types [zp_idx].gmtoff;
|
|
||||||
else
|
|
||||||
trans = types [zp_idx].gmtoff;
|
|
||||||
- icaltime = icaltime_from_timet (trans, 0);
|
|
||||||
+ icaltime = icaltime_from_timet_with_zone (trans, 0, NULL);
|
|
||||||
dtstart = icaltime;
|
|
||||||
dtstart.year = 1970;
|
|
||||||
dtstart.minute = dtstart.second = 0;
|
|
|
@ -1,255 +0,0 @@
|
||||||
From e6dc389330b51c508d0fa25d8e9ad599756ec69b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Patrick Ohly <patrick.ohly@intel.com>
|
|
||||||
Date: Thu, 16 Nov 2017 15:01:11 +0100
|
|
||||||
Subject: [PATCH] GNOME: replace gnome-keyring with libsecret
|
|
||||||
|
|
||||||
The GNOME keyring library has been obsoleted for a long time now,
|
|
||||||
long enough that the replacement libsecret is available on all
|
|
||||||
supported distros. Therefore we can switch unconditionally.
|
|
||||||
|
|
||||||
Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
|
|
||||||
---
|
|
||||||
src/backends/gnome/GNOMEPlatform.cpp | 170 ++++++++++++++---------------------
|
|
||||||
src/backends/gnome/configure-sub.in | 9 +-
|
|
||||||
2 files changed, 73 insertions(+), 106 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/backends/gnome/GNOMEPlatform.cpp b/src/backends/gnome/GNOMEPlatform.cpp
|
|
||||||
index f2f7a1d3..37f9811a 100644
|
|
||||||
--- a/src/backends/gnome/GNOMEPlatform.cpp
|
|
||||||
+++ b/src/backends/gnome/GNOMEPlatform.cpp
|
|
||||||
@@ -22,7 +22,7 @@
|
|
||||||
#ifdef USE_GNOME_KEYRING
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
-#include <gnome-keyring.h>
|
|
||||||
+#include <libsecret/secret.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "GNOMEPlatform.h"
|
|
||||||
@@ -30,46 +30,11 @@ extern "C" {
|
|
||||||
#include <syncevo/Exception.h>
|
|
||||||
#include <syncevo/UserInterface.h>
|
|
||||||
#include <syncevo/SyncConfig.h>
|
|
||||||
+#include <syncevo/GLibSupport.h>
|
|
||||||
|
|
||||||
#include <syncevo/declarations.h>
|
|
||||||
SE_BEGIN_CXX
|
|
||||||
|
|
||||||
-// Occasionally, libgnome-keyring fails with the following error messages:
|
|
||||||
-// Gkr: received an invalid, unencryptable, or non-utf8 secret
|
|
||||||
-// Gkr: call to daemon returned an invalid response: (null).(null)
|
|
||||||
-//
|
|
||||||
-// We work around that by retrying the operation a few times, for at
|
|
||||||
-// most this period of time. Didn't really help, so disable it for now
|
|
||||||
-// by using a zero duration.
|
|
||||||
-static const double GNOMEKeyringRetryDuration = 2; // seconds
|
|
||||||
-static const double GNOMEKeyringRetryInterval = 0.1; // seconds
|
|
||||||
-
|
|
||||||
-/**
|
|
||||||
- * libgnome-keyring has an internal gkr_reset_session()
|
|
||||||
- * method which gets called when the "org.freedesktop.secrets"
|
|
||||||
- * disconnects from the D-Bus session bus.
|
|
||||||
- *
|
|
||||||
- * We cannot call that method directly, but we can get it called by
|
|
||||||
- * faking the "disconnect" signal. That works because
|
|
||||||
- * on_connection_filter() in gkr-operation.c doesn't check who the
|
|
||||||
- * sender of the signal is.
|
|
||||||
- *
|
|
||||||
- * Once gkr_reset_session() got called, the next operation will
|
|
||||||
- * re-establish the connection. After the failure above, the second
|
|
||||||
- * attempt usually works.
|
|
||||||
- *
|
|
||||||
- * Any other client using libgnome-keyring will also be tricked into
|
|
||||||
- * disconnecting temporarily. That should be fine, any running
|
|
||||||
- * operation will continue to run and complete (?).
|
|
||||||
- */
|
|
||||||
-static void FlushGNOMEKeyring()
|
|
||||||
-{
|
|
||||||
- // Invoking dbus-send is easier than writing this in C++.
|
|
||||||
- // Besides, it ensures that the signal comes from some other
|
|
||||||
- // process. Not sure whether signals are sent back to the sender.
|
|
||||||
- system("dbus-send --session --type=signal /org/freedesktop/DBus org.freedesktop.DBus.NameOwnerChanged string:'org.freedesktop.secrets' string:':9.99' string:''");
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
/**
|
|
||||||
* GNOME keyring distinguishes between empty and unset
|
|
||||||
* password keys. This function returns NULL for an
|
|
||||||
@@ -97,6 +62,39 @@ static bool UseGNOMEKeyring(const InitStateTri &keyring)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
+class LibSecretHash : public GHashTableCXX
|
|
||||||
+{
|
|
||||||
+ std::list<std::string> m_buffer;
|
|
||||||
+
|
|
||||||
+public:
|
|
||||||
+ LibSecretHash(const ConfigPasswordKey &key) :
|
|
||||||
+ GHashTableCXX(g_hash_table_new(g_str_hash, g_str_equal), TRANSFER_REF)
|
|
||||||
+ {
|
|
||||||
+ // see https://developer.gnome.org/libsecret/0.16/libsecret-SecretSchema.html#SECRET-SCHEMA-COMPAT-NETWORK:CAPS
|
|
||||||
+ insert("user", key.user);
|
|
||||||
+ insert("domain", key.domain);
|
|
||||||
+ insert("server", key.server);
|
|
||||||
+ insert("object", key.object);
|
|
||||||
+ insert("protocol", key.protocol);
|
|
||||||
+ insert("authtype", key.authtype);
|
|
||||||
+ if (key.port) {
|
|
||||||
+ std::string value = StringPrintf("%d", key.port);
|
|
||||||
+ insert("port", value);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /** Keys are expected to be constants and not copied. Values are copied. */
|
|
||||||
+ void insert(const char *key, const std::string &value)
|
|
||||||
+ {
|
|
||||||
+ if (!value.empty()) {
|
|
||||||
+ m_buffer.push_back(value);
|
|
||||||
+ g_hash_table_insert(get(),
|
|
||||||
+ const_cast<char *>(key),
|
|
||||||
+ const_cast<char *>(m_buffer.back().c_str()));
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
bool GNOMELoadPasswordSlot(const InitStateTri &keyring,
|
|
||||||
const std::string &passwordName,
|
|
||||||
const std::string &descr,
|
|
||||||
@@ -108,46 +106,24 @@ bool GNOMELoadPasswordSlot(const InitStateTri &keyring,
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
- GnomeKeyringResult result = GNOME_KEYRING_RESULT_OK;
|
|
||||||
- GList* list;
|
|
||||||
- Timespec start = Timespec::monotonic();
|
|
||||||
- double sleepSecs = 0;
|
|
||||||
- do {
|
|
||||||
- if (sleepSecs != 0) {
|
|
||||||
- SE_LOG_DEBUG(NULL, "%s: previous attempt to load password '%s' from GNOME keyring failed, will try again: %s",
|
|
||||||
- key.description.c_str(),
|
|
||||||
- key.toString().c_str(),
|
|
||||||
- gnome_keyring_result_to_message(result));
|
|
||||||
- FlushGNOMEKeyring();
|
|
||||||
- Sleep(sleepSecs);
|
|
||||||
- }
|
|
||||||
- result = gnome_keyring_find_network_password_sync(passwdStr(key.user),
|
|
||||||
- passwdStr(key.domain),
|
|
||||||
- passwdStr(key.server),
|
|
||||||
- passwdStr(key.object),
|
|
||||||
- passwdStr(key.protocol),
|
|
||||||
- passwdStr(key.authtype),
|
|
||||||
- key.port,
|
|
||||||
- &list);
|
|
||||||
- sleepSecs = GNOMEKeyringRetryInterval;
|
|
||||||
- } while (result != GNOME_KEYRING_RESULT_OK &&
|
|
||||||
- (Timespec::monotonic() - start).duration() < GNOMEKeyringRetryDuration);
|
|
||||||
+ GErrorCXX gerror;
|
|
||||||
+ LibSecretHash hash(key);
|
|
||||||
+ PlainGStr result(secret_password_lookupv_sync(SECRET_SCHEMA_COMPAT_NETWORK,
|
|
||||||
+ hash,
|
|
||||||
+ NULL,
|
|
||||||
+ gerror));
|
|
||||||
|
|
||||||
// if find password stored in gnome keyring
|
|
||||||
- if(result == GNOME_KEYRING_RESULT_OK && list && list->data ) {
|
|
||||||
- GnomeKeyringNetworkPasswordData *key_data;
|
|
||||||
- key_data = (GnomeKeyringNetworkPasswordData*)list->data;
|
|
||||||
- password = std::string(key_data->password);
|
|
||||||
- gnome_keyring_network_password_list_free(list);
|
|
||||||
+ if (gerror) {
|
|
||||||
+ gerror.throwError(SE_HERE, StringPrintf("looking up password '%s'", descr.c_str()));
|
|
||||||
+ } else if (result) {
|
|
||||||
SE_LOG_DEBUG(NULL, "%s: loaded password from GNOME keyring using %s",
|
|
||||||
key.description.c_str(),
|
|
||||||
key.toString().c_str());
|
|
||||||
+ password = result;
|
|
||||||
} else {
|
|
||||||
- SE_LOG_DEBUG(NULL, "password not in GNOME keyring using %s: %s",
|
|
||||||
- key.toString().c_str(),
|
|
||||||
- result == GNOME_KEYRING_RESULT_NO_MATCH ? "no match" :
|
|
||||||
- result != GNOME_KEYRING_RESULT_OK ? gnome_keyring_result_to_message(result) :
|
|
||||||
- "empty result list");
|
|
||||||
+ SE_LOG_DEBUG(NULL, "password not in GNOME keyring using %s",
|
|
||||||
+ key.toString().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
@@ -173,38 +149,26 @@ bool GNOMESavePasswordSlot(const InitStateTri &keyring,
|
|
||||||
key.toString().c_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
- guint32 itemId;
|
|
||||||
- GnomeKeyringResult result = GNOME_KEYRING_RESULT_OK;
|
|
||||||
- // write password to keyring
|
|
||||||
- Timespec start = Timespec::monotonic();
|
|
||||||
- double sleepSecs = 0;
|
|
||||||
- do {
|
|
||||||
- if (sleepSecs != 0) {
|
|
||||||
- SE_LOG_DEBUG(NULL, "%s: previous attempt to save password '%s' in GNOME keyring failed, will try again: %s",
|
|
||||||
- key.description.c_str(),
|
|
||||||
- key.toString().c_str(),
|
|
||||||
- gnome_keyring_result_to_message(result));
|
|
||||||
- FlushGNOMEKeyring();
|
|
||||||
- Sleep(sleepSecs);
|
|
||||||
- }
|
|
||||||
- result = gnome_keyring_set_network_password_sync(NULL,
|
|
||||||
- passwdStr(key.user),
|
|
||||||
- passwdStr(key.domain),
|
|
||||||
- passwdStr(key.server),
|
|
||||||
- passwdStr(key.object),
|
|
||||||
- passwdStr(key.protocol),
|
|
||||||
- passwdStr(key.authtype),
|
|
||||||
- key.port,
|
|
||||||
- password.c_str(),
|
|
||||||
- &itemId);
|
|
||||||
- sleepSecs = GNOMEKeyringRetryInterval;
|
|
||||||
- } while (result != GNOME_KEYRING_RESULT_OK &&
|
|
||||||
- (Timespec::monotonic() - start).duration() < GNOMEKeyringRetryDuration);
|
|
||||||
- if (result != GNOME_KEYRING_RESULT_OK) {
|
|
||||||
- Exception::throwError(SE_HERE, StringPrintf("%s: saving password '%s' in GNOME keyring failed: %s",
|
|
||||||
- key.description.c_str(),
|
|
||||||
- key.toString().c_str(),
|
|
||||||
- gnome_keyring_result_to_message(result)));
|
|
||||||
+ GErrorCXX gerror;
|
|
||||||
+ LibSecretHash hash(key);
|
|
||||||
+ std::string label;
|
|
||||||
+ if (!key.user.empty() && !key.server.empty()) {
|
|
||||||
+ // This emulates the behavior of libgnomekeyring.
|
|
||||||
+ label = key.user + "@" + key.server;
|
|
||||||
+ } else {
|
|
||||||
+ label = passwordName;
|
|
||||||
+ }
|
|
||||||
+ gboolean result = secret_password_storev_sync(SECRET_SCHEMA_COMPAT_NETWORK,
|
|
||||||
+ hash,
|
|
||||||
+ NULL,
|
|
||||||
+ label.c_str(),
|
|
||||||
+ password.c_str(),
|
|
||||||
+ NULL,
|
|
||||||
+ gerror);
|
|
||||||
+ if (!result) {
|
|
||||||
+ gerror.throwError(SE_HERE, StringPrintf("%s: saving password '%s' in GNOME keyring",
|
|
||||||
+ key.description.c_str(),
|
|
||||||
+ key.toString().c_str()));
|
|
||||||
}
|
|
||||||
SE_LOG_DEBUG(NULL, "saved password in GNOME keyring using %s", key.toString().c_str());
|
|
||||||
|
|
||||||
diff --git a/src/backends/gnome/configure-sub.in b/src/backends/gnome/configure-sub.in
|
|
||||||
index 199989e8..d02d52a6 100644
|
|
||||||
--- a/src/backends/gnome/configure-sub.in
|
|
||||||
+++ b/src/backends/gnome/configure-sub.in
|
|
||||||
@@ -1,10 +1,13 @@
|
|
||||||
-PKG_CHECK_MODULES(KEYRING, [gnome-keyring-1 >= 2.20], HAVE_KEYRING=yes, HAVE_KEYRING=no)
|
|
||||||
+# According to https://developer.gnome.org/libsecret/0.16/libsecret-Password-storage.html#secret-password-store-sync
|
|
||||||
+# the simple API was still considered unstable. All supported distros
|
|
||||||
+# now have 0.18 where the API is stable.
|
|
||||||
+PKG_CHECK_MODULES(KEYRING, [libsecret-1 >= 0.18], HAVE_KEYRING=yes, HAVE_KEYRING=no)
|
|
||||||
AC_ARG_ENABLE(gnome-keyring,
|
|
||||||
AS_HELP_STRING([--enable-gnome-keyring],
|
|
||||||
- [enables or disables support for the GNOME keyring; default is on if development files are available]),
|
|
||||||
+ [enables or disables support for the GNOME keyring via libsecret; default is on if development files are available]),
|
|
||||||
[enable_gnome_keyring="$enableval"
|
|
||||||
test "$enable_gnome_keyring" = "yes" || test "$enable_gnome_keyring" = "no" || AC_MSG_ERROR([invalid value for --enable-gnome-keyring: $enable_gnome_keyring])
|
|
||||||
- test "$enable_gnome_keyring" = "no" || test "$HAVE_KEYRING" = "yes" || AC_MSG_ERROR([gnome-keyring-1 pkg >= 2.20 not found, needed for --enable-gnome-keyring])],
|
|
||||||
+ test "$enable_gnome_keyring" = "no" || test "$HAVE_KEYRING" = "yes" || AC_MSG_ERROR([libsecret-1 >= 0.18 not found, needed for --enable-gnome-keyring])],
|
|
||||||
enable_gnome_keyring="$HAVE_KEYRING")
|
|
||||||
if test $enable_gnome_keyring = "yes"; then
|
|
||||||
have_keyring=yes
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
Description: Fix FTBFS on kfreebsd due to missing SOCK_CLOEXEC
|
||||||
|
Work around missing SOCK_CLOEXEC on kfreebsd
|
||||||
|
by setting FD_CLOEXEC afterwards.
|
||||||
|
Author: Tino Mettler <tino+debian@tikei.de>
|
||||||
|
Last-Update: 2021-09-29
|
||||||
|
---
|
||||||
|
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
|
||||||
|
--- a/src/gdbusxx/gdbus-cxx-bridge.cpp
|
||||||
|
+++ b/src/gdbusxx/gdbus-cxx-bridge.cpp
|
||||||
|
@@ -285,6 +285,10 @@
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifndef SOCK_CLOEXEC
|
||||||
|
+#define SOCK_CLOEXEC 0
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
std::shared_ptr<DBusServerCXX> DBusServerCXX::listen(const NewConnection_t &newConnection, DBusErrorCXX *)
|
||||||
|
{
|
||||||
|
// Create two fds connected via a two-way stream. The parent
|
||||||
|
@@ -295,6 +299,21 @@
|
||||||
|
if (retval) {
|
||||||
|
SE_THROW(StringPrintf("socketpair: %s", strerror(errno)));
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if(SOCK_CLOEXEC == 0) {
|
||||||
|
+ int flags;
|
||||||
|
+ int i;
|
||||||
|
+ for(i = 0; i < 2; i++) {
|
||||||
|
+ flags = fcntl(fds[i], F_GETFD);
|
||||||
|
+ if (flags == -1){
|
||||||
|
+ SE_THROW(StringPrintf("fcntl: %s", strerror(errno)));
|
||||||
|
+ }
|
||||||
|
+ flags |= FD_CLOEXEC;
|
||||||
|
+ if (fcntl(fds[i], F_SETFD, flags) == -1){
|
||||||
|
+ SE_THROW(StringPrintf("fcntl: %s", strerror(errno)));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
GuardFD parentfd(fds[0]);
|
||||||
|
GuardFD childfd(fds[1]);
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
Description: adjust whitespace as required for recent autotools
|
||||||
|
Recent releases of autotools (possibly only autoreconf
|
||||||
|
apparently only recognizes the macro IT_PROG_INTLTOOL
|
||||||
|
when listed as the first word on a line.
|
||||||
|
Otherwise autoreconf fails with the following error message:
|
||||||
|
.
|
||||||
|
autoreconf: running: intltoolize --copy --force
|
||||||
|
ERROR: 'IT_PROG_INTLTOOL' must appear in configure.ac for intltool to work.
|
||||||
|
Author: Jonas Smedegaard <dr@jones.dk>
|
||||||
|
Last-Update: 2021-10-01
|
||||||
|
---
|
||||||
|
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -587,11 +587,11 @@
|
||||||
|
AC_DEFINE_UNQUOTED(DBUS_SERVICES_DIR, "$DBUS_SERVICES_DIR", [Location of D-Bus services directory])
|
||||||
|
|
||||||
|
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])
|
||||||
|
- AM_GLIB_GNU_GETTEXT
|
||||||
|
- SYNCEVOLUTION_LOCALEDIR=[${datadir}/locale]
|
||||||
|
+IT_PROG_INTLTOOL([0.37.1])
|
||||||
|
+GETTEXT_PACKAGE=syncevolution
|
||||||
|
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [The gettext package name])
|
||||||
|
+AM_GLIB_GNU_GETTEXT
|
||||||
|
+SYNCEVOLUTION_LOCALEDIR=[${datadir}/locale]
|
||||||
|
fi
|
||||||
|
|
||||||
|
# decide which sync-ui(s) we are building:
|
|
@ -0,0 +1,3 @@
|
||||||
|
0xxx: Grabbed from upstream development.
|
||||||
|
1xxx: Possibly relevant for upstream adoption.
|
||||||
|
2xxx: Only relevant for official Debian release.
|
|
@ -1,4 +1,2 @@
|
||||||
# debian/source/git-patches exported from git by quilt-patches-deb-export-hook
|
1001_SOCK_CLOEXEC.patch
|
||||||
0001-Fix-FTBFS-on-kfreebsd-due-to-missing-SOCK_CLOEXEC.patch
|
1002_intltool.patch
|
||||||
0002-libical-support-libical-v3.patch
|
|
||||||
0003-GNOME-replace-gnome-keyring-with-libsecret.patch
|
|
||||||
|
|
|
@ -1,12 +1,7 @@
|
||||||
#!/usr/bin/make -f
|
#!/usr/bin/make -f
|
||||||
# -*- makefile -*-
|
# -*- makefile -*-
|
||||||
UPSTREAMTAG=upstream/1.5.2
|
|
||||||
|
|
||||||
SOURCEPKG=$(shell dpkg-parsechangelog | sed -n 's/^Source: \(.*\)/\1/p')
|
export DEB_CXXFLAGS_APPEND = -std=c++14
|
||||||
UPSTREAM=$(shell dpkg-parsechangelog | sed -n 's/^Version: \(.*\)-[^-]*/\1/p')
|
|
||||||
ORIG=${SOURCEPKG}_${UPSTREAM}.orig.tar.gz
|
|
||||||
|
|
||||||
DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
|
|
||||||
|
|
||||||
export CONFIG_SHELL=/bin/bash
|
export CONFIG_SHELL=/bin/bash
|
||||||
|
|
||||||
|
@ -14,44 +9,31 @@ export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||||
export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
|
export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
|
||||||
export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
|
export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
|
||||||
|
|
||||||
%:
|
%:
|
||||||
dh $@ --parallel
|
dh $@
|
||||||
|
|
||||||
override_dh_auto_install:
|
override_dh_autoreconf:
|
||||||
make install DESTDIR=$(CURDIR)/debian/tmp
|
dh_autoreconf ./autogen.sh
|
||||||
install --mode=0755 --owner=root test/syncevo-http-server.py \
|
|
||||||
$(CURDIR)/debian/tmp/usr/bin/syncevo-http-server
|
|
||||||
|
|
||||||
override_dh_auto_configure:
|
override_dh_auto_configure:
|
||||||
sh autogen.sh
|
|
||||||
dh_auto_configure -- --with-synthesis-src=none --prefix=/usr \
|
dh_auto_configure -- --with-synthesis-src=none --prefix=/usr \
|
||||||
--sysconfdir=/etc \
|
--sysconfdir=/etc \
|
||||||
--libexecdir=/usr/lib/$(DEB_HOST_MULTIARCH)/syncevolution \
|
|
||||||
--enable-gui \
|
--enable-gui \
|
||||||
--enable-kwallet --enable-akonadi \
|
|
||||||
--with-rst2man --with-rst2html --enable-dav \
|
--with-rst2man --with-rst2html --enable-dav \
|
||||||
--enable-oauth2
|
--enable-oauth2
|
||||||
|
|
||||||
|
execute_after_dh_auto_install:
|
||||||
|
cp test/syncevo-http-server.py \
|
||||||
|
debian/tmp/usr/bin/syncevo-http-server
|
||||||
|
|
||||||
override_dh_install:
|
override_dh_install:
|
||||||
dh_install -X"*.pl"
|
dh_install -X"*.pl"
|
||||||
|
|
||||||
override_dh_strip:
|
override_dh_missing:
|
||||||
dh_strip --dbgsym-migration='syncevolution-dbg'
|
dh_missing
|
||||||
|
|
||||||
override_dh_auto_clean:
|
|
||||||
rm -f INSTALL compile po/LINGUAS src/backends/backends.am \
|
|
||||||
src/synthesis-includes/Makefile.in test-driver
|
|
||||||
dh_auto_clean
|
|
||||||
|
|
||||||
override_dh_makeshlibs:
|
override_dh_makeshlibs:
|
||||||
dh_makeshlibs -V'libsyncevolution0 (>= 1.5.2-3~)'
|
dh_makeshlibs -V'libsyncevolution0 (>= 1.5.2-3~)' -plibsyncevolution0
|
||||||
|
dh_makeshlibs -V'libsyncevo-dbus0 (>= 1.5.2-3~)' -plibsyncevo-dbus0
|
||||||
get-orig-source:
|
dh_makeshlibs -V'libgdbussyncevo0 (>= 1.5.2-3~)' -plibgdbussyncevo0
|
||||||
git archive --format=tar ${UPSTREAMTAG} --prefix=${SOURCEPKG}_${UPSTREAM}/ | gzip -9 > ../${ORIG}
|
dh_makeshlibs --remaining-packages
|
||||||
|
|
||||||
PATCH_EXPORT_SCRIPT=/usr/share/gitpkg/hooks/quilt-patches-deb-export-hook
|
|
||||||
export-patches:
|
|
||||||
[ ! -r debian/patches ] || \
|
|
||||||
grep "^\#*$(notdir $(PATCH_EXPORT_SCRIPT))" debian/patches/series
|
|
||||||
rm -rf debian/patches
|
|
||||||
bash $(PATCH_EXPORT_SCRIPT)
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
upstream/${UPSTREAM_REF}..patches/${DEB_REF}
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
# License is in Reference field (see bug#786450)
|
||||||
|
missing-license-paragraph-in-dep5-copyright debian/copyright artistic *
|
||||||
|
missing-license-paragraph-in-dep5-copyright debian/copyright gpl-1\+ *
|
||||||
|
missing-license-paragraph-in-dep5-copyright debian/copyright gpl-2\+ *
|
||||||
|
missing-license-paragraph-in-dep5-copyright debian/copyright gpl-3 *
|
||||||
|
missing-license-paragraph-in-dep5-copyright debian/copyright lgpl-2 *
|
||||||
|
missing-license-paragraph-in-dep5-copyright debian/copyright lgpl-2\+ *
|
||||||
|
missing-license-paragraph-in-dep5-copyright debian/copyright lgpl-2\.1 *
|
||||||
|
missing-license-paragraph-in-dep5-copyright debian/copyright lgpl-3 *
|
||||||
|
missing-license-text-in-dep5-copyright debian/copyright Artistic *
|
||||||
|
missing-license-text-in-dep5-copyright debian/copyright GPL-1\+ *
|
||||||
|
missing-license-text-in-dep5-copyright debian/copyright GPL-2\+ *
|
||||||
|
missing-license-text-in-dep5-copyright debian/copyright GPL-3 *
|
||||||
|
missing-license-text-in-dep5-copyright debian/copyright LGPL-2 *
|
||||||
|
missing-license-text-in-dep5-copyright debian/copyright LGPL-2\+ *
|
||||||
|
missing-license-text-in-dep5-copyright debian/copyright LGPL-2\.1 *
|
||||||
|
missing-license-text-in-dep5-copyright debian/copyright LGPL-3 *
|
|
@ -1,23 +1,4 @@
|
||||||
usr/share/locale/ja/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/ro/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/fi/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/sv/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/ar/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/pt_BR/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/gl/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/hu/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/ko/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/zh_TW/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/de/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/zh_CN/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/es/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/pl/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/id/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/da/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/fr/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/nl/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/it/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/th/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/share/locale/ca/LC_MESSAGES/syncevolution.mo
|
|
||||||
usr/bin/synccompare
|
usr/bin/synccompare
|
||||||
|
usr/bin/syncevo-webdav-lookup
|
||||||
|
usr/share/locale/*/LC_MESSAGES/syncevolution.mo
|
||||||
usr/share/syncevolution
|
usr/share/syncevolution
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
test/dbus-server-sync.py
|
|
|
@ -1,5 +1,6 @@
|
||||||
usr/share/dbus-1/services/org.syncevolution.service
|
etc/xdg/autostart/syncevo-dbus-server.desktop
|
||||||
|
usr/libexec/syncevo-dbus-helper
|
||||||
|
usr/libexec/syncevo-dbus-server
|
||||||
|
usr/libexec/syncevo-dbus-server-startup.sh
|
||||||
usr/lib/systemd/user/*.service
|
usr/lib/systemd/user/*.service
|
||||||
usr/lib/*/syncevolution/syncevo-dbus-server
|
usr/share/dbus-1/services/org.syncevolution.service
|
||||||
usr/lib/*/syncevolution/syncevo-dbus-helper
|
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
usr/bin/syncevo-http-server
|
usr/bin/syncevo-http-server
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
usr/lib/*/syncevolution/backends/platformkde.so
|
|
||||||
usr/lib/*/syncevolution/backends/syncakonadi.so
|
|
|
@ -1,10 +1,12 @@
|
||||||
usr/lib/*/syncevolution/backends/syncfile.so
|
usr/lib/*/syncevolution/backends/providergoa.so
|
||||||
usr/lib/*/syncevolution/backends/syncdav.so
|
|
||||||
usr/lib/*/syncevolution/backends/syncxmlrpc.so
|
|
||||||
usr/lib/*/syncevolution/backends/synckcalextended.so
|
|
||||||
usr/lib/*/syncevolution/backends/syncqtcontacts.so
|
|
||||||
usr/lib/*/syncevolution/backends/syncmaemocal.so
|
|
||||||
usr/lib/*/syncevolution/backends/syncactivesync.so
|
|
||||||
usr/lib/*/syncevolution/backends/syncsqlite.so
|
|
||||||
usr/lib/*/syncevolution/backends/provideroauth2.so
|
usr/lib/*/syncevolution/backends/provideroauth2.so
|
||||||
usr/lib/*/syncevolution/syncevo-local-sync
|
usr/lib/*/syncevolution/backends/syncdav.so
|
||||||
|
usr/lib/*/syncevolution/backends/syncfile.so
|
||||||
|
usr/lib/*/syncevolution/backends/syncpbap.so
|
||||||
|
usr/lib/*/syncevolution/backends/synckcalextended.so
|
||||||
|
usr/lib/*/syncevolution/backends/syncmaemocal.so
|
||||||
|
usr/lib/*/syncevolution/backends/syncqtcontacts.so
|
||||||
|
usr/lib/*/syncevolution/backends/syncsqlite.so
|
||||||
|
usr/lib/*/syncevolution/backends/syncxmlrpc.so
|
||||||
|
|
||||||
|
usr/libexec/syncevo-local-sync
|
||||||
|
|
|
@ -1,9 +1,3 @@
|
||||||
debian/tmp/usr/share/doc/syncevolution/README.nokia_7210c
|
|
||||||
debian/tmp/usr/share/doc/syncevolution/README.scheduleworld
|
|
||||||
debian/tmp/usr/share/doc/syncevolution/README.mobical
|
|
||||||
debian/tmp/usr/share/doc/syncevolution/README
|
|
||||||
debian/tmp/usr/share/doc/syncevolution/README.funambol
|
|
||||||
debian/tmp/usr/share/doc/syncevolution/README.zyb
|
|
||||||
debian/tmp/usr/share/doc/syncevolution/NEWS
|
debian/tmp/usr/share/doc/syncevolution/NEWS
|
||||||
debian/tmp/usr/share/doc/syncevolution/README.google
|
debian/tmp/usr/share/doc/syncevolution/README
|
||||||
debian/tmp/usr/share/doc/syncevolution/README.memotoo
|
debian/tmp/usr/share/doc/syncevolution/README.*
|
||||||
|
|
|
@ -1,2 +1,5 @@
|
||||||
|
debian/tmp/usr/share/doc/syncevolution/accounts
|
||||||
|
debian/tmp/usr/share/doc/syncevolution/syncevo-http-server-logging.conf
|
||||||
debian/tmp/usr/share/syncevolution/xml/update-samples.pl
|
debian/tmp/usr/share/syncevolution/xml/update-samples.pl
|
||||||
|
debian/tmp/usr/share/doc/syncevolution/accounts
|
||||||
test/syncevo-phone-config.py
|
test/syncevo-phone-config.py
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
syncevolution.1
|
debian/tmp/usr/share/man/man1/syncevolution.1
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
version=3
|
version=4
|
||||||
|
# check: uscan --report
|
||||||
|
# update: gbp import-orig --upstream-vcs-tag=vX.Y.Z --uscan
|
||||||
|
|
||||||
opts=dversionmangle=s/\+ds\d+$// \
|
opts=\
|
||||||
http://downloads.syncevolution.org/syncevolution/sources/syncevolution-(.*).tar.gz
|
filenamemangle=s/.*?(@ANY_VERSION@@ARCHIVE_EXT@)/@PACKAGE@$1/,\
|
||||||
|
uversionmangle=s/-(?=\d)/./g;s/-?pre/~pre/,\
|
||||||
|
dversionmangle=auto \
|
||||||
|
https://gitlab.freedesktop.org/SyncEvolution/syncevolution/-/tags \
|
||||||
|
.*?@ANY_VERSION@@ARCHIVE_EXT@
|
||||||
|
|
|
@ -0,0 +1,982 @@
|
||||||
|
# ===========================================================================
|
||||||
|
# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
|
||||||
|
# ===========================================================================
|
||||||
|
#
|
||||||
|
# SYNOPSIS
|
||||||
|
#
|
||||||
|
# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# Check for baseline language coverage in the compiler for the specified
|
||||||
|
# version of the C++ standard. If necessary, add switches to CXX and
|
||||||
|
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
|
||||||
|
# or '14' (for the C++14 standard).
|
||||||
|
#
|
||||||
|
# The second argument, if specified, indicates whether you insist on an
|
||||||
|
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
|
||||||
|
# -std=c++11). If neither is specified, you get whatever works, with
|
||||||
|
# preference for an extended mode.
|
||||||
|
#
|
||||||
|
# The third argument, if specified 'mandatory' or if left unspecified,
|
||||||
|
# indicates that baseline support for the specified C++ standard is
|
||||||
|
# required and that the macro should error out if no mode with that
|
||||||
|
# support is found. If specified 'optional', then configuration proceeds
|
||||||
|
# regardless, after defining HAVE_CXX${VERSION} if and only if a
|
||||||
|
# supporting mode is found.
|
||||||
|
#
|
||||||
|
# LICENSE
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
|
||||||
|
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
|
||||||
|
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
|
||||||
|
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
|
||||||
|
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
|
||||||
|
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
|
||||||
|
# Copyright (c) 2016 Krzesimir Nowak <qdlacz@gmail.com>
|
||||||
|
#
|
||||||
|
# Copying and distribution of this file, with or without modification, are
|
||||||
|
# permitted in any medium without royalty provided the copyright notice
|
||||||
|
# and this notice are preserved. This file is offered as-is, without any
|
||||||
|
# warranty.
|
||||||
|
|
||||||
|
#serial 7
|
||||||
|
|
||||||
|
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
|
||||||
|
dnl (serial version number 13).
|
||||||
|
|
||||||
|
AX_REQUIRE_DEFINED([AC_MSG_WARN])
|
||||||
|
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
|
||||||
|
m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
|
||||||
|
[$1], [14], [ax_cxx_compile_alternatives="14 1y"],
|
||||||
|
[$1], [17], [ax_cxx_compile_alternatives="17 1z"],
|
||||||
|
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||||
|
m4_if([$2], [], [],
|
||||||
|
[$2], [ext], [],
|
||||||
|
[$2], [noext], [],
|
||||||
|
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||||
|
m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
|
||||||
|
[$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
|
||||||
|
[$3], [optional], [ax_cxx_compile_cxx$1_required=false],
|
||||||
|
[m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
|
||||||
|
AC_LANG_PUSH([C++])dnl
|
||||||
|
ac_success=no
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
|
||||||
|
ax_cv_cxx_compile_cxx$1,
|
||||||
|
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[ax_cv_cxx_compile_cxx$1=yes],
|
||||||
|
[ax_cv_cxx_compile_cxx$1=no])])
|
||||||
|
if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
|
||||||
|
ac_success=yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
m4_if([$2], [noext], [], [dnl
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||||
|
switch="-std=gnu++${alternative}"
|
||||||
|
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||||
|
$cachevar,
|
||||||
|
[ac_save_CXX="$CXX"
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[eval $cachevar=yes],
|
||||||
|
[eval $cachevar=no])
|
||||||
|
CXX="$ac_save_CXX"])
|
||||||
|
if eval test x\$$cachevar = xyes; then
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
if test -n "$CXXCPP" ; then
|
||||||
|
CXXCPP="$CXXCPP $switch"
|
||||||
|
fi
|
||||||
|
ac_success=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi])
|
||||||
|
|
||||||
|
m4_if([$2], [ext], [], [dnl
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
dnl HP's aCC needs +std=c++11 according to:
|
||||||
|
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
|
||||||
|
dnl Cray's crayCC needs "-h std=c++11"
|
||||||
|
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||||
|
for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
|
||||||
|
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||||
|
$cachevar,
|
||||||
|
[ac_save_CXX="$CXX"
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[eval $cachevar=yes],
|
||||||
|
[eval $cachevar=no])
|
||||||
|
CXX="$ac_save_CXX"])
|
||||||
|
if eval test x\$$cachevar = xyes; then
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
if test -n "$CXXCPP" ; then
|
||||||
|
CXXCPP="$CXXCPP $switch"
|
||||||
|
fi
|
||||||
|
ac_success=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test x$ac_success = xyes; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi])
|
||||||
|
AC_LANG_POP([C++])
|
||||||
|
if test x$ax_cxx_compile_cxx$1_required = xtrue; then
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
HAVE_CXX$1=0
|
||||||
|
AC_MSG_NOTICE([No compiler with C++$1 support was found])
|
||||||
|
else
|
||||||
|
HAVE_CXX$1=1
|
||||||
|
AC_DEFINE(HAVE_CXX$1,1,
|
||||||
|
[define if the compiler supports basic C++$1 syntax])
|
||||||
|
fi
|
||||||
|
AC_SUBST(HAVE_CXX$1)
|
||||||
|
m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])])
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Test body for checking C++11 support
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
dnl Test body for checking C++14 support
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||||
|
)
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
|
||||||
|
)
|
||||||
|
|
||||||
|
dnl Tests for new features in C++11
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++11, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 201103L
|
||||||
|
|
||||||
|
#error "This is not a C++11 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace cxx11
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace test_static_assert
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct check
|
||||||
|
{
|
||||||
|
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_final_override
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Base
|
||||||
|
{
|
||||||
|
virtual void f() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Derived : public Base
|
||||||
|
{
|
||||||
|
virtual void f() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_double_right_angle_brackets
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct check {};
|
||||||
|
|
||||||
|
typedef check<void> single_type;
|
||||||
|
typedef check<check<void>> double_type;
|
||||||
|
typedef check<check<check<void>>> triple_type;
|
||||||
|
typedef check<check<check<check<void>>>> quadruple_type;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_decltype
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
f()
|
||||||
|
{
|
||||||
|
int a = 1;
|
||||||
|
decltype(a) b = 2;
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_type_deduction
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
struct is_same
|
||||||
|
{
|
||||||
|
static const bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct is_same<T, T>
|
||||||
|
{
|
||||||
|
static const bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
auto
|
||||||
|
add(T1 a1, T2 a2) -> decltype(a1 + a2)
|
||||||
|
{
|
||||||
|
return a1 + a2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test(const int c, volatile int v)
|
||||||
|
{
|
||||||
|
static_assert(is_same<int, decltype(0)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(c)>::value == false, "");
|
||||||
|
static_assert(is_same<int, decltype(v)>::value == false, "");
|
||||||
|
auto ac = c;
|
||||||
|
auto av = v;
|
||||||
|
auto sumi = ac + av + 'x';
|
||||||
|
auto sumf = ac + av + 1.0;
|
||||||
|
static_assert(is_same<int, decltype(ac)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(av)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(sumi)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(sumf)>::value == false, "");
|
||||||
|
static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
|
||||||
|
return (sumf > 0.0) ? sumi : add(c, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
int f() { return 0; }
|
||||||
|
int g() noexcept { return 0; }
|
||||||
|
|
||||||
|
static_assert(noexcept(f()) == false, "");
|
||||||
|
static_assert(noexcept(g()) == true, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_constexpr
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
unsigned long constexpr
|
||||||
|
strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
|
||||||
|
{
|
||||||
|
return *s ? strlen_c_r(s + 1, acc + 1) : acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
unsigned long constexpr
|
||||||
|
strlen_c(const CharT *const s) noexcept
|
||||||
|
{
|
||||||
|
return strlen_c_r(s, 0UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(strlen_c("") == 0UL, "");
|
||||||
|
static_assert(strlen_c("1") == 1UL, "");
|
||||||
|
static_assert(strlen_c("example") == 7UL, "");
|
||||||
|
static_assert(strlen_c("another\0example") == 7UL, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_rvalue_references
|
||||||
|
{
|
||||||
|
|
||||||
|
template < int N >
|
||||||
|
struct answer
|
||||||
|
{
|
||||||
|
static constexpr int value = N;
|
||||||
|
};
|
||||||
|
|
||||||
|
answer<1> f(int&) { return answer<1>(); }
|
||||||
|
answer<2> f(const int&) { return answer<2>(); }
|
||||||
|
answer<3> f(int&&) { return answer<3>(); }
|
||||||
|
|
||||||
|
void
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
const int c = 0;
|
||||||
|
static_assert(decltype(f(i))::value == 1, "");
|
||||||
|
static_assert(decltype(f(c))::value == 2, "");
|
||||||
|
static_assert(decltype(f(0))::value == 3, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_uniform_initialization
|
||||||
|
{
|
||||||
|
|
||||||
|
struct test
|
||||||
|
{
|
||||||
|
static const int zero {};
|
||||||
|
static const int one {1};
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(test::zero == 0, "");
|
||||||
|
static_assert(test::one == 1, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
void
|
||||||
|
test1()
|
||||||
|
{
|
||||||
|
auto lambda1 = [](){};
|
||||||
|
auto lambda2 = lambda1;
|
||||||
|
lambda1();
|
||||||
|
lambda2();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test2()
|
||||||
|
{
|
||||||
|
auto a = [](int i, int j){ return i + j; }(1, 2);
|
||||||
|
auto b = []() -> int { return '0'; }();
|
||||||
|
auto c = [=](){ return a + b; }();
|
||||||
|
auto d = [&](){ return c; }();
|
||||||
|
auto e = [a, &b](int x) mutable {
|
||||||
|
const auto identity = [](int y){ return y; };
|
||||||
|
for (auto i = 0; i < a; ++i)
|
||||||
|
a += b--;
|
||||||
|
return x + identity(a + b);
|
||||||
|
}(0);
|
||||||
|
return a + b + c + d + e;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test3()
|
||||||
|
{
|
||||||
|
const auto nullary = [](){ return 0; };
|
||||||
|
const auto unary = [](int x){ return x; };
|
||||||
|
using nullary_t = decltype(nullary);
|
||||||
|
using unary_t = decltype(unary);
|
||||||
|
const auto higher1st = [](nullary_t f){ return f(); };
|
||||||
|
const auto higher2nd = [unary](nullary_t f1){
|
||||||
|
return [unary, f1](unary_t f2){ return f2(unary(f1())); };
|
||||||
|
};
|
||||||
|
return higher1st(nullary) + higher2nd(nullary)(unary);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_variadic_templates
|
||||||
|
{
|
||||||
|
|
||||||
|
template <int...>
|
||||||
|
struct sum;
|
||||||
|
|
||||||
|
template <int N0, int... N1toN>
|
||||||
|
struct sum<N0, N1toN...>
|
||||||
|
{
|
||||||
|
static constexpr auto value = N0 + sum<N1toN...>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct sum<>
|
||||||
|
{
|
||||||
|
static constexpr auto value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sum<>::value == 0, "");
|
||||||
|
static_assert(sum<1>::value == 1, "");
|
||||||
|
static_assert(sum<23>::value == 23, "");
|
||||||
|
static_assert(sum<1, 2>::value == 3, "");
|
||||||
|
static_assert(sum<5, 5, 11>::value == 21, "");
|
||||||
|
static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
|
||||||
|
// Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
|
||||||
|
// because of this.
|
||||||
|
namespace test_template_alias_sfinae
|
||||||
|
{
|
||||||
|
|
||||||
|
struct foo {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using member = typename T::member_type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void func(...) {}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void func(member<T>*) {}
|
||||||
|
|
||||||
|
void test();
|
||||||
|
|
||||||
|
void test() { func<foo>(0); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx11
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 201103L
|
||||||
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Tests for new features in C++14
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++14, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 201402L
|
||||||
|
|
||||||
|
#error "This is not a C++14 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace cxx14
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace test_polymorphic_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
const auto lambda = [](auto&&... args){
|
||||||
|
const auto istiny = [](auto x){
|
||||||
|
return (sizeof(x) == 1UL) ? 1 : 0;
|
||||||
|
};
|
||||||
|
const int aretiny[] = { istiny(args)... };
|
||||||
|
return aretiny[0];
|
||||||
|
};
|
||||||
|
return lambda(1, 1L, 1.0f, '1');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_binary_literals
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr auto ivii = 0b0000000000101010;
|
||||||
|
static_assert(ivii == 42, "wrong value");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_generalized_constexpr
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
constexpr unsigned long
|
||||||
|
strlen_c(const CharT *const s) noexcept
|
||||||
|
{
|
||||||
|
auto length = 0UL;
|
||||||
|
for (auto p = s; *p; ++p)
|
||||||
|
++length;
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(strlen_c("") == 0UL, "");
|
||||||
|
static_assert(strlen_c("x") == 1UL, "");
|
||||||
|
static_assert(strlen_c("test") == 4UL, "");
|
||||||
|
static_assert(strlen_c("another\0test") == 7UL, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambda_init_capture
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
auto x = 0;
|
||||||
|
const auto lambda1 = [a = x](int b){ return a + b; };
|
||||||
|
const auto lambda2 = [a = lambda1(x)](){ return a; };
|
||||||
|
return lambda2();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_digit_separators
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr auto ten_million = 100'000'000;
|
||||||
|
static_assert(ten_million == 100000000, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_return_type_deduction
|
||||||
|
{
|
||||||
|
|
||||||
|
auto f(int& x) { return x; }
|
||||||
|
decltype(auto) g(int& x) { return x; }
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
struct is_same
|
||||||
|
{
|
||||||
|
static constexpr auto value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct is_same<T, T>
|
||||||
|
{
|
||||||
|
static constexpr auto value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
auto x = 0;
|
||||||
|
static_assert(is_same<int, decltype(f(x))>::value, "");
|
||||||
|
static_assert(is_same<int&, decltype(g(x))>::value, "");
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx14
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 201402L
|
||||||
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Tests for new features in C++17
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++17, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus <= 201402L
|
||||||
|
|
||||||
|
#error "This is not a C++17 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define REALLY_CLANG
|
||||||
|
#else
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define REALLY_GCC
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <utility>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace cxx17
|
||||||
|
{
|
||||||
|
|
||||||
|
#if !defined(REALLY_CLANG)
|
||||||
|
namespace test_constexpr_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: test it with clang++ from git
|
||||||
|
|
||||||
|
constexpr int foo = [](){return 42;}();
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // !defined(REALLY_CLANG)
|
||||||
|
|
||||||
|
namespace test::nested_namespace::definitions
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_fold_expression
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
int multiply(Args... args)
|
||||||
|
{
|
||||||
|
return (args * ... * 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
bool all(Args... args)
|
||||||
|
{
|
||||||
|
return (args && ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_extended_static_assert
|
||||||
|
{
|
||||||
|
|
||||||
|
static_assert (true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_auto_brace_init_list
|
||||||
|
{
|
||||||
|
|
||||||
|
auto foo = {5};
|
||||||
|
auto bar {5};
|
||||||
|
|
||||||
|
static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
|
||||||
|
static_assert(std::is_same<int, decltype(bar)>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_typename_in_template_template_parameter
|
||||||
|
{
|
||||||
|
|
||||||
|
template<template<typename> typename X> struct D;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_fallthrough_nodiscard_maybe_unused_attributes
|
||||||
|
{
|
||||||
|
|
||||||
|
int f1()
|
||||||
|
{
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int f2()
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto unused = f1();
|
||||||
|
|
||||||
|
switch (f1())
|
||||||
|
{
|
||||||
|
case 17:
|
||||||
|
f1();
|
||||||
|
[[fallthrough]];
|
||||||
|
case 42:
|
||||||
|
f1();
|
||||||
|
}
|
||||||
|
return f1();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_extended_aggregate_initialization
|
||||||
|
{
|
||||||
|
|
||||||
|
struct base1
|
||||||
|
{
|
||||||
|
int b1, b2 = 42;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct base2
|
||||||
|
{
|
||||||
|
base2() {
|
||||||
|
b3 = 42;
|
||||||
|
}
|
||||||
|
int b3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct derived : base1, base2
|
||||||
|
{
|
||||||
|
int d;
|
||||||
|
};
|
||||||
|
|
||||||
|
derived d1 {{1, 2}, {}, 4}; // full initialization
|
||||||
|
derived d2 {{}, {}, 4}; // value-initialized bases
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_general_range_based_for_loop
|
||||||
|
{
|
||||||
|
|
||||||
|
struct iter
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
int& operator* ()
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int& operator* () const
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
iter& operator++()
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sentinel
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator== (const iter& i, const sentinel& s)
|
||||||
|
{
|
||||||
|
return i.i == s.i;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!= (const iter& i, const sentinel& s)
|
||||||
|
{
|
||||||
|
return !(i == s);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct range
|
||||||
|
{
|
||||||
|
iter begin() const
|
||||||
|
{
|
||||||
|
return {0};
|
||||||
|
}
|
||||||
|
|
||||||
|
sentinel end() const
|
||||||
|
{
|
||||||
|
return {5};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
range r {};
|
||||||
|
|
||||||
|
for (auto i : r)
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto v = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambda_capture_asterisk_this_by_value
|
||||||
|
{
|
||||||
|
|
||||||
|
struct t
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int foo()
|
||||||
|
{
|
||||||
|
return [*this]()
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_enum_class_construction
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class byte : unsigned char
|
||||||
|
{};
|
||||||
|
|
||||||
|
byte foo {42};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_constexpr_if
|
||||||
|
{
|
||||||
|
|
||||||
|
template <bool cond>
|
||||||
|
int f ()
|
||||||
|
{
|
||||||
|
if constexpr(cond)
|
||||||
|
{
|
||||||
|
return 13;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_selection_statement_with_initializer
|
||||||
|
{
|
||||||
|
|
||||||
|
int f()
|
||||||
|
{
|
||||||
|
return 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
int f2()
|
||||||
|
{
|
||||||
|
if (auto i = f(); i > 0)
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (auto i = f(); i + 4)
|
||||||
|
{
|
||||||
|
case 17:
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(REALLY_CLANG)
|
||||||
|
namespace test_template_argument_deduction_for_class_templates
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: test it with clang++ from git
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
struct pair
|
||||||
|
{
|
||||||
|
pair (T1 p1, T2 p2)
|
||||||
|
: m1 {p1},
|
||||||
|
m2 {p2}
|
||||||
|
{}
|
||||||
|
|
||||||
|
T1 m1;
|
||||||
|
T2 m2;
|
||||||
|
};
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto p = pair{13, 42u};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // !defined(REALLY_CLANG)
|
||||||
|
|
||||||
|
namespace test_non_type_auto_template_parameters
|
||||||
|
{
|
||||||
|
|
||||||
|
template <auto n>
|
||||||
|
struct B
|
||||||
|
{};
|
||||||
|
|
||||||
|
B<5> b1;
|
||||||
|
B<'a'> b2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(REALLY_CLANG)
|
||||||
|
namespace test_structured_bindings
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: test it with clang++ from git
|
||||||
|
|
||||||
|
int arr[2] = { 1, 2 };
|
||||||
|
std::pair<int, int> pr = { 1, 2 };
|
||||||
|
|
||||||
|
auto f1() -> int(&)[2]
|
||||||
|
{
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto f2() -> std::pair<int, int>&
|
||||||
|
{
|
||||||
|
return pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S
|
||||||
|
{
|
||||||
|
int x1 : 2;
|
||||||
|
volatile double y1;
|
||||||
|
};
|
||||||
|
|
||||||
|
S f3()
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [ x1, y1 ] = f1();
|
||||||
|
auto& [ xr1, yr1 ] = f1();
|
||||||
|
auto [ x2, y2 ] = f2();
|
||||||
|
auto& [ xr2, yr2 ] = f2();
|
||||||
|
const auto [ x3, y3 ] = f3();
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // !defined(REALLY_CLANG)
|
||||||
|
|
||||||
|
#if !defined(REALLY_CLANG)
|
||||||
|
namespace test_exception_spec_type_system
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO: test it with clang++ from git
|
||||||
|
|
||||||
|
struct Good {};
|
||||||
|
struct Bad {};
|
||||||
|
|
||||||
|
void g1() noexcept;
|
||||||
|
void g2();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Bad
|
||||||
|
f(T*, T*);
|
||||||
|
|
||||||
|
template<typename T1, typename T2>
|
||||||
|
Good
|
||||||
|
f(T1*, T2*);
|
||||||
|
|
||||||
|
static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // !defined(REALLY_CLANG)
|
||||||
|
|
||||||
|
namespace test_inline_variables
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class T> void f(T)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<class T> inline T g(T)
|
||||||
|
{
|
||||||
|
return T{};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> inline void f<>(int)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<> int g<>(int)
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx17
|
||||||
|
|
||||||
|
#endif // __cplusplus <= 201402L
|
||||||
|
|
||||||
|
]])
|
|
@ -0,0 +1,39 @@
|
||||||
|
# =============================================================================
|
||||||
|
# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
|
||||||
|
# =============================================================================
|
||||||
|
#
|
||||||
|
# SYNOPSIS
|
||||||
|
#
|
||||||
|
# AX_CXX_COMPILE_STDCXX_11([ext|noext], [mandatory|optional])
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# Check for baseline language coverage in the compiler for the C++11
|
||||||
|
# standard; if necessary, add switches to CXX and CXXCPP to enable
|
||||||
|
# support.
|
||||||
|
#
|
||||||
|
# This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX
|
||||||
|
# macro with the version set to C++11. The two optional arguments are
|
||||||
|
# forwarded literally as the second and third argument respectively.
|
||||||
|
# Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for
|
||||||
|
# more information. If you want to use this macro, you also need to
|
||||||
|
# download the ax_cxx_compile_stdcxx.m4 file.
|
||||||
|
#
|
||||||
|
# LICENSE
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
|
||||||
|
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
|
||||||
|
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
|
||||||
|
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
|
||||||
|
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
|
||||||
|
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
|
||||||
|
#
|
||||||
|
# Copying and distribution of this file, with or without modification, are
|
||||||
|
# permitted in any medium without royalty provided the copyright notice
|
||||||
|
# and this notice are preserved. This file is offered as-is, without any
|
||||||
|
# warranty.
|
||||||
|
|
||||||
|
#serial 18
|
||||||
|
|
||||||
|
AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX])
|
||||||
|
AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [AX_CXX_COMPILE_STDCXX([11], [$1], [$2])])
|
|
@ -0,0 +1,34 @@
|
||||||
|
# =============================================================================
|
||||||
|
# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_14.html
|
||||||
|
# =============================================================================
|
||||||
|
#
|
||||||
|
# SYNOPSIS
|
||||||
|
#
|
||||||
|
# AX_CXX_COMPILE_STDCXX_14([ext|noext], [mandatory|optional])
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# Check for baseline language coverage in the compiler for the C++14
|
||||||
|
# standard; if necessary, add switches to CXX and CXXCPP to enable
|
||||||
|
# support.
|
||||||
|
#
|
||||||
|
# This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX
|
||||||
|
# macro with the version set to C++14. The two optional arguments are
|
||||||
|
# forwarded literally as the second and third argument respectively.
|
||||||
|
# Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for
|
||||||
|
# more information. If you want to use this macro, you also need to
|
||||||
|
# download the ax_cxx_compile_stdcxx.m4 file.
|
||||||
|
#
|
||||||
|
# LICENSE
|
||||||
|
#
|
||||||
|
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
|
||||||
|
#
|
||||||
|
# Copying and distribution of this file, with or without modification, are
|
||||||
|
# permitted in any medium without royalty provided the copyright notice
|
||||||
|
# and this notice are preserved. This file is offered as-is, without any
|
||||||
|
# warranty.
|
||||||
|
|
||||||
|
#serial 5
|
||||||
|
|
||||||
|
AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX])
|
||||||
|
AC_DEFUN([AX_CXX_COMPILE_STDCXX_14], [AX_CXX_COMPILE_STDCXX([14], [$1], [$2])])
|
|
@ -34,7 +34,7 @@ COPYRIGHT_HOLDER =
|
||||||
# It can be your email address, or a mailing list address where translators
|
# It can be your email address, or a mailing list address where translators
|
||||||
# can write to without being subscribed, or the URL of a web page through
|
# can write to without being subscribed, or the URL of a web page through
|
||||||
# which the translators can contact you.
|
# which the translators can contact you.
|
||||||
MSGID_BUGS_ADDRESS = http://moblin.org/projects/syncevolution
|
MSGID_BUGS_ADDRESS = https://syncevolution.org/
|
||||||
|
|
||||||
# This is the list of locale categories, beyond LC_MESSAGES, for which the
|
# This is the list of locale categories, beyond LC_MESSAGES, for which the
|
||||||
# message catalogs shall be used. It is usually empty.
|
# message catalogs shall be used. It is usually empty.
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
src/gtk-ui/ui.xml
|
src/gtk-ui/ui.xml
|
||||||
src/gtk-ui/gtkinfobar.c
|
src/gtk-ui/gtkinfobar.c
|
||||||
src/synthesis/src/pcre/pcre_compile.c
|
src/synthesis/src/pcre/pcre_compile.c
|
||||||
src/dbus/server/pim/testpim.py
|
|
||||||
|
|
2
po/ar.po
2
po/ar.po
|
@ -6,7 +6,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: syncevolution\n"
|
"Project-Id-Version: syncevolution\n"
|
||||||
"Report-Msgid-Bugs-To: http://moblin.org/projects/syncevolution\n"
|
"Report-Msgid-Bugs-To: https://syncevolution.org/\n"
|
||||||
"POT-Creation-Date: 2009-10-16 11:24+0000\n"
|
"POT-Creation-Date: 2009-10-16 11:24+0000\n"
|
||||||
"PO-Revision-Date: 2009-11-16 16:28+0200\n"
|
"PO-Revision-Date: 2009-11-16 16:28+0200\n"
|
||||||
"Last-Translator: Yousef Abu Al Naser <yousef@itsoftex.com>\n"
|
"Last-Translator: Yousef Abu Al Naser <yousef@itsoftex.com>\n"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: syncevolution.master\n"
|
"Project-Id-Version: syncevolution.master\n"
|
||||||
"Report-Msgid-Bugs-To: http://moblin.org/projects/syncevolution\n"
|
"Report-Msgid-Bugs-To: https://syncevolution.org/\n"
|
||||||
"POT-Creation-Date: 2010-05-22 09:19+0000\n"
|
"POT-Creation-Date: 2010-05-22 09:19+0000\n"
|
||||||
"PO-Revision-Date: \n"
|
"PO-Revision-Date: \n"
|
||||||
"Last-Translator: astur <malditoastur@gmail.com>\n"
|
"Last-Translator: astur <malditoastur@gmail.com>\n"
|
||||||
|
|
2
po/ca.po
2
po/ca.po
|
@ -7,7 +7,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Syncevolution 2.x\n"
|
"Project-Id-Version: Syncevolution 2.x\n"
|
||||||
"Report-Msgid-Bugs-To: http://moblin.org/projects/syncevolution\n"
|
"Report-Msgid-Bugs-To: https://syncevolution.org/\n"
|
||||||
"POT-Creation-Date: 2009-08-15 09:21+0000\n"
|
"POT-Creation-Date: 2009-08-15 09:21+0000\n"
|
||||||
"PO-Revision-Date: 2010-01-02 14:18+0100\n"
|
"PO-Revision-Date: 2010-01-02 14:18+0100\n"
|
||||||
"Last-Translator: Gil Forcada <gilforcada@guifi.net>\n"
|
"Last-Translator: Gil Forcada <gilforcada@guifi.net>\n"
|
||||||
|
|
2
po/da.po
2
po/da.po
|
@ -7,7 +7,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: syncevolution\n"
|
"Project-Id-Version: syncevolution\n"
|
||||||
"Report-Msgid-Bugs-To: http://moblin.org/projects/syncevolution\n"
|
"Report-Msgid-Bugs-To: https://syncevolution.org/\n"
|
||||||
"POT-Creation-Date: 2009-11-19 18:24+0000\n"
|
"POT-Creation-Date: 2009-11-19 18:24+0000\n"
|
||||||
"PO-Revision-Date: 2009-11-24 22:25+0100\n"
|
"PO-Revision-Date: 2009-11-24 22:25+0100\n"
|
||||||
"Last-Translator: Kris Thomsen <lakristho@gmail.com>\n"
|
"Last-Translator: Kris Thomsen <lakristho@gmail.com>\n"
|
||||||
|
|
2
po/gl.po
2
po/gl.po
|
@ -6,7 +6,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: http://moblin.org/projects/syncevolution\n"
|
"Report-Msgid-Bugs-To: https://syncevolution.org/\n"
|
||||||
"POT-Creation-Date: 2009-10-01 19:27+0000\n"
|
"POT-Creation-Date: 2009-10-01 19:27+0000\n"
|
||||||
"PO-Revision-Date: 2009-10-14 21:52+0200\n"
|
"PO-Revision-Date: 2009-10-14 21:52+0200\n"
|
||||||
"Last-Translator: Xosé <xosecalvo@gmail.com>\n"
|
"Last-Translator: Xosé <xosecalvo@gmail.com>\n"
|
||||||
|
|
2
po/hu.po
2
po/hu.po
|
@ -6,7 +6,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: syncevolution\n"
|
"Project-Id-Version: syncevolution\n"
|
||||||
"Report-Msgid-Bugs-To: http://moblin.org/projects/syncevolution\n"
|
"Report-Msgid-Bugs-To: https://syncevolution.org/\n"
|
||||||
"POT-Creation-Date: 2009-12-21 18:45+0000\n"
|
"POT-Creation-Date: 2009-12-21 18:45+0000\n"
|
||||||
"PO-Revision-Date: 2010-01-26 16:07+0100\n"
|
"PO-Revision-Date: 2010-01-26 16:07+0100\n"
|
||||||
"Last-Translator: Gergely Lónyai <aleph@mandriva.org>\n"
|
"Last-Translator: Gergely Lónyai <aleph@mandriva.org>\n"
|
||||||
|
|
2
po/id.po
2
po/id.po
|
@ -2,7 +2,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: syncevolution\n"
|
"Project-Id-Version: syncevolution\n"
|
||||||
"Report-Msgid-Bugs-To: http://moblin.org/projects/syncevolution\n"
|
"Report-Msgid-Bugs-To: https://syncevolution.org/\n"
|
||||||
"POT-Creation-Date: 2009-10-01 19:27+0000\n"
|
"POT-Creation-Date: 2009-10-01 19:27+0000\n"
|
||||||
"PO-Revision-Date: \n"
|
"PO-Revision-Date: \n"
|
||||||
"Last-Translator: Andika Triwidada <andika@gmail.com>\n"
|
"Last-Translator: Andika Triwidada <andika@gmail.com>\n"
|
||||||
|
|
2
po/ro.po
2
po/ro.po
|
@ -7,7 +7,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: syncevolution\n"
|
"Project-Id-Version: syncevolution\n"
|
||||||
"Report-Msgid-Bugs-To: http://moblin.org/projects/syncevolution\n"
|
"Report-Msgid-Bugs-To: https://syncevolution.org/\n"
|
||||||
"POT-Creation-Date: 2009-10-01 19:27+0000\n"
|
"POT-Creation-Date: 2009-10-01 19:27+0000\n"
|
||||||
"PO-Revision-Date: 2009-10-03 20:23+0200\n"
|
"PO-Revision-Date: 2009-10-03 20:23+0200\n"
|
||||||
"Last-Translator: Cosmin Bordeianu <elloxar@gmail.com>\n"
|
"Last-Translator: Cosmin Bordeianu <elloxar@gmail.com>\n"
|
||||||
|
|
2
po/sk.po
2
po/sk.po
|
@ -6,7 +6,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: syncevolution.master\n"
|
"Project-Id-Version: syncevolution.master\n"
|
||||||
"Report-Msgid-Bugs-To: http://moblin.org/projects/syncevolution\n"
|
"Report-Msgid-Bugs-To: https://syncevolution.org/\n"
|
||||||
"POT-Creation-Date: 2010-04-21 09:23+0000\n"
|
"POT-Creation-Date: 2010-04-21 09:23+0000\n"
|
||||||
"PO-Revision-Date: 2010-04-20 23:45+0200\n"
|
"PO-Revision-Date: 2010-04-20 23:45+0200\n"
|
||||||
"Last-Translator: Tomáš Virgl <tomas@virgl.net>\n"
|
"Last-Translator: Tomáš Virgl <tomas@virgl.net>\n"
|
||||||
|
|
2
po/th.po
2
po/th.po
|
@ -6,7 +6,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: syncevolution\n"
|
"Project-Id-Version: syncevolution\n"
|
||||||
"Report-Msgid-Bugs-To: http://moblin.org/projects/syncevolution\n"
|
"Report-Msgid-Bugs-To: https://syncevolution.org/\n"
|
||||||
"POT-Creation-Date: 2009-12-21 18:45+0000\n"
|
"POT-Creation-Date: 2009-12-21 18:45+0000\n"
|
||||||
"PO-Revision-Date: 2010-01-19 22:07+0700\n"
|
"PO-Revision-Date: 2010-01-19 22:07+0700\n"
|
||||||
"Last-Translator: Anuchit Chalothorn <anoochit@gmail.com>\n"
|
"Last-Translator: Anuchit Chalothorn <anoochit@gmail.com>\n"
|
||||||
|
|
2
po/tr.po
2
po/tr.po
|
@ -6,7 +6,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: http://moblin.org/projects/syncevolution\n"
|
"Report-Msgid-Bugs-To: https://syncevolution.org/\n"
|
||||||
"POT-Creation-Date: 2010-05-19 09:19+0000\n"
|
"POT-Creation-Date: 2010-05-19 09:19+0000\n"
|
||||||
"PO-Revision-Date: 2010-05-19 10:57-0500\n"
|
"PO-Revision-Date: 2010-05-19 10:57-0500\n"
|
||||||
"Last-Translator: Ahmet Özgür Erdemli <dbl2010@gmail.com>\n"
|
"Last-Translator: Ahmet Özgür Erdemli <dbl2010@gmail.com>\n"
|
||||||
|
|
532
src/async.patch
532
src/async.patch
|
@ -1,532 +0,0 @@
|
||||||
This patch demonstrates how switching from the current, synchronous
|
|
||||||
to the corresponding asynchronous API could work. This helps to
|
|
||||||
avoid some timeouts with EDS-DBus, but not all: the e_book_async_get_changes()
|
|
||||||
call still times out.
|
|
||||||
|
|
||||||
Index: src/EvolutionContactSource.cpp
|
|
||||||
===================================================================
|
|
||||||
RCS file: /cvsroot/sync4jevolution/sync4jevolution/src/EvolutionContactSource.cpp,v
|
|
||||||
retrieving revision 1.50
|
|
||||||
diff -c -r1.50 EvolutionContactSource.cpp
|
|
||||||
*** src/EvolutionContactSource.cpp 3 Jan 2007 20:58:41 -0000 1.50
|
|
||||||
--- src/EvolutionContactSource.cpp 22 Feb 2007 19:27:50 -0000
|
|
||||||
***************
|
|
||||||
*** 27,32 ****
|
|
||||||
--- 27,33 ----
|
|
||||||
#ifdef ENABLE_EBOOK
|
|
||||||
|
|
||||||
#include "EvolutionContactSource.h"
|
|
||||||
+ #include <libebook/e-book-view.h>
|
|
||||||
|
|
||||||
#include <common/base/Log.h>
|
|
||||||
#include "vocl/VConverter.h"
|
|
||||||
***************
|
|
||||||
*** 154,159 ****
|
|
||||||
--- 155,207 ----
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ void EvolutionContactSource::addContacts(void *custom, GList *nextItem)
|
|
||||||
+ {
|
|
||||||
+ EvolutionContactSource *source = (EvolutionContactSource *)custom;
|
|
||||||
+
|
|
||||||
+ while (nextItem) {
|
|
||||||
+ const char *uid = (const char *)e_contact_get_const(E_CONTACT(nextItem->data),
|
|
||||||
+ E_CONTACT_UID);
|
|
||||||
+ source->m_allItems.addItem(uid);
|
|
||||||
+ nextItem = nextItem->next;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ void EvolutionContactSource::addChanges(EBook *book,
|
|
||||||
+ EBookStatus status,
|
|
||||||
+ GList *nextItem,
|
|
||||||
+ gpointer custom)
|
|
||||||
+ {
|
|
||||||
+ EvolutionContactSource *source = (EvolutionContactSource *)custom;
|
|
||||||
+ source->m_status = status;
|
|
||||||
+
|
|
||||||
+ while (nextItem) {
|
|
||||||
+ EBookChange *ebc = (EBookChange *)nextItem->data;
|
|
||||||
+
|
|
||||||
+ if (ebc->contact) {
|
|
||||||
+ const char *uid = (const char *)e_contact_get_const( ebc->contact, E_CONTACT_UID );
|
|
||||||
+
|
|
||||||
+ if (uid) {
|
|
||||||
+ switch (ebc->change_type) {
|
|
||||||
+ case E_BOOK_CHANGE_CARD_ADDED:
|
|
||||||
+ source->m_newItems.addItem(uid);
|
|
||||||
+ break;
|
|
||||||
+ case E_BOOK_CHANGE_CARD_MODIFIED:
|
|
||||||
+ source->m_updatedItems.addItem(uid);
|
|
||||||
+ break;
|
|
||||||
+ case E_BOOK_CHANGE_CARD_DELETED:
|
|
||||||
+ source->m_deletedItems.addItem(uid);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ nextItem = nextItem->next;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ source->m_loop.quit();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+
|
|
||||||
void EvolutionContactSource::beginSyncThrow(bool needAll,
|
|
||||||
bool needPartial,
|
|
||||||
bool deleteLocal)
|
|
||||||
***************
|
|
||||||
*** 161,234 ****
|
|
||||||
GError *gerror = NULL;
|
|
||||||
|
|
||||||
if (deleteLocal) {
|
|
||||||
! eptr<EBookQuery> allItemsQuery( e_book_query_any_field_contains(""), "query" );
|
|
||||||
! GList *nextItem;
|
|
||||||
! if (!e_book_get_contacts( m_addressbook, allItemsQuery, &nextItem, &gerror )) {
|
|
||||||
! throwError( "reading all items", gerror );
|
|
||||||
! }
|
|
||||||
! while (nextItem) {
|
|
||||||
! const char *uid = (const char *)e_contact_get_const(E_CONTACT(nextItem->data),
|
|
||||||
! E_CONTACT_UID);
|
|
||||||
! if (!e_book_remove_contact( m_addressbook, uid, &gerror ) ) {
|
|
||||||
! throwError( string( "deleting contact " ) + uid,
|
|
||||||
gerror );
|
|
||||||
}
|
|
||||||
- nextItem = nextItem->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needAll) {
|
|
||||||
! eptr<EBookQuery> allItemsQuery( e_book_query_any_field_contains(""), "query" );
|
|
||||||
! GList *nextItem;
|
|
||||||
! if (!e_book_get_contacts( m_addressbook, allItemsQuery, &nextItem, &gerror )) {
|
|
||||||
! throwError( "reading all items", gerror );
|
|
||||||
! }
|
|
||||||
! while (nextItem) {
|
|
||||||
! const char *uid = (const char *)e_contact_get_const(E_CONTACT(nextItem->data),
|
|
||||||
! E_CONTACT_UID);
|
|
||||||
! m_allItems.addItem(uid);
|
|
||||||
! nextItem = nextItem->next;
|
|
||||||
! }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needPartial) {
|
|
||||||
GList *nextItem;
|
|
||||||
if (!e_book_get_changes( m_addressbook, (char *)m_changeId.c_str(), &nextItem, &gerror )) {
|
|
||||||
throwError( "reading changes", gerror );
|
|
||||||
}
|
|
||||||
! while (nextItem) {
|
|
||||||
! EBookChange *ebc = (EBookChange *)nextItem->data;
|
|
||||||
!
|
|
||||||
! if (ebc->contact) {
|
|
||||||
! const char *uid = (const char *)e_contact_get_const( ebc->contact, E_CONTACT_UID );
|
|
||||||
!
|
|
||||||
! if (uid) {
|
|
||||||
! switch (ebc->change_type) {
|
|
||||||
! case E_BOOK_CHANGE_CARD_ADDED:
|
|
||||||
! m_newItems.addItem(uid);
|
|
||||||
! break;
|
|
||||||
! case E_BOOK_CHANGE_CARD_MODIFIED:
|
|
||||||
! m_updatedItems.addItem(uid);
|
|
||||||
! break;
|
|
||||||
! case E_BOOK_CHANGE_CARD_DELETED:
|
|
||||||
! m_deletedItems.addItem(uid);
|
|
||||||
! break;
|
|
||||||
! }
|
|
||||||
! }
|
|
||||||
! }
|
|
||||||
! nextItem = nextItem->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EvolutionContactSource::endSyncThrow()
|
|
||||||
{
|
|
||||||
if (m_isModified) {
|
|
||||||
- GError *gerror = NULL;
|
|
||||||
- GList *nextItem;
|
|
||||||
// move change_id forward so that our own changes are not listed the next time
|
|
||||||
! if (!e_book_get_changes( m_addressbook, (char *)m_changeId.c_str(), &nextItem, &gerror )) {
|
|
||||||
! throwError( "reading changes", gerror );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resetItems();
|
|
||||||
--- 209,264 ----
|
|
||||||
GError *gerror = NULL;
|
|
||||||
|
|
||||||
if (deleteLocal) {
|
|
||||||
! m_allItems.clear();
|
|
||||||
! listAllContacts(addContacts, this);
|
|
||||||
!
|
|
||||||
! EvolutionSyncSource::itemList::const_iterator it;
|
|
||||||
! for (it = m_allItems.begin();
|
|
||||||
! it != m_allItems.end();
|
|
||||||
! ++it) {
|
|
||||||
! if (!e_book_remove_contact( m_addressbook, it->c_str(), &gerror ) ) {
|
|
||||||
! throwError( string( "deleting contact " ) + *it,
|
|
||||||
gerror );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+ m_allItems.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needAll) {
|
|
||||||
! listAllContacts(addContacts, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needPartial) {
|
|
||||||
+ #if 0
|
|
||||||
+ // times out on N770
|
|
||||||
+ GError *gerror = NULL;
|
|
||||||
GList *nextItem;
|
|
||||||
if (!e_book_get_changes( m_addressbook, (char *)m_changeId.c_str(), &nextItem, &gerror )) {
|
|
||||||
throwError( "reading changes", gerror );
|
|
||||||
}
|
|
||||||
! addChanges(m_addressbook, E_BOOK_ERROR_OK, nextItem, (gpointer)this);
|
|
||||||
! #else
|
|
||||||
! if (e_book_async_get_changes(m_addressbook, (char *)m_changeId.c_str(), addChanges, this)) {
|
|
||||||
! throwError( "reading changes", gerror );
|
|
||||||
}
|
|
||||||
+ m_loop.run();
|
|
||||||
+ if (m_status != E_BOOK_ERROR_OK) {
|
|
||||||
+ throw runtime_error("reading changes stopped with an error");
|
|
||||||
+ }
|
|
||||||
+ #endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EvolutionContactSource::endSyncThrow()
|
|
||||||
{
|
|
||||||
if (m_isModified) {
|
|
||||||
// move change_id forward so that our own changes are not listed the next time
|
|
||||||
! if (e_book_async_get_changes(m_addressbook, (char *)m_changeId.c_str(), addChanges, this)) {
|
|
||||||
! throw runtime_error("reading changes");
|
|
||||||
! }
|
|
||||||
! m_loop.run();
|
|
||||||
! if (m_status != E_BOOK_ERROR_OK) {
|
|
||||||
! throw runtime_error("reading changes stopped with an error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resetItems();
|
|
||||||
***************
|
|
||||||
*** 241,263 ****
|
|
||||||
m_addressbook = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
! void EvolutionContactSource::exportData(ostream &out)
|
|
||||||
{
|
|
||||||
! eptr<EBookQuery> allItemsQuery( e_book_query_any_field_contains(""), "query" );
|
|
||||||
! GList *nextItem;
|
|
||||||
! GError *gerror = NULL;
|
|
||||||
! if (!e_book_get_contacts( m_addressbook, allItemsQuery, &nextItem, &gerror )) {
|
|
||||||
! throwError( "reading all items", gerror );
|
|
||||||
! }
|
|
||||||
while (nextItem) {
|
|
||||||
eptr<char> vcardstr(e_vcard_to_string(&E_CONTACT(nextItem->data)->parent,
|
|
||||||
EVC_FORMAT_VCARD_30));
|
|
||||||
|
|
||||||
! out << (const char *)vcardstr << "\r\n\r\n";
|
|
||||||
nextItem = nextItem->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SyncItem *EvolutionContactSource::createItem( const string &uid, SyncState state )
|
|
||||||
{
|
|
||||||
logItem( uid, "extracting from EV" );
|
|
||||||
--- 271,296 ----
|
|
||||||
m_addressbook = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
!
|
|
||||||
! static void dumpContacts(void *custom, GList *nextItem)
|
|
||||||
{
|
|
||||||
! ostream *out = (ostream *)custom;
|
|
||||||
!
|
|
||||||
while (nextItem) {
|
|
||||||
eptr<char> vcardstr(e_vcard_to_string(&E_CONTACT(nextItem->data)->parent,
|
|
||||||
EVC_FORMAT_VCARD_30));
|
|
||||||
|
|
||||||
! *out << (const char *)vcardstr << "\r\n\r\n";
|
|
||||||
!
|
|
||||||
nextItem = nextItem->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ void EvolutionContactSource::exportData(ostream &out)
|
|
||||||
+ {
|
|
||||||
+ listAllContacts(dumpContacts, (void *)&out);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
SyncItem *EvolutionContactSource::createItem( const string &uid, SyncState state )
|
|
||||||
{
|
|
||||||
logItem( uid, "extracting from EV" );
|
|
||||||
***************
|
|
||||||
*** 773,776 ****
|
|
||||||
--- 806,876 ----
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ class EvolutionContactListAll {
|
|
||||||
+ public:
|
|
||||||
+ EvolutionContactListAll(void (*processList)(void *custom, GList *list), void *custom, EvolutionContactSource &source):
|
|
||||||
+ m_processList(processList),
|
|
||||||
+ m_custom(custom),
|
|
||||||
+ m_source(source),
|
|
||||||
+ m_status(E_BOOK_VIEW_STATUS_OK)
|
|
||||||
+ {}
|
|
||||||
+
|
|
||||||
+ static void contactsAdded(EBookView *ebookview,
|
|
||||||
+ gpointer arg1,
|
|
||||||
+ gpointer user_data) {
|
|
||||||
+ EvolutionContactListAll *listAll = (EvolutionContactListAll *)user_data;
|
|
||||||
+ listAll->m_processList(listAll->m_custom, (GList *)arg1);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ static void sequenceDone(EBookView *ebookview,
|
|
||||||
+ gint arg1,
|
|
||||||
+ gpointer user_data) {
|
|
||||||
+ EvolutionContactListAll *listAll = (EvolutionContactListAll *)user_data;
|
|
||||||
+ listAll->m_status = (EBookViewStatus)arg1;
|
|
||||||
+ listAll->m_source.m_loop.quit();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /** throw an error exception if an error occurred */
|
|
||||||
+ void checkStatus() {
|
|
||||||
+ if (m_status != E_BOOK_VIEW_STATUS_OK) {
|
|
||||||
+ throw runtime_error("iterating over all contacts failed");
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ private:
|
|
||||||
+ void (*m_processList)(void *custom, GList *list);
|
|
||||||
+ void *m_custom;
|
|
||||||
+ EvolutionContactSource &m_source;
|
|
||||||
+ EBookViewStatus m_status;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ void EvolutionContactSource::listAllContacts(void (*processList)(void *custom, GList *list), void *custom)
|
|
||||||
+ {
|
|
||||||
+ eptr<EBookQuery> allItemsQuery( e_book_query_any_field_contains(""), "query" );
|
|
||||||
+ GError *gerror = NULL;
|
|
||||||
+ EBookView *viewptr;
|
|
||||||
+
|
|
||||||
+ if (e_book_get_book_view(m_addressbook, allItemsQuery, NULL, -1, &viewptr, &gerror)) {
|
|
||||||
+ eptr<EBookView, GObject> view(viewptr);
|
|
||||||
+ EvolutionContactListAll listAll(processList, custom, *this);
|
|
||||||
+
|
|
||||||
+ g_signal_connect(viewptr, "contacts-added", G_CALLBACK(listAll.contactsAdded), &listAll);
|
|
||||||
+ g_signal_connect(viewptr, "sequence-complete", G_CALLBACK(listAll.sequenceDone), &listAll);
|
|
||||||
+ e_book_view_start(view);
|
|
||||||
+ m_loop.run();
|
|
||||||
+ e_book_view_stop(view);
|
|
||||||
+ // workaround for http://bugzilla.gnome.org/show_bug.cgi?id=399011
|
|
||||||
+ // Without the sleep() EDS often (but not always) crashes in e_book_backend_get_book_views()
|
|
||||||
+ // during one of the following calls.
|
|
||||||
+ sleep(1);
|
|
||||||
+ listAll.checkStatus();
|
|
||||||
+ } else {
|
|
||||||
+ throwError( "getting view on addressbook", gerror );
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
#endif /* ENABLE_EBOOK */
|
|
||||||
Index: src/EvolutionContactSource.h
|
|
||||||
===================================================================
|
|
||||||
RCS file: /cvsroot/sync4jevolution/sync4jevolution/src/EvolutionContactSource.h,v
|
|
||||||
retrieving revision 1.22
|
|
||||||
diff -c -r1.22 EvolutionContactSource.h
|
|
||||||
*** src/EvolutionContactSource.h 10 Dec 2006 17:35:18 -0000 1.22
|
|
||||||
--- src/EvolutionContactSource.h 22 Feb 2007 19:27:50 -0000
|
|
||||||
***************
|
|
||||||
*** 32,37 ****
|
|
||||||
--- 32,49 ----
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
/**
|
|
||||||
+ * callback used by EvolutionContactSource::listAll() and
|
|
||||||
+ */
|
|
||||||
+ class EvolutionCallback
|
|
||||||
+ {
|
|
||||||
+ public:
|
|
||||||
+ /**
|
|
||||||
+ * Called to iterate over data. Content of list depends on context.
|
|
||||||
+ */
|
|
||||||
+ virtual void processList(GList *list) = 0;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ /**
|
|
||||||
* Implements access to Evolution address books.
|
|
||||||
*/
|
|
||||||
class EvolutionContactSource : public EvolutionSyncSource
|
|
||||||
***************
|
|
||||||
*** 81,87 ****
|
|
||||||
// implementation of SyncSource
|
|
||||||
//
|
|
||||||
virtual ArrayElement *clone() { return new EvolutionContactSource(*this); }
|
|
||||||
!
|
|
||||||
protected:
|
|
||||||
//
|
|
||||||
// implementation of EvolutionSyncSource callbacks
|
|
||||||
--- 93,102 ----
|
|
||||||
// implementation of SyncSource
|
|
||||||
//
|
|
||||||
virtual ArrayElement *clone() { return new EvolutionContactSource(*this); }
|
|
||||||
!
|
|
||||||
! /** start and stop event processing on this source */
|
|
||||||
! EvolutionAsync m_loop;
|
|
||||||
!
|
|
||||||
protected:
|
|
||||||
//
|
|
||||||
// implementation of EvolutionSyncSource callbacks
|
|
||||||
***************
|
|
||||||
*** 142,149 ****
|
|
||||||
--- 157,191 ----
|
|
||||||
insert("CALURI");
|
|
||||||
}
|
|
||||||
} m_uniqueProperties;
|
|
||||||
+
|
|
||||||
+ /**
|
|
||||||
+ * extracts all contacts
|
|
||||||
+ *
|
|
||||||
+ * @param processList is fed the contacts, possibly in multiple chunks
|
|
||||||
+ * @param custom pointer passed through to processList
|
|
||||||
+ */
|
|
||||||
+ void listAllContacts(void (*processList)(void *custom, GList *list), void *custom);
|
|
||||||
+
|
|
||||||
+ /**
|
|
||||||
+ * callback for listAllContacts() which adds all contacts to m_allItems
|
|
||||||
+ */
|
|
||||||
+ static void addContacts(void *custom, GList *nextItem);
|
|
||||||
+
|
|
||||||
+ /**
|
|
||||||
+ * EBookListCallback for beginSyncThrow()'s e_book_async_get_changes ()
|
|
||||||
+ */
|
|
||||||
+ static void addChanges(EBook *book,
|
|
||||||
+ EBookStatus status,
|
|
||||||
+ GList *nextItem,
|
|
||||||
+ gpointer custom);
|
|
||||||
+ /**
|
|
||||||
+ * status passed to addChanges()
|
|
||||||
+ */
|
|
||||||
+ EBookStatus m_status;
|
|
||||||
};
|
|
||||||
|
|
||||||
+
|
|
||||||
+
|
|
||||||
#endif // ENABLE_EBOOK
|
|
||||||
|
|
||||||
#endif // INCL_EVOLUTIONCONTACTSOURCE
|
|
||||||
Index: src/EvolutionSmartPtr.h
|
|
||||||
===================================================================
|
|
||||||
RCS file: /cvsroot/sync4jevolution/sync4jevolution/src/EvolutionSmartPtr.h,v
|
|
||||||
retrieving revision 1.8
|
|
||||||
diff -c -r1.8 EvolutionSmartPtr.h
|
|
||||||
*** src/EvolutionSmartPtr.h 10 Dec 2006 17:35:19 -0000 1.8
|
|
||||||
--- src/EvolutionSmartPtr.h 22 Feb 2007 19:27:50 -0000
|
|
||||||
***************
|
|
||||||
*** 34,39 ****
|
|
||||||
--- 34,40 ----
|
|
||||||
|
|
||||||
void inline unref( char *pointer ) { free( pointer ); }
|
|
||||||
void inline unref( GObject *pointer ) { g_object_unref( pointer ); }
|
|
||||||
+ void inline unref( GMainLoop *pointer ) { g_main_loop_unref( pointer ); }
|
|
||||||
#ifdef ENABLE_EBOOK
|
|
||||||
void inline unref( EBookQuery *pointer ) { e_book_query_unref( pointer ); }
|
|
||||||
#endif
|
|
||||||
Index: src/EvolutionSyncClient.cpp
|
|
||||||
===================================================================
|
|
||||||
RCS file: /cvsroot/sync4jevolution/sync4jevolution/src/EvolutionSyncClient.cpp,v
|
|
||||||
retrieving revision 1.24
|
|
||||||
diff -c -r1.24 EvolutionSyncClient.cpp
|
|
||||||
*** src/EvolutionSyncClient.cpp 17 Dec 2006 16:33:45 -0000 1.24
|
|
||||||
--- src/EvolutionSyncClient.cpp 22 Feb 2007 19:27:50 -0000
|
|
||||||
***************
|
|
||||||
*** 432,438 ****
|
|
||||||
int res = DMTClientConfig::readDevInfoConfig(syncMLNode, syncMLNode);
|
|
||||||
|
|
||||||
// always read device ID from the traditional property "deviceId"
|
|
||||||
! eptr<char> tmp(syncMLNode.readPropertyValue("deviceId"));
|
|
||||||
deviceConfig.setDevID(tmp);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
--- 432,438 ----
|
|
||||||
int res = DMTClientConfig::readDevInfoConfig(syncMLNode, syncMLNode);
|
|
||||||
|
|
||||||
// always read device ID from the traditional property "deviceId"
|
|
||||||
! arrayptr<char> tmp(syncMLNode.readPropertyValue("deviceId"));
|
|
||||||
deviceConfig.setDevID(tmp);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
***************
|
|
||||||
*** 482,489 ****
|
|
||||||
// redirect logging as soon as possible
|
|
||||||
SourceList sourceList(m_server, m_doLogging);
|
|
||||||
|
|
||||||
! eptr<char> logdir(config.getSyncMLNode()->readPropertyValue("logdir"));
|
|
||||||
! eptr<char> maxlogdirs(config.getSyncMLNode()->readPropertyValue("maxlogdirs"));
|
|
||||||
sourceList.setLogdir(logdir, atoi(maxlogdirs));
|
|
||||||
|
|
||||||
SyncSourceConfig *sourceconfigs = config.getSyncSourceConfigs();
|
|
||||||
--- 482,489 ----
|
|
||||||
// redirect logging as soon as possible
|
|
||||||
SourceList sourceList(m_server, m_doLogging);
|
|
||||||
|
|
||||||
! arrayptr<char> logdir(config.getSyncMLNode()->readPropertyValue("logdir"));
|
|
||||||
! arrayptr<char> maxlogdirs(config.getSyncMLNode()->readPropertyValue("maxlogdirs"));
|
|
||||||
sourceList.setLogdir(logdir, atoi(maxlogdirs));
|
|
||||||
|
|
||||||
SyncSourceConfig *sourceconfigs = config.getSyncSourceConfigs();
|
|
||||||
Index: src/EvolutionSyncSource.h
|
|
||||||
===================================================================
|
|
||||||
RCS file: /cvsroot/sync4jevolution/sync4jevolution/src/EvolutionSyncSource.h,v
|
|
||||||
retrieving revision 1.24
|
|
||||||
diff -c -r1.24 EvolutionSyncSource.h
|
|
||||||
*** src/EvolutionSyncSource.h 10 Dec 2006 17:35:19 -0000 1.24
|
|
||||||
--- src/EvolutionSyncSource.h 22 Feb 2007 19:27:51 -0000
|
|
||||||
***************
|
|
||||||
*** 33,38 ****
|
|
||||||
--- 33,40 ----
|
|
||||||
#include <spdm/ManagementNode.h>
|
|
||||||
#include <base/Log.h>
|
|
||||||
|
|
||||||
+ #include <EvolutionSmartPtr.h>
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* This class implements the functionality shared by
|
|
||||||
* both EvolutionCalenderSource and EvolutionContactSource:
|
|
||||||
***************
|
|
||||||
*** 371,374 ****
|
|
||||||
--- 373,400 ----
|
|
||||||
string m_user, m_passwd;
|
|
||||||
};
|
|
||||||
|
|
||||||
+ /**
|
|
||||||
+ * Utility class which hides the mechanisms needed to handle events
|
|
||||||
+ * during asynchronous calls.
|
|
||||||
+ */
|
|
||||||
+ class EvolutionAsync {
|
|
||||||
+ public:
|
|
||||||
+ EvolutionAsync() :
|
|
||||||
+ m_loop(g_main_loop_new(NULL, FALSE), "main loop")
|
|
||||||
+ {}
|
|
||||||
+
|
|
||||||
+ /** start processing events */
|
|
||||||
+ void run() {
|
|
||||||
+ g_main_loop_run(m_loop);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /** stop processing events, to be called inside run() by callback */
|
|
||||||
+ void quit() {
|
|
||||||
+ g_main_loop_quit(m_loop);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ private:
|
|
||||||
+ eptr<GMainLoop> m_loop;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
#endif // INCL_EVOLUTIONSYNCSOURCE
|
|
|
@ -58,7 +58,7 @@ void ActiveSyncCalendarSource::beginSync(const std::string &lastToken, const std
|
||||||
// re-populate cache from storage, without any item data
|
// re-populate cache from storage, without any item data
|
||||||
ConfigProps props;
|
ConfigProps props;
|
||||||
m_trackingNode->readProperties(props);
|
m_trackingNode->readProperties(props);
|
||||||
BOOST_FOREACH(const StringPair &prop, props) {
|
for (const auto &prop: props) {
|
||||||
const std::string &easid = prop.first;
|
const std::string &easid = prop.first;
|
||||||
const std::string &value = prop.second;
|
const std::string &value = prop.second;
|
||||||
size_t pos = value.find('/');
|
size_t pos = value.find('/');
|
||||||
|
@ -70,9 +70,9 @@ void ActiveSyncCalendarSource::beginSync(const std::string &lastToken, const std
|
||||||
size_t nextpos = value.find('/', pos + 1);
|
size_t nextpos = value.find('/', pos + 1);
|
||||||
if (nextpos != value.npos) {
|
if (nextpos != value.npos) {
|
||||||
std::string uid = m_escape.unescape(value.substr(pos + 1, nextpos - pos - 1));
|
std::string uid = m_escape.unescape(value.substr(pos + 1, nextpos - pos - 1));
|
||||||
boost::shared_ptr<Event> &eventptr = m_cache[easid];
|
std::shared_ptr<Event> &eventptr = m_cache[easid];
|
||||||
if (!eventptr) {
|
if (!eventptr) {
|
||||||
eventptr = boost::shared_ptr<Event>(new Event);
|
eventptr = std::make_shared<Event>();
|
||||||
}
|
}
|
||||||
eventptr->m_easid = easid;
|
eventptr->m_easid = easid;
|
||||||
eventptr->m_uid = uid;
|
eventptr->m_uid = uid;
|
||||||
|
@ -104,7 +104,7 @@ void ActiveSyncCalendarSource::beginSync(const std::string &lastToken, const std
|
||||||
for (bool firstIteration = true;
|
for (bool firstIteration = true;
|
||||||
moreAvailable;
|
moreAvailable;
|
||||||
firstIteration = false) {
|
firstIteration = false) {
|
||||||
gchar *buffer = NULL;
|
gchar *buffer = nullptr;
|
||||||
GErrorCXX gerror;
|
GErrorCXX gerror;
|
||||||
EASItemsCXX created, updated;
|
EASItemsCXX created, updated;
|
||||||
EASIdsCXX deleted;
|
EASIdsCXX deleted;
|
||||||
|
@ -142,7 +142,7 @@ void ActiveSyncCalendarSource::beginSync(const std::string &lastToken, const std
|
||||||
|
|
||||||
|
|
||||||
// populate ID lists and content cache
|
// populate ID lists and content cache
|
||||||
BOOST_FOREACH(EasItemInfo *item, created) {
|
for (EasItemInfo *item: created) {
|
||||||
if (!item->server_id) {
|
if (!item->server_id) {
|
||||||
throwError(SE_HERE, "no server ID for new eas item");
|
throwError(SE_HERE, "no server ID for new eas item");
|
||||||
}
|
}
|
||||||
|
@ -155,13 +155,13 @@ void ActiveSyncCalendarSource::beginSync(const std::string &lastToken, const std
|
||||||
throwError(SE_HERE, StringPrintf("no body returned for new eas item %s", easid.c_str()));
|
throwError(SE_HERE, StringPrintf("no body returned for new eas item %s", easid.c_str()));
|
||||||
}
|
}
|
||||||
Event &event = setItemData(easid, item->data);
|
Event &event = setItemData(easid, item->data);
|
||||||
BOOST_FOREACH(const std::string &subid, event.m_subids) {
|
for (const std::string &subid: event.m_subids) {
|
||||||
SE_LOG_DEBUG(getDisplayName(), "new eas item %s = uid %s + rid %s",
|
SE_LOG_DEBUG(getDisplayName(), "new eas item %s = uid %s + rid %s",
|
||||||
easid.c_str(), event.m_uid.c_str(), subid.c_str());
|
easid.c_str(), event.m_uid.c_str(), subid.c_str());
|
||||||
addItem(createLUID(easid, subid), NEW);
|
addItem(createLUID(easid, subid), NEW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BOOST_FOREACH(EasItemInfo *item, updated) {
|
for (EasItemInfo *item: updated) {
|
||||||
if (!item->server_id) {
|
if (!item->server_id) {
|
||||||
throwError(SE_HERE, "no server ID for updated eas item");
|
throwError(SE_HERE, "no server ID for updated eas item");
|
||||||
}
|
}
|
||||||
|
@ -174,13 +174,13 @@ void ActiveSyncCalendarSource::beginSync(const std::string &lastToken, const std
|
||||||
throwError(SE_HERE, StringPrintf("no body returned for updated eas item %s", easid.c_str()));
|
throwError(SE_HERE, StringPrintf("no body returned for updated eas item %s", easid.c_str()));
|
||||||
}
|
}
|
||||||
Event &event = setItemData(easid, item->data);
|
Event &event = setItemData(easid, item->data);
|
||||||
BOOST_FOREACH(const std::string &subid, event.m_subids) {
|
for (const std::string &subid: event.m_subids) {
|
||||||
SE_LOG_DEBUG(getDisplayName(), "deleted eas item %s = uid %s + rid %s",
|
SE_LOG_DEBUG(getDisplayName(), "deleted eas item %s = uid %s + rid %s",
|
||||||
easid.c_str(), event.m_uid.c_str(), subid.c_str());
|
easid.c_str(), event.m_uid.c_str(), subid.c_str());
|
||||||
addItem(createLUID(easid, subid), UPDATED);
|
addItem(createLUID(easid, subid), UPDATED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BOOST_FOREACH(const char *serverID, deleted) {
|
for (const char *serverID: deleted) {
|
||||||
if (!serverID) {
|
if (!serverID) {
|
||||||
throwError(SE_HERE, "no server ID for deleted eas item");
|
throwError(SE_HERE, "no server ID for deleted eas item");
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ void ActiveSyncCalendarSource::beginSync(const std::string &lastToken, const std
|
||||||
if (event.m_subids.empty()) {
|
if (event.m_subids.empty()) {
|
||||||
SE_LOG_DEBUG(getDisplayName(), "deleted eas item %s empty?!", easid.c_str());
|
SE_LOG_DEBUG(getDisplayName(), "deleted eas item %s empty?!", easid.c_str());
|
||||||
} else {
|
} else {
|
||||||
BOOST_FOREACH(const std::string &subid, event.m_subids) {
|
for (const std::string &subid: event.m_subids) {
|
||||||
SE_LOG_DEBUG(getDisplayName(), "deleted eas item %s = uid %s + rid %s",
|
SE_LOG_DEBUG(getDisplayName(), "deleted eas item %s = uid %s + rid %s",
|
||||||
easid.c_str(), event.m_uid.c_str(), subid.c_str());
|
easid.c_str(), event.m_uid.c_str(), subid.c_str());
|
||||||
addItem(createLUID(easid, subid), DELETED);
|
addItem(createLUID(easid, subid), DELETED);
|
||||||
|
@ -218,10 +218,10 @@ void ActiveSyncCalendarSource::beginSync(const std::string &lastToken, const std
|
||||||
|
|
||||||
// now also generate full list of all current items:
|
// now also generate full list of all current items:
|
||||||
// old items + new (added to m_events above) - deleted (removed above)
|
// old items + new (added to m_events above) - deleted (removed above)
|
||||||
BOOST_FOREACH(const EventCache::value_type &entry, m_cache) {
|
for (const auto &entry: m_cache) {
|
||||||
const std::string &easid = entry.first;
|
const std::string &easid = entry.first;
|
||||||
const boost::shared_ptr<Event> &eventptr = entry.second;
|
const std::shared_ptr<Event> &eventptr = entry.second;
|
||||||
BOOST_FOREACH(const std::string &subid, eventptr->m_subids) {
|
for (const std::string &subid: eventptr->m_subids) {
|
||||||
SE_LOG_DEBUG(getDisplayName(), "existing eas item %s = uid %s + rid %s",
|
SE_LOG_DEBUG(getDisplayName(), "existing eas item %s = uid %s + rid %s",
|
||||||
easid.c_str(), eventptr->m_uid.c_str(), subid.c_str());
|
easid.c_str(), eventptr->m_uid.c_str(), subid.c_str());
|
||||||
addItem(createLUID(easid, subid), ANY);
|
addItem(createLUID(easid, subid), ANY);
|
||||||
|
@ -233,13 +233,13 @@ std::string ActiveSyncCalendarSource::endSync(bool success)
|
||||||
{
|
{
|
||||||
m_trackingNode->clear();
|
m_trackingNode->clear();
|
||||||
if (success) {
|
if (success) {
|
||||||
BOOST_FOREACH(const EventCache::value_type &entry, m_cache) {
|
for (const auto &entry: m_cache) {
|
||||||
const std::string &easid = entry.first;
|
const std::string &easid = entry.first;
|
||||||
const boost::shared_ptr<Event> &eventptr = entry.second;
|
const std::shared_ptr<Event> &eventptr = entry.second;
|
||||||
std::stringstream buffer;
|
std::stringstream buffer;
|
||||||
buffer << "//"; // use same format as in MapSyncSource, just in case - was '/' << m_escape.escape(ids.m_revision) << '/';
|
buffer << "//"; // use same format as in MapSyncSource, just in case - was '/' << m_escape.escape(ids.m_revision) << '/';
|
||||||
buffer << m_escape.escape(eventptr->m_uid) << '/';
|
buffer << m_escape.escape(eventptr->m_uid) << '/';
|
||||||
BOOST_FOREACH(const std::string &subid, eventptr->m_subids) {
|
for (const std::string &subid: eventptr->m_subids) {
|
||||||
buffer << m_escape.escape(subid) << '/';
|
buffer << m_escape.escape(subid) << '/';
|
||||||
}
|
}
|
||||||
m_trackingNode->setProperty(easid, buffer.str());
|
m_trackingNode->setProperty(easid, buffer.str());
|
||||||
|
@ -298,7 +298,7 @@ std::string ActiveSyncCalendarSource::getDescription(const string &luid)
|
||||||
|
|
||||||
ActiveSyncCalendarSource::Event &ActiveSyncCalendarSource::findItem(const std::string &easid)
|
ActiveSyncCalendarSource::Event &ActiveSyncCalendarSource::findItem(const std::string &easid)
|
||||||
{
|
{
|
||||||
EventCache::iterator it = m_cache.find(easid);
|
auto it = m_cache.find(easid);
|
||||||
if (it == m_cache.end()) {
|
if (it == m_cache.end()) {
|
||||||
throwError(SE_HERE, STATUS_NOT_FOUND, "merged event not found: " + easid);
|
throwError(SE_HERE, STATUS_NOT_FOUND, "merged event not found: " + easid);
|
||||||
}
|
}
|
||||||
|
@ -324,12 +324,12 @@ ActiveSyncCalendarSource::Event &ActiveSyncCalendarSource::loadItem(Event &event
|
||||||
|
|
||||||
ActiveSyncCalendarSource::Event &ActiveSyncCalendarSource::setItemData(const std::string &easid, const std::string &data)
|
ActiveSyncCalendarSource::Event &ActiveSyncCalendarSource::setItemData(const std::string &easid, const std::string &data)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<Event> &eventptr = m_cache[easid];
|
std::shared_ptr<Event> &eventptr = m_cache[easid];
|
||||||
if (eventptr) {
|
if (eventptr) {
|
||||||
eventptr->m_uid.clear();
|
eventptr->m_uid.clear();
|
||||||
eventptr->m_subids.clear();
|
eventptr->m_subids.clear();
|
||||||
} else {
|
} else {
|
||||||
eventptr = boost::shared_ptr<Event>(new Event);
|
eventptr = std::make_shared<Event>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Event &event = *eventptr;
|
Event &event = *eventptr;
|
||||||
|
@ -408,10 +408,10 @@ SyncSourceRaw::InsertItemResult ActiveSyncCalendarSource::insertItem(const std::
|
||||||
const std::string &callerSubID = ids.second;
|
const std::string &callerSubID = ids.second;
|
||||||
|
|
||||||
// parse new event
|
// parse new event
|
||||||
boost::shared_ptr<Event> newEvent(new Event);
|
auto newEvent = std::make_shared<Event>();
|
||||||
newEvent->m_calendar.set(icalcomponent_new_from_string((char *)item.c_str()), // hack for old libical
|
newEvent->m_calendar.set(icalcomponent_new_from_string((char *)item.c_str()), // hack for old libical
|
||||||
"parsing iCalendar 2.0");
|
"parsing iCalendar 2.0");
|
||||||
icalcomponent *firstcomp = NULL;
|
icalcomponent *firstcomp = nullptr;
|
||||||
for (icalcomponent *comp = firstcomp = icalcomponent_get_first_component(newEvent->m_calendar, ICAL_VEVENT_COMPONENT);
|
for (icalcomponent *comp = firstcomp = icalcomponent_get_first_component(newEvent->m_calendar, ICAL_VEVENT_COMPONENT);
|
||||||
comp;
|
comp;
|
||||||
comp = icalcomponent_get_next_component(newEvent->m_calendar, ICAL_VEVENT_COMPONENT)) {
|
comp = icalcomponent_get_next_component(newEvent->m_calendar, ICAL_VEVENT_COMPONENT)) {
|
||||||
|
@ -444,7 +444,7 @@ SyncSourceRaw::InsertItemResult ActiveSyncCalendarSource::insertItem(const std::
|
||||||
// our caller didn't.
|
// our caller didn't.
|
||||||
std::string knownSubID = callerSubID;
|
std::string knownSubID = callerSubID;
|
||||||
if (easid.empty()) {
|
if (easid.empty()) {
|
||||||
EventCache::iterator it = m_cache.findByUID(newEvent->m_uid);
|
auto it = m_cache.findByUID(newEvent->m_uid);
|
||||||
if (it != m_cache.end()) {
|
if (it != m_cache.end()) {
|
||||||
easid = it->first;
|
easid = it->first;
|
||||||
knownSubID = subid;
|
knownSubID = subid;
|
||||||
|
@ -458,7 +458,7 @@ SyncSourceRaw::InsertItemResult ActiveSyncCalendarSource::insertItem(const std::
|
||||||
InsertItemResult res = ActiveSyncSource::insertItem("", item);
|
InsertItemResult res = ActiveSyncSource::insertItem("", item);
|
||||||
easid = res.m_luid;
|
easid = res.m_luid;
|
||||||
|
|
||||||
EventCache::iterator it = m_cache.find(res.m_luid);
|
auto it = m_cache.find(res.m_luid);
|
||||||
if (it != m_cache.end()) {
|
if (it != m_cache.end()) {
|
||||||
// merge into existing Event
|
// merge into existing Event
|
||||||
Event &event = loadItem(*it->second);
|
Event &event = loadItem(*it->second);
|
||||||
|
@ -499,7 +499,7 @@ SyncSourceRaw::InsertItemResult ActiveSyncCalendarSource::insertItem(const std::
|
||||||
// the parent event or (if not found) the current event
|
// the parent event or (if not found) the current event
|
||||||
eptr<icalproperty> rid(icalproperty_new_recurrenceid(icaltime_from_string(knownSubID.c_str())),
|
eptr<icalproperty> rid(icalproperty_new_recurrenceid(icaltime_from_string(knownSubID.c_str())),
|
||||||
"new rid");
|
"new rid");
|
||||||
icalproperty *dtstart = NULL;
|
icalproperty *dtstart = nullptr;
|
||||||
icalcomponent *comp;
|
icalcomponent *comp;
|
||||||
// look for parent first
|
// look for parent first
|
||||||
for (comp = icalcomponent_get_first_component(event.m_calendar, ICAL_VEVENT_COMPONENT);
|
for (comp = icalcomponent_get_first_component(event.m_calendar, ICAL_VEVENT_COMPONENT);
|
||||||
|
@ -541,7 +541,7 @@ SyncSourceRaw::InsertItemResult ActiveSyncCalendarSource::insertItem(const std::
|
||||||
loadItem(event);
|
loadItem(event);
|
||||||
|
|
||||||
// update cache: find old VEVENT and remove it before adding new one
|
// update cache: find old VEVENT and remove it before adding new one
|
||||||
icalcomponent *removeme = NULL;
|
icalcomponent *removeme = nullptr;
|
||||||
for (icalcomponent *comp = icalcomponent_get_first_component(event.m_calendar, ICAL_VEVENT_COMPONENT);
|
for (icalcomponent *comp = icalcomponent_get_first_component(event.m_calendar, ICAL_VEVENT_COMPONENT);
|
||||||
comp;
|
comp;
|
||||||
comp = icalcomponent_get_next_component(event.m_calendar, ICAL_VEVENT_COMPONENT)) {
|
comp = icalcomponent_get_next_component(event.m_calendar, ICAL_VEVENT_COMPONENT)) {
|
||||||
|
@ -653,7 +653,7 @@ void ActiveSyncCalendarSource::deleteItem(const string &luid)
|
||||||
throwError(SE_HERE, STATUS_NOT_FOUND, "sub event not found: " + subid + " in " + easid);
|
throwError(SE_HERE, STATUS_NOT_FOUND, "sub event not found: " + subid + " in " + easid);
|
||||||
} else {
|
} else {
|
||||||
event.m_subids.clear();
|
event.m_subids.clear();
|
||||||
event.m_calendar = NULL;
|
event.m_calendar = nullptr;
|
||||||
ActiveSyncSource::deleteItem(ids.first);
|
ActiveSyncSource::deleteItem(ids.first);
|
||||||
}
|
}
|
||||||
m_cache.erase(easid);
|
m_cache.erase(easid);
|
||||||
|
@ -689,7 +689,7 @@ void ActiveSyncCalendarSource::deleteItem(const string &luid)
|
||||||
|
|
||||||
void ActiveSyncCalendarSource::removeAllItems()
|
void ActiveSyncCalendarSource::removeAllItems()
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const EventCache::value_type &entry, m_cache) {
|
for (const auto &entry: m_cache) {
|
||||||
ActiveSyncSource::deleteItem(entry.first);
|
ActiveSyncSource::deleteItem(entry.first);
|
||||||
}
|
}
|
||||||
m_cache.clear();
|
m_cache.clear();
|
||||||
|
|
|
@ -29,8 +29,7 @@
|
||||||
#include <syncevo/eds_abi_wrapper.h>
|
#include <syncevo/eds_abi_wrapper.h>
|
||||||
#include <syncevo/SmartPtr.h>
|
#include <syncevo/SmartPtr.h>
|
||||||
|
|
||||||
#include <boost/utility.hpp>
|
#include <memory>
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
@ -100,7 +99,7 @@ class ActiveSyncCalendarSource : public ActiveSyncCalFormatSource
|
||||||
/**
|
/**
|
||||||
* parsed VCALENDAR component representing the current
|
* parsed VCALENDAR component representing the current
|
||||||
* state of the item as it exists on the WebDAV server,
|
* state of the item as it exists on the WebDAV server,
|
||||||
* must be kept up-to-date as we make changes, may be NULL
|
* must be kept up-to-date as we make changes, may be nullptr
|
||||||
*/
|
*/
|
||||||
eptr<icalcomponent> m_calendar;
|
eptr<icalcomponent> m_calendar;
|
||||||
|
|
||||||
|
@ -119,7 +118,7 @@ class ActiveSyncCalendarSource : public ActiveSyncCalFormatSource
|
||||||
* A cache of information about each merged item. Maps from
|
* A cache of information about each merged item. Maps from
|
||||||
* easid to Event.
|
* easid to Event.
|
||||||
*/
|
*/
|
||||||
class EventCache : public std::map<std::string, boost::shared_ptr<Event> >
|
class EventCache : public std::map<std::string, std::shared_ptr<Event> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EventCache() : m_initialized(false) {}
|
EventCache() : m_initialized(false) {}
|
||||||
|
@ -141,7 +140,7 @@ class ActiveSyncCalendarSource : public ActiveSyncCalFormatSource
|
||||||
* On-disk representation of m_cache (without the item data).
|
* On-disk representation of m_cache (without the item data).
|
||||||
* Format same as in MapSyncSource (code copied, refactor!).
|
* Format same as in MapSyncSource (code copied, refactor!).
|
||||||
*/
|
*/
|
||||||
boost::shared_ptr<ConfigNode> m_trackingNode;
|
std::shared_ptr<ConfigNode> m_trackingNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
SE_END_CXX
|
SE_END_CXX
|
||||||
|
|
|
@ -88,13 +88,13 @@ void ActiveSyncSource::findCollections(const std::string &account, const bool fo
|
||||||
if (!eas_sync_handler_get_folder_list (handler,
|
if (!eas_sync_handler_get_folder_list (handler,
|
||||||
force_update,
|
force_update,
|
||||||
folders,
|
folders,
|
||||||
NULL,
|
nullptr,
|
||||||
gerror)) {
|
gerror)) {
|
||||||
gerror.throwError(SE_HERE, "fetching folder list");
|
gerror.throwError(SE_HERE, "fetching folder list");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the Collections */
|
/* Save the Collections */
|
||||||
BOOST_FOREACH(EasFolder *folder, folders) {
|
for (EasFolder *folder: folders) {
|
||||||
m_collections[folder->folder_id].collectionId = folder->folder_id;
|
m_collections[folder->folder_id].collectionId = folder->folder_id;
|
||||||
m_collections[folder->folder_id].name = folder->display_name;
|
m_collections[folder->folder_id].name = folder->display_name;
|
||||||
m_collections[folder->folder_id].parentId = folder->parent_id;
|
m_collections[folder->folder_id].parentId = folder->parent_id;
|
||||||
|
@ -103,7 +103,7 @@ void ActiveSyncSource::findCollections(const std::string &account, const bool fo
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the full paths */
|
/* Save the full paths */
|
||||||
BOOST_FOREACH(std::string id, m_collections | boost::adaptors::map_keys) {
|
for (std::string id: m_collections | boost::adaptors::map_keys) {
|
||||||
m_folderPaths[m_collections[id].fullPath()] = id;
|
m_folderPaths[m_collections[id].fullPath()] = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@ ActiveSyncSource::Databases ActiveSyncSource::getDatabases()
|
||||||
|
|
||||||
findCollections(account, true);
|
findCollections(account, true);
|
||||||
|
|
||||||
BOOST_FOREACH(Collection coll, m_collections | boost::adaptors::map_values) {
|
for (Collection coll: m_collections | boost::adaptors::map_values) {
|
||||||
if (coll.getFolderType() == getEasType()) {
|
if (coll.getFolderType() == getEasType()) {
|
||||||
result.push_back(Database(coll.pathName, coll.collectionId, coll.collectionIsDefault()));
|
result.push_back(Database(coll.pathName, coll.collectionId, coll.collectionIsDefault()));
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ std::string ActiveSyncSource::lookupFolder(const std::string &folder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup folder name
|
// Lookup folder name
|
||||||
FolderPaths::const_iterator entry = m_folderPaths.find(key);
|
auto entry = m_folderPaths.find(key);
|
||||||
if (entry != m_folderPaths.end()) {
|
if (entry != m_folderPaths.end()) {
|
||||||
return entry->second;
|
return entry->second;
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@ void ActiveSyncSource::open()
|
||||||
void ActiveSyncSource::close()
|
void ActiveSyncSource::close()
|
||||||
{
|
{
|
||||||
// free handler if not done already
|
// free handler if not done already
|
||||||
m_handler.set(NULL);
|
m_handler.set(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActiveSyncSource::beginSync(const std::string &lastToken, const std::string &resumeToken)
|
void ActiveSyncSource::beginSync(const std::string &lastToken, const std::string &resumeToken)
|
||||||
|
@ -278,7 +278,7 @@ void ActiveSyncSource::beginSync(const std::string &lastToken, const std::string
|
||||||
for (bool firstIteration = true;
|
for (bool firstIteration = true;
|
||||||
moreAvailable;
|
moreAvailable;
|
||||||
firstIteration = false) {
|
firstIteration = false) {
|
||||||
gchar *buffer = NULL;
|
gchar *buffer = nullptr;
|
||||||
GErrorCXX gerror;
|
GErrorCXX gerror;
|
||||||
EASItemsCXX created, updated;
|
EASItemsCXX created, updated;
|
||||||
EASIdsCXX deleted;
|
EASIdsCXX deleted;
|
||||||
|
@ -315,7 +315,7 @@ void ActiveSyncSource::beginSync(const std::string &lastToken, const std::string
|
||||||
// will ask us for older, unmodified item content which we won't have.
|
// will ask us for older, unmodified item content which we won't have.
|
||||||
|
|
||||||
// populate ID lists and content cache
|
// populate ID lists and content cache
|
||||||
BOOST_FOREACH(EasItemInfo *item, created) {
|
for (EasItemInfo *item: created) {
|
||||||
if (!item->server_id) {
|
if (!item->server_id) {
|
||||||
throwError(SE_HERE, "no server ID for new eas item");
|
throwError(SE_HERE, "no server ID for new eas item");
|
||||||
}
|
}
|
||||||
|
@ -331,7 +331,7 @@ void ActiveSyncSource::beginSync(const std::string &lastToken, const std::string
|
||||||
}
|
}
|
||||||
m_items[luid] = item->data;
|
m_items[luid] = item->data;
|
||||||
}
|
}
|
||||||
BOOST_FOREACH(EasItemInfo *item, updated) {
|
for (EasItemInfo *item: updated) {
|
||||||
if (!item->server_id) {
|
if (!item->server_id) {
|
||||||
throwError(SE_HERE, "no server ID for updated eas item");
|
throwError(SE_HERE, "no server ID for updated eas item");
|
||||||
}
|
}
|
||||||
|
@ -347,7 +347,7 @@ void ActiveSyncSource::beginSync(const std::string &lastToken, const std::string
|
||||||
}
|
}
|
||||||
m_items[luid] = item->data;
|
m_items[luid] = item->data;
|
||||||
}
|
}
|
||||||
BOOST_FOREACH(const char *serverID, deleted) {
|
for (const char *serverID: deleted) {
|
||||||
if (!serverID) {
|
if (!serverID) {
|
||||||
throwError(SE_HERE, "no server ID for deleted eas item");
|
throwError(SE_HERE, "no server ID for deleted eas item");
|
||||||
}
|
}
|
||||||
|
@ -379,7 +379,7 @@ void ActiveSyncSource::beginSync(const std::string &lastToken, const std::string
|
||||||
// old items + new (added to m_ids above) - deleted (removed above)
|
// old items + new (added to m_ids above) - deleted (removed above)
|
||||||
ConfigProps props;
|
ConfigProps props;
|
||||||
m_ids->readProperties(props);
|
m_ids->readProperties(props);
|
||||||
BOOST_FOREACH(const StringPair &entry, props) {
|
for (const auto &entry: props) {
|
||||||
const std::string &luid = entry.first;
|
const std::string &luid = entry.first;
|
||||||
SE_LOG_DEBUG(getDisplayName(), "existing item %s", luid.c_str());
|
SE_LOG_DEBUG(getDisplayName(), "existing item %s", luid.c_str());
|
||||||
addItem(luid, ANY);
|
addItem(luid, ANY);
|
||||||
|
@ -523,7 +523,7 @@ SyncSourceSerialize::InsertItemResult ActiveSyncSource::insertItem(const std::st
|
||||||
void ActiveSyncSource::readItem(const std::string &luid, std::string &item)
|
void ActiveSyncSource::readItem(const std::string &luid, std::string &item)
|
||||||
{
|
{
|
||||||
// return straight from cache?
|
// return straight from cache?
|
||||||
std::map<std::string, std::string>::iterator it = m_items.find(luid);
|
auto it = m_items.find(luid);
|
||||||
if (it == m_items.end()) {
|
if (it == m_items.end()) {
|
||||||
// no, must fetch
|
// no, must fetch
|
||||||
EASItemPtr tmp(eas_item_info_new(), "EasItem");
|
EASItemPtr tmp(eas_item_info_new(), "EasItem");
|
||||||
|
|
|
@ -31,8 +31,6 @@
|
||||||
#include <syncevo/SmartPtr.h>
|
#include <syncevo/SmartPtr.h>
|
||||||
#include <syncevo/GLibSupport.h>
|
#include <syncevo/GLibSupport.h>
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
@ -135,7 +133,7 @@ class ActiveSyncSource :
|
||||||
// that we use a common prefix, so that we can use the key/value store
|
// that we use a common prefix, so that we can use the key/value store
|
||||||
// also for other keys if the need ever arises).
|
// also for other keys if the need ever arises).
|
||||||
m_itemNode(new PrefixConfigNode("item-",
|
m_itemNode(new PrefixConfigNode("item-",
|
||||||
boost::shared_ptr<ConfigNode>(new SafeConfigNode(params.m_nodes.getTrackingNode())))),
|
std::static_pointer_cast<ConfigNode>(std::make_shared<SafeConfigNode>(params.m_nodes.getTrackingNode())))),
|
||||||
m_context(params.m_context)
|
m_context(params.m_context)
|
||||||
{
|
{
|
||||||
if (!m_context) {
|
if (!m_context) {
|
||||||
|
@ -143,7 +141,7 @@ class ActiveSyncSource :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** sync config used by this instance, never NULL */
|
/** sync config used by this instance, never nullptr */
|
||||||
SyncConfig &getSyncConfig() { return *m_context; }
|
SyncConfig &getSyncConfig() { return *m_context; }
|
||||||
|
|
||||||
/* partial implementation of SyncSource */
|
/* partial implementation of SyncSource */
|
||||||
|
@ -183,11 +181,11 @@ class ActiveSyncSource :
|
||||||
void findCollections(const std::string &account, bool force_update);
|
void findCollections(const std::string &account, bool force_update);
|
||||||
std::string lookupFolder(const std::string &folder);
|
std::string lookupFolder(const std::string &folder);
|
||||||
|
|
||||||
boost::shared_ptr<ConfigNode> m_itemNode;
|
std::shared_ptr<ConfigNode> m_itemNode;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** "target-config@<context>" instance which holds our username == ActiveSync account ID */
|
/** "target-config@<context>" instance which holds our username == ActiveSync account ID */
|
||||||
boost::shared_ptr<SyncConfig> m_context;
|
std::shared_ptr<SyncConfig> m_context;
|
||||||
|
|
||||||
/** account ID for libeas, must be set in "username" config property */
|
/** account ID for libeas, must be set in "username" config property */
|
||||||
std::string m_account;
|
std::string m_account;
|
||||||
|
@ -206,9 +204,9 @@ class ActiveSyncSource :
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* server-side IDs of all items, updated as changes are reported and/or are made;
|
* server-side IDs of all items, updated as changes are reported and/or are made;
|
||||||
* NULL if not using change tracking
|
* nullptr if not using change tracking
|
||||||
*/
|
*/
|
||||||
boost::shared_ptr<ConfigNode> m_ids;
|
std::shared_ptr<ConfigNode> m_ids;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cache of all items, filled at begin of session and updated as
|
* cache of all items, filled at begin of session and updated as
|
||||||
|
@ -231,7 +229,7 @@ class ActiveSyncSource :
|
||||||
Collection() :
|
Collection() :
|
||||||
type(0),
|
type(0),
|
||||||
pathFound(false),
|
pathFound(false),
|
||||||
source(NULL)
|
source(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
int getFolderType();
|
int getFolderType();
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
|
||||||
static SyncSource *createSource(const SyncSourceParams ¶ms)
|
static std::unique_ptr<SyncSource> createSource(const SyncSourceParams ¶ms)
|
||||||
{
|
{
|
||||||
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
||||||
bool isMe;
|
bool isMe;
|
||||||
|
@ -44,7 +44,7 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
if (isMe) {
|
if (isMe) {
|
||||||
return
|
return
|
||||||
#ifdef ENABLE_ACTIVESYNC
|
#ifdef ENABLE_ACTIVESYNC
|
||||||
new ActiveSyncContactSource(params)
|
std::make_unique<ActiveSyncContactSource>(params)
|
||||||
#else
|
#else
|
||||||
RegisterSyncSource::InactiveSource(params)
|
RegisterSyncSource::InactiveSource(params)
|
||||||
#endif
|
#endif
|
||||||
|
@ -55,7 +55,7 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
if (isMe) {
|
if (isMe) {
|
||||||
return
|
return
|
||||||
#ifdef ENABLE_ACTIVESYNC
|
#ifdef ENABLE_ACTIVESYNC
|
||||||
new ActiveSyncCalendarSource(params, EAS_ITEM_CALENDAR)
|
std::make_unique<ActiveSyncCalendarSource>(params, EAS_ITEM_CALENDAR)
|
||||||
#else
|
#else
|
||||||
RegisterSyncSource::InactiveSource(params)
|
RegisterSyncSource::InactiveSource(params)
|
||||||
#endif
|
#endif
|
||||||
|
@ -66,7 +66,7 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
if (isMe) {
|
if (isMe) {
|
||||||
return
|
return
|
||||||
#ifdef ENABLE_ACTIVESYNC
|
#ifdef ENABLE_ACTIVESYNC
|
||||||
new ActiveSyncCalFormatSource(params, EAS_ITEM_TODO)
|
std::make_unique<ActiveSyncCalFormatSource>(params, EAS_ITEM_TODO)
|
||||||
#else
|
#else
|
||||||
RegisterSyncSource::InactiveSource(params)
|
RegisterSyncSource::InactiveSource(params)
|
||||||
#endif
|
#endif
|
||||||
|
@ -77,14 +77,14 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
if (isMe) {
|
if (isMe) {
|
||||||
return
|
return
|
||||||
#ifdef ENABLE_ACTIVESYNC
|
#ifdef ENABLE_ACTIVESYNC
|
||||||
new ActiveSyncCalFormatSource(params, EAS_ITEM_JOURNAL)
|
std::make_unique<ActiveSyncCalFormatSource>(params, EAS_ITEM_JOURNAL)
|
||||||
#else
|
#else
|
||||||
RegisterSyncSource::InactiveSource(params)
|
RegisterSyncSource::InactiveSource(params)
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterSyncSource registerMe("ActiveSync",
|
static RegisterSyncSource registerMe("ActiveSync",
|
||||||
|
@ -114,11 +114,11 @@ class ActiveSyncsTest : public CppUnit::TestFixture {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void testInstantiate() {
|
void testInstantiate() {
|
||||||
boost::shared_ptr<SyncSource> source;
|
std::unique_ptr<SyncSource> source;
|
||||||
source.reset(SyncSource::createTestingSource("contacts", "ActiveSync Address Book", true));
|
source = SyncSource::createTestingSource("contacts", "ActiveSync Address Book", true);
|
||||||
source.reset(SyncSource::createTestingSource("events", "ActiveSync Events", true));
|
source = SyncSource::createTestingSource("events", "ActiveSync Events", true);
|
||||||
source.reset(SyncSource::createTestingSource("todos", "ActiveSync Todos", true));
|
source = SyncSource::createTestingSource("todos", "ActiveSync Todos", true);
|
||||||
source.reset(SyncSource::createTestingSource("memos", "ActiveSync Memos", true));
|
source = SyncSource::createTestingSource("memos", "ActiveSync Memos", true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ static int DumpItems(ClientTest &client, TestingSyncSource &source, const std::s
|
||||||
// each server ID might appear multiple times, once for each
|
// each server ID might appear multiple times, once for each
|
||||||
// recurrence associated with it
|
// recurrence associated with it
|
||||||
std::set<std::string> easids;
|
std::set<std::string> easids;
|
||||||
BOOST_FOREACH (const std::string &luid, eassource.getAllItems()) {
|
for (const std::string &luid: eassource.getAllItems()) {
|
||||||
// slight hack: we know that luids in ActiveSyncSource base
|
// slight hack: we know that luids in ActiveSyncSource base
|
||||||
// class pass through this method unmodified, so no need to
|
// class pass through this method unmodified, so no need to
|
||||||
// avoid it
|
// avoid it
|
||||||
|
@ -159,7 +159,7 @@ static int DumpItems(ClientTest &client, TestingSyncSource &source, const std::s
|
||||||
easids.insert(ids.first);
|
easids.insert(ids.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(const std::string &easid, easids) {
|
for (const std::string &easid: easids) {
|
||||||
std::string item;
|
std::string item;
|
||||||
if (forceBaseReadItem) {
|
if (forceBaseReadItem) {
|
||||||
// This bypasses the more specialized
|
// This bypasses the more specialized
|
||||||
|
@ -183,12 +183,12 @@ static int DumpItems(ClientTest &client, TestingSyncSource &source, const std::s
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TestingSyncSource *createEASSource(const ClientTestConfig::createsource_t &create,
|
static std::unique_ptr<TestingSyncSource> createEASSource(const ClientTestConfig::createsource_t &create,
|
||||||
ClientTest &client,
|
ClientTest &client,
|
||||||
const std::string &clientID,
|
const std::string &clientID,
|
||||||
int source, bool isSourceA)
|
int source, bool isSourceA)
|
||||||
{
|
{
|
||||||
std::auto_ptr<TestingSyncSource> res(create(client, clientID, source, isSourceA));
|
std::unique_ptr<TestingSyncSource> res(create(client, clientID, source, isSourceA));
|
||||||
|
|
||||||
// Mangle username: if the base username in the config is account
|
// Mangle username: if the base username in the config is account
|
||||||
// "foo", then source B uses "foo_B", because otherwise it'll end
|
// "foo", then source B uses "foo_B", because otherwise it'll end
|
||||||
|
@ -201,12 +201,12 @@ static TestingSyncSource *createEASSource(const ClientTestConfig::createsource_t
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res->getDatabaseID().empty()) {
|
if (res->getDatabaseID().empty()) {
|
||||||
return res.release();
|
return res;
|
||||||
} else {
|
} else {
|
||||||
// sorry, no database
|
// sorry, no database
|
||||||
SE_LOG_ERROR(NULL, "cannot create EAS datastore for database %s, check config",
|
SE_LOG_ERROR(NULL, "cannot create EAS datastore for database %s, check config",
|
||||||
res->getDatabaseID().c_str());
|
res->getDatabaseID().c_str());
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,17 +218,20 @@ static void updateConfigEAS(const RegisterSyncSourceTest */* me */,
|
||||||
// cannot run tests involving a second database:
|
// cannot run tests involving a second database:
|
||||||
// wrap orginal source creation, set default database for
|
// wrap orginal source creation, set default database for
|
||||||
// database #0 and refuse to return a source for database #1
|
// database #0 and refuse to return a source for database #1
|
||||||
config.m_createSourceA = boost::bind(createEASSource, config.m_createSourceA,
|
config.m_createSourceA = [create=config.m_createSourceA] (ClientTest &client, const std::string &clientID, int source, bool isSourceA) {
|
||||||
_1, _2, _3, _4);
|
return createEASSource(create, client, clientID, source, isSourceA);
|
||||||
config.m_createSourceB = boost::bind(createEASSource, config.m_createSourceB,
|
};
|
||||||
_1, _2, _3, _4);
|
config.m_createSourceB = [create=config.m_createSourceB] (ClientTest &client, const std::string &clientID, int source, bool isSourceA) {
|
||||||
|
return createEASSource(create, client, clientID, source, isSourceA);
|
||||||
config.m_dump = boost::bind(DumpItems, _1, _2, _3,
|
};
|
||||||
type == EAS_ITEM_CONTACT ||
|
config.m_dump = [type] (ClientTest &client, TestingSyncSource &source, const std::string &file) {
|
||||||
// need to read from our cache for Google Calendar,
|
return DumpItems(client, source, file,
|
||||||
// because it does not support Fetch
|
type == EAS_ITEM_CONTACT ||
|
||||||
strcmp(getEnv("CLIENT_TEST_SERVER", ""), "googleeas")
|
// need to read from our cache for Google Calendar,
|
||||||
);
|
// because it does not support Fetch
|
||||||
|
strcmp(getEnv("CLIENT_TEST_SERVER", ""), "googleeas")
|
||||||
|
);
|
||||||
|
};
|
||||||
config.m_sourceLUIDsAreVolatile = true;
|
config.m_sourceLUIDsAreVolatile = true;
|
||||||
// TODO: find out how ActiveSync/Exchange handle children without parent;
|
// TODO: find out how ActiveSync/Exchange handle children without parent;
|
||||||
// at the moment, the child is stored as if it was a stand-alone event
|
// at the moment, the child is stored as if it was a stand-alone event
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
|
||||||
static SyncSource *createSource(const SyncSourceParams ¶ms)
|
static std::unique_ptr<SyncSource> createSource(const SyncSourceParams ¶ms)
|
||||||
{
|
{
|
||||||
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
||||||
bool isMe;
|
bool isMe;
|
||||||
|
@ -40,13 +40,13 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
|| sourceType.m_format == "text/x-vcard") {
|
|| sourceType.m_format == "text/x-vcard") {
|
||||||
return
|
return
|
||||||
#ifdef ENABLE_AKONADI
|
#ifdef ENABLE_AKONADI
|
||||||
new AkonadiContactSource(params)
|
std::make_unique<AkonadiContactSource>(params)
|
||||||
#else
|
#else
|
||||||
isMe ? RegisterSyncSource::InactiveSource(params) : NULL
|
isMe ? RegisterSyncSource::InactiveSource(params) : nullptr
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,13 +56,13 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
|| sourceType.m_format == "text/x-vcalendar") {
|
|| sourceType.m_format == "text/x-vcalendar") {
|
||||||
return
|
return
|
||||||
#ifdef ENABLE_AKONADI
|
#ifdef ENABLE_AKONADI
|
||||||
new AkonadiTaskSource(params)
|
std::make_unique<AkonadiTaskSource>(params)
|
||||||
#else
|
#else
|
||||||
isMe ? RegisterSyncSource::InactiveSource(params) : NULL
|
isMe ? RegisterSyncSource::InactiveSource(params) : nullptr
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,13 +71,13 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
if (sourceType.m_format == "" || sourceType.m_format == "text/plain") {
|
if (sourceType.m_format == "" || sourceType.m_format == "text/plain") {
|
||||||
return
|
return
|
||||||
#ifdef ENABLE_AKONADI
|
#ifdef ENABLE_AKONADI
|
||||||
new AkonadiMemoSource(params)
|
std::make_unique<AkonadiMemoSource>(params)
|
||||||
#else
|
#else
|
||||||
isMe ? RegisterSyncSource::InactiveSource(params) : NULL
|
isMe ? RegisterSyncSource::InactiveSource(params) : nullptr
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,17 +87,17 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
sourceType.m_format == "text/x-vcalendar" /* this is for backwards compatibility with broken configs */ ) {
|
sourceType.m_format == "text/x-vcalendar" /* this is for backwards compatibility with broken configs */ ) {
|
||||||
return
|
return
|
||||||
#ifdef ENABLE_AKONADI
|
#ifdef ENABLE_AKONADI
|
||||||
new AkonadiCalendarSource(params)
|
std::make_unique<AkonadiCalendarSource>(params)
|
||||||
#else
|
#else
|
||||||
isMe ? RegisterSyncSource::InactiveSource(params) : NULL
|
isMe ? RegisterSyncSource::InactiveSource(params) : nullptr
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterSyncSource registerMe("KDE Contact/Calendar/Task List/Memos",
|
static RegisterSyncSource registerMe("KDE Contact/Calendar/Task List/Memos",
|
||||||
|
@ -147,59 +147,59 @@ class AkonadiTest : public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static string addItem(boost::shared_ptr<TestingSyncSource> source,
|
static string addItem(std::shared_ptr<TestingSyncSource> source,
|
||||||
string &data) {
|
string &data) {
|
||||||
SyncSourceRaw::InsertItemResult res = source->insertItemRaw("", data);
|
SyncSourceRaw::InsertItemResult res = source->insertItemRaw("", data);
|
||||||
return res.m_luid;
|
return res.m_luid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void testInstantiate() {
|
void testInstantiate() {
|
||||||
boost::shared_ptr<SyncSource> source;
|
std::unique_ptr<SyncSource> source;
|
||||||
// source.reset(SyncSource::createTestingSource("addressbook", "addressbook", true));
|
// source = SyncSource::createTestingSource("addressbook", "addressbook", true);
|
||||||
// source.reset(SyncSource::createTestingSource("addressbook", "contacts", true));
|
// source = SyncSource::createTestingSource("addressbook", "contacts", true);
|
||||||
source.reset(SyncSource::createTestingSource("addressbook", "kde-contacts", true));
|
source = SyncSource::createTestingSource("addressbook", "kde-contacts", true);
|
||||||
source.reset(SyncSource::createTestingSource("addressbook", "KDE Contacts", true));
|
source = SyncSource::createTestingSource("addressbook", "KDE Contacts", true);
|
||||||
source.reset(SyncSource::createTestingSource("addressbook", "KDE Address Book:text/x-vcard", true));
|
source = SyncSource::createTestingSource("addressbook", "KDE Address Book:text/x-vcard", true);
|
||||||
source.reset(SyncSource::createTestingSource("addressbook", "KDE Address Book:text/vcard", true));
|
source = SyncSource::createTestingSource("addressbook", "KDE Address Book:text/vcard", true);
|
||||||
|
|
||||||
|
|
||||||
// source.reset(SyncSource::createTestingSource("calendar", "calendar", true));
|
// source = SyncSource::createTestingSource("calendar", "calendar", true);
|
||||||
source.reset(SyncSource::createTestingSource("calendar", "kde-calendar", true));
|
source = SyncSource::createTestingSource("calendar", "kde-calendar", true);
|
||||||
source.reset(SyncSource::createTestingSource("calendar", "KDE Calendar:text/calendar", true));
|
source = SyncSource::createTestingSource("calendar", "KDE Calendar:text/calendar", true);
|
||||||
|
|
||||||
// source.reset(SyncSource::createTestingSource("tasks", "tasks", true));
|
// source = SyncSource::createTestingSource("tasks", "tasks", true);
|
||||||
source.reset(SyncSource::createTestingSource("tasks", "kde-tasks", true));
|
source = SyncSource::createTestingSource("tasks", "kde-tasks", true);
|
||||||
source.reset(SyncSource::createTestingSource("tasks", "KDE Tasks", true));
|
source = SyncSource::createTestingSource("tasks", "KDE Tasks", true);
|
||||||
source.reset(SyncSource::createTestingSource("tasks", "KDE Task List:text/calendar", true));
|
source = SyncSource::createTestingSource("tasks", "KDE Task List:text/calendar", true);
|
||||||
|
|
||||||
// source.reset(SyncSource::createTestingSource("memos", "memos", true));
|
// source = SyncSource::createTestingSource("memos", "memos", true);
|
||||||
source.reset(SyncSource::createTestingSource("memos", "kde-memos", true));
|
source = SyncSource::createTestingSource("memos", "kde-memos", true);
|
||||||
source.reset(SyncSource::createTestingSource("memos", "KDE Memos:text/plain", true));
|
source = SyncSource::createTestingSource("memos", "KDE Memos:text/plain", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: support default databases
|
// TODO: support default databases
|
||||||
|
|
||||||
// void testOpenDefaultAddressBook() {
|
// void testOpenDefaultAddressBook() {
|
||||||
// boost::shared_ptr<TestingSyncSource> source;
|
// std::shared_ptr<TestingSyncSource> source;
|
||||||
// source.reset((TestingSyncSource *)SyncSource::createTestingSource("contacts", "kde-contacts", true, NULL));
|
// source = (TestingSyncSource *)SyncSource::createTestingSource("contacts", "kde-contacts", true, nullptr);
|
||||||
// CPPUNIT_ASSERT_NO_THROW(source->open());
|
// CPPUNIT_ASSERT_NO_THROW(source->open());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// void testOpenDefaultCalendar() {
|
// void testOpenDefaultCalendar() {
|
||||||
// boost::shared_ptr<TestingSyncSource> source;
|
// std::shared_ptr<TestingSyncSource> source;
|
||||||
// source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "kde-calendar", true, NULL));
|
// source = (TestingSyncSource *)SyncSource::createTestingSource("calendar", "kde-calendar", true, nullptr);
|
||||||
// CPPUNIT_ASSERT_NO_THROW(source->open());
|
// CPPUNIT_ASSERT_NO_THROW(source->open());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// void testOpenDefaultTodo() {
|
// void testOpenDefaultTodo() {
|
||||||
// boost::shared_ptr<TestingSyncSource> source;
|
// std::shared_ptr<TestingSyncSource> source;
|
||||||
// source.reset((TestingSyncSource *)SyncSource::createTestingSource("tasks", "kde-tasks", true, NULL));
|
// source = (TestingSyncSource *)SyncSource::createTestingSource("tasks", "kde-tasks", true, nullptr);
|
||||||
// CPPUNIT_ASSERT_NO_THROW(source->open());
|
// CPPUNIT_ASSERT_NO_THROW(source->open());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// void testOpenDefaultMemo() {
|
// void testOpenDefaultMemo() {
|
||||||
// boost::shared_ptr<TestingSyncSource> source;
|
// std::shared_ptr<TestingSyncSource> source;
|
||||||
// source.reset((TestingSyncSource *)SyncSource::createTestingSource("memos", "kde-memos", true, NULL));
|
// source = (TestingSyncSource *)SyncSource::createTestingSource("memos", "kde-memos", true, nullptr);
|
||||||
// CPPUNIT_ASSERT_NO_THROW(source->open());
|
// CPPUNIT_ASSERT_NO_THROW(source->open());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
@ -209,8 +209,8 @@ protected:
|
||||||
prefix = "SyncEvolution_Test_";
|
prefix = "SyncEvolution_Test_";
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<TestingSyncSource> source;
|
std::shared_ptr<TestingSyncSource> source;
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("eds_event", "kde-calendar", true, prefix));
|
source.reset((TestingSyncSource *)SyncSource::createTestingSource("eds_event", "kde-calendar", true, prefix).release());
|
||||||
CPPUNIT_ASSERT_NO_THROW(source->open());
|
CPPUNIT_ASSERT_NO_THROW(source->open());
|
||||||
|
|
||||||
string newyork =
|
string newyork =
|
||||||
|
|
|
@ -16,6 +16,6 @@ src_backends_akonadi_syncakonadi_la_SOURCES = \
|
||||||
src/backends/akonadi/akonadisyncsource.cpp
|
src/backends/akonadi/akonadisyncsource.cpp
|
||||||
src_backends_akonadi_syncakonadi_la_LIBADD = $(KDEPIM_LIBS) $(SYNCEVOLUTION_LIBS)
|
src_backends_akonadi_syncakonadi_la_LIBADD = $(KDEPIM_LIBS) $(SYNCEVOLUTION_LIBS)
|
||||||
src_backends_akonadi_syncakonadi_la_LDFLAGS = -module -avoid-version
|
src_backends_akonadi_syncakonadi_la_LDFLAGS = -module -avoid-version
|
||||||
src_backends_akonadi_syncakonadi_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) $(SYNCEVO_WFLAGS)
|
src_backends_akonadi_syncakonadi_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) $(SYNCEVO_WFLAGS_DEPRECATED)
|
||||||
src_backends_akonadi_syncakonadi_la_CPPFLAGS = $(SYNCEVOLUTION_CFLAGS) -I$(top_srcdir)/test $(BACKEND_CPPFLAGS)
|
src_backends_akonadi_syncakonadi_la_CPPFLAGS = $(SYNCEVOLUTION_CFLAGS) -I$(top_srcdir)/test $(BACKEND_CPPFLAGS)
|
||||||
src_backends_akonadi_syncakonadi_la_DEPENDENCIES = src/syncevo/libsyncevolution.la
|
src_backends_akonadi_syncakonadi_la_DEPENDENCIES = src/syncevo/libsyncevolution.la
|
||||||
|
|
|
@ -39,10 +39,6 @@
|
||||||
|
|
||||||
#include <syncevo/util.h>
|
#include <syncevo/util.h>
|
||||||
|
|
||||||
#include <boost/lambda/lambda.hpp>
|
|
||||||
#include <boost/lambda/bind.hpp>
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
|
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
@ -56,7 +52,7 @@ using namespace Akonadi;
|
||||||
*
|
*
|
||||||
* To avoid double frees, we need to disable auto-deletion.
|
* To avoid double frees, we need to disable auto-deletion.
|
||||||
* This method does that. Use like this:
|
* This method does that. Use like this:
|
||||||
* std::auto_ptr<CollectionStatisticsJob> statisticsJob(DisableAutoDelete(new CollectionStatisticsJob(m_collection)));
|
* std::unique_ptr<CollectionStatisticsJob> statisticsJob(DisableAutoDelete(new CollectionStatisticsJob(m_collection)));
|
||||||
*/
|
*/
|
||||||
template<class J> J *DisableAutoDelete(J *job) { job->setAutoDelete(false); return job; }
|
template<class J> J *DisableAutoDelete(J *job) { job->setAutoDelete(false); return job; }
|
||||||
|
|
||||||
|
@ -75,12 +71,12 @@ bool AkonadiSyncSource::isEmpty()
|
||||||
{
|
{
|
||||||
if (!GRunIsMain()) {
|
if (!GRunIsMain()) {
|
||||||
bool result;
|
bool result;
|
||||||
GRunInMain(boost::lambda::var(result) = boost::lambda::bind(&AkonadiSyncSource::isEmpty, this));
|
GRunInMain([this, &result] () { result = isEmpty(); });
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//To Check if the respective collection is Empty, without actually loading the collections
|
//To Check if the respective collection is Empty, without actually loading the collections
|
||||||
std::auto_ptr<CollectionStatisticsJob> statisticsJob(DisableAutoDelete(new CollectionStatisticsJob(m_collection)));
|
std::unique_ptr<CollectionStatisticsJob> statisticsJob(DisableAutoDelete(new CollectionStatisticsJob(m_collection)));
|
||||||
if (!statisticsJob->exec()) {
|
if (!statisticsJob->exec()) {
|
||||||
throwError(SE_HERE, "Error fetching the collection stats");
|
throwError(SE_HERE, "Error fetching the collection stats");
|
||||||
}
|
}
|
||||||
|
@ -90,7 +86,7 @@ bool AkonadiSyncSource::isEmpty()
|
||||||
void AkonadiSyncSource::start()
|
void AkonadiSyncSource::start()
|
||||||
{
|
{
|
||||||
if (!GRunIsMain()) {
|
if (!GRunIsMain()) {
|
||||||
GRunInMain(boost::bind(&AkonadiSyncSource::start, this));
|
GRunInMain([this]() { start(); });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +113,7 @@ SyncSource::Databases AkonadiSyncSource::getDatabases()
|
||||||
{
|
{
|
||||||
if (!GRunIsMain()) {
|
if (!GRunIsMain()) {
|
||||||
Databases result;
|
Databases result;
|
||||||
GRunInMain(boost::lambda::var(result) = boost::lambda::bind(&AkonadiSyncSource::getDatabases, this));
|
GRunInMain([this, &result] () { result = getDatabases(); });
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,8 +125,8 @@ SyncSource::Databases AkonadiSyncSource::getDatabases()
|
||||||
// as the default one used by the source.
|
// as the default one used by the source.
|
||||||
// res.push_back("Contacts", "some-KDE-specific-ID", isDefault);
|
// res.push_back("Contacts", "some-KDE-specific-ID", isDefault);
|
||||||
|
|
||||||
std::auto_ptr<CollectionFetchJob> fetchJob(DisableAutoDelete(new CollectionFetchJob(Collection::root(),
|
std::unique_ptr<CollectionFetchJob> fetchJob(DisableAutoDelete(new CollectionFetchJob(Collection::root(),
|
||||||
CollectionFetchJob::Recursive)));
|
CollectionFetchJob::Recursive)));
|
||||||
|
|
||||||
fetchJob->fetchScope().setContentMimeTypes(m_mimeTypes);
|
fetchJob->fetchScope().setContentMimeTypes(m_mimeTypes);
|
||||||
|
|
||||||
|
@ -155,7 +151,7 @@ SyncSource::Databases AkonadiSyncSource::getDatabases()
|
||||||
void AkonadiSyncSource::open()
|
void AkonadiSyncSource::open()
|
||||||
{
|
{
|
||||||
if (!GRunIsMain()) {
|
if (!GRunIsMain()) {
|
||||||
GRunInMain(boost::bind(&AkonadiSyncSource::open, this));
|
GRunInMain([this] () { open(); });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,8 +189,8 @@ void AkonadiSyncSource::open()
|
||||||
// Verify that the collection exists and ensure that
|
// Verify that the collection exists and ensure that
|
||||||
// m_collection.contentMimeTypes() returns valid information. The
|
// m_collection.contentMimeTypes() returns valid information. The
|
||||||
// collection constructed so far only contains the collection ID.
|
// collection constructed so far only contains the collection ID.
|
||||||
std::auto_ptr<CollectionFetchJob> fetchJob(DisableAutoDelete(new CollectionFetchJob(m_collection,
|
std::unique_ptr<CollectionFetchJob> fetchJob(DisableAutoDelete(new CollectionFetchJob(m_collection,
|
||||||
CollectionFetchJob::Base)));
|
CollectionFetchJob::Base)));
|
||||||
if (!fetchJob->exec()) {
|
if (!fetchJob->exec()) {
|
||||||
throwError(SE_HERE, StringPrintf("cannot fetch collection %s", id.c_str()));
|
throwError(SE_HERE, StringPrintf("cannot fetch collection %s", id.c_str()));
|
||||||
}
|
}
|
||||||
|
@ -223,16 +219,16 @@ void AkonadiSyncSource::open()
|
||||||
void AkonadiSyncSource::listAllItems(SyncSourceRevisions::RevisionMap_t &revisions)
|
void AkonadiSyncSource::listAllItems(SyncSourceRevisions::RevisionMap_t &revisions)
|
||||||
{
|
{
|
||||||
if (!GRunIsMain()) {
|
if (!GRunIsMain()) {
|
||||||
GRunInMain(boost::bind(&AkonadiSyncSource::listAllItems, this, boost::ref(revisions)));
|
GRunInMain([this, &revisions] () { listAllItems(revisions); });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy all local IDs and the corresponding revision
|
// copy all local IDs and the corresponding revision
|
||||||
std::auto_ptr<ItemFetchJob> fetchJob(DisableAutoDelete(new ItemFetchJob(m_collection)));
|
std::unique_ptr<ItemFetchJob> fetchJob(DisableAutoDelete(new ItemFetchJob(m_collection)));
|
||||||
if (!fetchJob->exec()) {
|
if (!fetchJob->exec()) {
|
||||||
throwError(SE_HERE, "listing items");
|
throwError(SE_HERE, "listing items");
|
||||||
}
|
}
|
||||||
BOOST_FOREACH (const Item &item, fetchJob->items()) {
|
for (const Item &item: fetchJob->items()) {
|
||||||
// Filter out items which don't have the right type (for example, VTODO when
|
// Filter out items which don't have the right type (for example, VTODO when
|
||||||
// syncing events)
|
// syncing events)
|
||||||
if (m_mimeTypes.contains(item.mimeType())) {
|
if (m_mimeTypes.contains(item.mimeType())) {
|
||||||
|
@ -251,7 +247,7 @@ TrackingSyncSource::InsertItemResult AkonadiSyncSource::insertItem(const std::st
|
||||||
{
|
{
|
||||||
if (!GRunIsMain()) {
|
if (!GRunIsMain()) {
|
||||||
InsertItemResult result;
|
InsertItemResult result;
|
||||||
GRunInMain(boost::lambda::var(result) = boost::lambda::bind(&AkonadiSyncSource::insertItem, this, boost::cref(luid), boost::cref(data), raw));
|
GRunInMain([this, &result, &luid, &data, raw] () { return insertItem(luid, data, raw); });
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +256,7 @@ TrackingSyncSource::InsertItemResult AkonadiSyncSource::insertItem(const std::st
|
||||||
if (luid.empty()) {
|
if (luid.empty()) {
|
||||||
item.setMimeType(m_mimeTypes.front());
|
item.setMimeType(m_mimeTypes.front());
|
||||||
item.setPayloadFromData(QByteArray(data.c_str()));
|
item.setPayloadFromData(QByteArray(data.c_str()));
|
||||||
std::auto_ptr<ItemCreateJob> createJob(DisableAutoDelete(new ItemCreateJob(item, m_collection)));
|
std::unique_ptr<ItemCreateJob> createJob(DisableAutoDelete(new ItemCreateJob(item, m_collection)));
|
||||||
if (!createJob->exec()) {
|
if (!createJob->exec()) {
|
||||||
throwError(SE_HERE, string("storing new item ") + luid);
|
throwError(SE_HERE, string("storing new item ") + luid);
|
||||||
return InsertItemResult("", "", ITEM_OKAY);
|
return InsertItemResult("", "", ITEM_OKAY);
|
||||||
|
@ -268,13 +264,13 @@ TrackingSyncSource::InsertItemResult AkonadiSyncSource::insertItem(const std::st
|
||||||
item = createJob->item();
|
item = createJob->item();
|
||||||
} else {
|
} else {
|
||||||
Entity::Id syncItemId = QByteArray(luid.c_str()).toLongLong();
|
Entity::Id syncItemId = QByteArray(luid.c_str()).toLongLong();
|
||||||
std::auto_ptr<ItemFetchJob> fetchJob(DisableAutoDelete(new ItemFetchJob(Item(syncItemId))));
|
std::unique_ptr<ItemFetchJob> fetchJob(DisableAutoDelete(new ItemFetchJob(Item(syncItemId))));
|
||||||
if (!fetchJob->exec()) {
|
if (!fetchJob->exec()) {
|
||||||
throwError(SE_HERE, string("checking item ") + luid);
|
throwError(SE_HERE, string("checking item ") + luid);
|
||||||
}
|
}
|
||||||
item = fetchJob->items().first();
|
item = fetchJob->items().first();
|
||||||
item.setPayloadFromData(QByteArray(data.c_str()));
|
item.setPayloadFromData(QByteArray(data.c_str()));
|
||||||
std::auto_ptr<ItemModifyJob> modifyJob(DisableAutoDelete(new ItemModifyJob(item)));
|
std::unique_ptr<ItemModifyJob> modifyJob(DisableAutoDelete(new ItemModifyJob(item)));
|
||||||
// TODO: SyncEvolution must pass the known revision that
|
// TODO: SyncEvolution must pass the known revision that
|
||||||
// we are updating.
|
// we are updating.
|
||||||
// TODO: check that the item has not been updated in the meantime
|
// TODO: check that the item has not been updated in the meantime
|
||||||
|
@ -296,7 +292,7 @@ TrackingSyncSource::InsertItemResult AkonadiSyncSource::insertItem(const std::st
|
||||||
void AkonadiSyncSource::removeItem(const string &luid)
|
void AkonadiSyncSource::removeItem(const string &luid)
|
||||||
{
|
{
|
||||||
if (!GRunIsMain()) {
|
if (!GRunIsMain()) {
|
||||||
GRunInMain(boost::bind(&AkonadiSyncSource::removeItem, this, boost::cref(luid)));
|
GRunInMain([this, &luid] () { removeItem(luid); });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +300,7 @@ void AkonadiSyncSource::removeItem(const string &luid)
|
||||||
|
|
||||||
// Delete the item from our collection
|
// Delete the item from our collection
|
||||||
// TODO: check that the revision is right (need revision from SyncEvolution)
|
// TODO: check that the revision is right (need revision from SyncEvolution)
|
||||||
std::auto_ptr<ItemDeleteJob> deleteJob(DisableAutoDelete(new ItemDeleteJob(Item(syncItemId))));
|
std::unique_ptr<ItemDeleteJob> deleteJob(DisableAutoDelete(new ItemDeleteJob(Item(syncItemId))));
|
||||||
if (!deleteJob->exec()) {
|
if (!deleteJob->exec()) {
|
||||||
throwError(SE_HERE, string("deleting item " ) + luid);
|
throwError(SE_HERE, string("deleting item " ) + luid);
|
||||||
}
|
}
|
||||||
|
@ -313,13 +309,13 @@ void AkonadiSyncSource::removeItem(const string &luid)
|
||||||
void AkonadiSyncSource::readItem(const std::string &luid, std::string &data, bool raw)
|
void AkonadiSyncSource::readItem(const std::string &luid, std::string &data, bool raw)
|
||||||
{
|
{
|
||||||
if (!GRunIsMain()) {
|
if (!GRunIsMain()) {
|
||||||
GRunInMain(boost::bind(&AkonadiSyncSource::readItem, this, boost::cref(luid), boost::ref(data), raw));
|
GRunInMain([this, &luid, &data, raw] () { readItem(luid, data, raw); });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity::Id syncItemId = QByteArray(luid.c_str()).toLongLong();
|
Entity::Id syncItemId = QByteArray(luid.c_str()).toLongLong();
|
||||||
|
|
||||||
std::auto_ptr<ItemFetchJob> fetchJob(DisableAutoDelete(new ItemFetchJob(Item(syncItemId))));
|
std::unique_ptr<ItemFetchJob> fetchJob(DisableAutoDelete(new ItemFetchJob(Item(syncItemId))));
|
||||||
fetchJob->fetchScope().fetchFullPayload();
|
fetchJob->fetchScope().fetchFullPayload();
|
||||||
if (fetchJob->exec()) {
|
if (fetchJob->exec()) {
|
||||||
if (fetchJob->items().empty()) {
|
if (fetchJob->items().empty()) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ if ! test "$KDEPIM_CFLAGS"; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if ! test "$KDEPIM_LIBS"; then
|
if ! test "$KDEPIM_LIBS"; then
|
||||||
KDEPIM_LIBS="-L`kde4-config --install lib` -lakonadi-kde `${PKG_CONFIG} --libs QtDBus` -lQtCore -lkdeui -lkdecore"
|
KDEPIM_LIBS="-L`kde4-config --install lib` -lakonadi-kde `${PKG_CONFIG} --libs QtDBus` -lQtCore"
|
||||||
fi
|
fi
|
||||||
AC_LANG_PUSH(C++)
|
AC_LANG_PUSH(C++)
|
||||||
old_CPPFLAGS="$CPPFLAGS"
|
old_CPPFLAGS="$CPPFLAGS"
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
@ -36,9 +35,6 @@ using namespace std;
|
||||||
#include "EvolutionMemoSource.h"
|
#include "EvolutionMemoSource.h"
|
||||||
#include "e-cal-check-timezones.h"
|
#include "e-cal-check-timezones.h"
|
||||||
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
|
||||||
|
@ -62,7 +58,7 @@ void EvolutionCalendarSource::LUIDs::eraseLUID(const ItemID &id)
|
||||||
{
|
{
|
||||||
iterator it = find(id.m_uid);
|
iterator it = find(id.m_uid);
|
||||||
if (it != end()) {
|
if (it != end()) {
|
||||||
set<string>::iterator it2 = it->second.find(id.m_rid);
|
auto it2 = it->second.find(id.m_rid);
|
||||||
if (it2 != it->second.end()) {
|
if (it2 != it->second.end()) {
|
||||||
it->second.erase(it2);
|
it->second.erase(it2);
|
||||||
if (it->second.empty()) {
|
if (it->second.empty()) {
|
||||||
|
@ -124,7 +120,7 @@ EvolutionCalendarSource::EvolutionCalendarSource(EvolutionCalendarSourceType typ
|
||||||
// This is not available in older Evolution versions.
|
// This is not available in older Evolution versions.
|
||||||
// A configure check could detect that, but as this isn't
|
// A configure check could detect that, but as this isn't
|
||||||
// important the functionality is simply disabled.
|
// important the functionality is simply disabled.
|
||||||
m_newSystem = NULL /* e_cal_new_system_memos */;
|
m_newSystem = nullptr /* e_cal_new_system_memos */;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -144,21 +140,21 @@ SyncSource::Databases EvolutionCalendarSource::getDatabases()
|
||||||
m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS ? e_source_registry_ref_default_calendar :
|
m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS ? e_source_registry_ref_default_calendar :
|
||||||
m_type == EVOLUTION_CAL_SOURCE_TYPE_TASKS ? e_source_registry_ref_default_task_list :
|
m_type == EVOLUTION_CAL_SOURCE_TYPE_TASKS ? e_source_registry_ref_default_task_list :
|
||||||
m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS ? e_source_registry_ref_default_memo_list :
|
m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS ? e_source_registry_ref_default_memo_list :
|
||||||
NULL);
|
nullptr);
|
||||||
#else
|
#else
|
||||||
ESourceList *tmp = NULL;
|
ESourceList *tmp = nullptr;
|
||||||
if (!e_cal_get_sources(&tmp, sourceType(), gerror)) {
|
if (!e_cal_get_sources(&tmp, sourceType(), gerror)) {
|
||||||
// ignore unspecific errors (like on Maemo with no support for memos)
|
// ignore unspecific errors (like on Maemo with no support for memos)
|
||||||
// and continue with empty list (perhaps defaults work)
|
// and continue with empty list (perhaps defaults work)
|
||||||
if (!gerror) {
|
if (!gerror) {
|
||||||
tmp = NULL;
|
tmp = nullptr;
|
||||||
} else {
|
} else {
|
||||||
throwError(SE_HERE, "unable to access backend databases", gerror);
|
throwError(SE_HERE, "unable to access backend databases", gerror);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ESourceListCXX sources(tmp, TRANSFER_REF);
|
ESourceListCXX sources(tmp, TRANSFER_REF);
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (GSList *g = sources ? e_source_list_peek_groups (sources) : NULL;
|
for (GSList *g = sources ? e_source_list_peek_groups (sources) : nullptr;
|
||||||
g;
|
g;
|
||||||
g = g->next) {
|
g = g->next) {
|
||||||
ESourceGroup *group = E_SOURCE_GROUP (g->data);
|
ESourceGroup *group = E_SOURCE_GROUP (g->data);
|
||||||
|
@ -184,14 +180,7 @@ SyncSource::Databases EvolutionCalendarSource::getDatabases()
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifndef USE_EDS_CLIENT
|
||||||
static EClient *newECalClient(ESource *source,
|
|
||||||
ECalClientSourceType ecalSourceType,
|
|
||||||
GError **gerror)
|
|
||||||
{
|
|
||||||
return E_CLIENT(e_cal_client_new(source, ecalSourceType, gerror));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
char *EvolutionCalendarSource::authenticate(const char *prompt,
|
char *EvolutionCalendarSource::authenticate(const char *prompt,
|
||||||
const char *key)
|
const char *key)
|
||||||
{
|
{
|
||||||
|
@ -200,7 +189,7 @@ char *EvolutionCalendarSource::authenticate(const char *prompt,
|
||||||
SE_LOG_DEBUG(getDisplayName(), "authentication requested, prompt \"%s\", key \"%s\" => %s",
|
SE_LOG_DEBUG(getDisplayName(), "authentication requested, prompt \"%s\", key \"%s\" => %s",
|
||||||
prompt, key,
|
prompt, key,
|
||||||
!passwd.empty() ? "returning configured password" : "no password configured");
|
!passwd.empty() ? "returning configured password" : "no password configured");
|
||||||
return !passwd.empty() ? strdup(passwd.c_str()) : NULL;
|
return !passwd.empty() ? strdup(passwd.c_str()) : nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -218,15 +207,18 @@ void EvolutionCalendarSource::open()
|
||||||
// be others with similar problems and for local storage it is
|
// be others with similar problems and for local storage it is
|
||||||
// a reasonably cheap operation (so no harm there).
|
// a reasonably cheap operation (so no harm there).
|
||||||
for (int retries = 0; retries < 2; retries++) {
|
for (int retries = 0; retries < 2; retries++) {
|
||||||
|
auto create = [type=sourceType()] (ESource *source, GError **gerror) {
|
||||||
|
return E_CLIENT(e_cal_client_connect_sync(source, type,
|
||||||
|
-1, // timeout in seconds
|
||||||
|
nullptr, // cancellable
|
||||||
|
gerror));
|
||||||
|
};
|
||||||
m_calendar.reset(E_CAL_CLIENT(openESource(sourceExtension(),
|
m_calendar.reset(E_CAL_CLIENT(openESource(sourceExtension(),
|
||||||
m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS ? e_source_registry_ref_builtin_calendar :
|
m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS ? e_source_registry_ref_builtin_calendar :
|
||||||
m_type == EVOLUTION_CAL_SOURCE_TYPE_TASKS ? e_source_registry_ref_builtin_task_list :
|
m_type == EVOLUTION_CAL_SOURCE_TYPE_TASKS ? e_source_registry_ref_builtin_task_list :
|
||||||
m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS ? e_source_registry_ref_builtin_memo_list :
|
m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS ? e_source_registry_ref_builtin_memo_list :
|
||||||
NULL,
|
nullptr,
|
||||||
boost::bind(newECalClient,
|
create).get()));
|
||||||
_1,
|
|
||||||
sourceType(),
|
|
||||||
_2)).get()));
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
GErrorCXX gerror;
|
GErrorCXX gerror;
|
||||||
|
@ -307,7 +299,7 @@ bool EvolutionCalendarSource::isEmpty()
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
class ECalClientViewSyncHandler {
|
class ECalClientViewSyncHandler {
|
||||||
public:
|
public:
|
||||||
typedef boost::function<void(const GSList *list)> Process_t;
|
typedef std::function<void(const GSList *list)> Process_t;
|
||||||
|
|
||||||
ECalClientViewSyncHandler(ECalClientViewCXX &view,
|
ECalClientViewSyncHandler(ECalClientViewCXX &view,
|
||||||
const Process_t &process) :
|
const Process_t &process) :
|
||||||
|
@ -318,12 +310,12 @@ class ECalClientViewSyncHandler {
|
||||||
bool processSync(GErrorCXX &gerror)
|
bool processSync(GErrorCXX &gerror)
|
||||||
{
|
{
|
||||||
// Listen for view signals
|
// Listen for view signals
|
||||||
m_view.connectSignal<void (ECalClientView *ebookview,
|
m_view.connectSignal<ECalClientView *,
|
||||||
const GSList *contacts)>("objects-added",
|
const GSList *>()("objects-added",
|
||||||
boost::bind(m_process, _2));
|
[this] (ECalClientView *, const GSList *list) { m_process(list); });
|
||||||
m_view.connectSignal<void (EBookClientView *ebookview,
|
m_view.connectSignal<ECalClientView *,
|
||||||
const GError *error)>("complete",
|
const GError *>()("complete",
|
||||||
boost::bind(&ECalClientViewSyncHandler::completed, this, _2));
|
[this] (ECalClientView *, const GError *gerror) { completed(gerror); });
|
||||||
|
|
||||||
// Start the view
|
// Start the view
|
||||||
e_cal_client_view_start (m_view, m_error);
|
e_cal_client_view_start (m_view, m_error);
|
||||||
|
@ -334,7 +326,7 @@ class ECalClientViewSyncHandler {
|
||||||
|
|
||||||
// Async -> Sync
|
// Async -> Sync
|
||||||
m_loop.run();
|
m_loop.run();
|
||||||
e_cal_client_view_stop (m_view, NULL);
|
e_cal_client_view_stop (m_view, nullptr);
|
||||||
|
|
||||||
if (m_error) {
|
if (m_error) {
|
||||||
std::swap(gerror, m_error);
|
std::swap(gerror, m_error);
|
||||||
|
@ -364,21 +356,7 @@ class ECalClientViewSyncHandler {
|
||||||
// Possible error while watching the view
|
// Possible error while watching the view
|
||||||
GErrorCXX m_error;
|
GErrorCXX m_error;
|
||||||
};
|
};
|
||||||
|
#endif // USE_EDS_CLIENT
|
||||||
static void list_revisions(const GSList *objects, EvolutionCalendarSource::RevisionMap_t *revisions)
|
|
||||||
{
|
|
||||||
const GSList *l;
|
|
||||||
|
|
||||||
for (l = objects; l; l = l->next) {
|
|
||||||
icalcomponent *icomp = (icalcomponent*)l->data;
|
|
||||||
EvolutionCalendarSource::ItemID id = EvolutionCalendarSource::getItemID(icomp);
|
|
||||||
string luid = id.getLUID();
|
|
||||||
string modTime = EvolutionCalendarSource::getItemModTime(icomp);
|
|
||||||
|
|
||||||
(*revisions)[luid] = modTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void EvolutionCalendarSource::listAllItems(RevisionMap_t &revisions)
|
void EvolutionCalendarSource::listAllItems(RevisionMap_t &revisions)
|
||||||
{
|
{
|
||||||
|
@ -386,14 +364,29 @@ void EvolutionCalendarSource::listAllItems(RevisionMap_t &revisions)
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
ECalClientView *view;
|
ECalClientView *view;
|
||||||
|
|
||||||
if (!e_cal_client_get_view_sync (m_calendar, "#t", &view, NULL, gerror)) {
|
if (!e_cal_client_get_view_sync (m_calendar, "#t", &view, nullptr, gerror)) {
|
||||||
throwError(SE_HERE, "getting the view" , gerror);
|
throwError(SE_HERE, "getting the view" , gerror);
|
||||||
}
|
}
|
||||||
ECalClientViewCXX viewPtr = ECalClientViewCXX::steal(view);
|
ECalClientViewCXX viewPtr = ECalClientViewCXX::steal(view);
|
||||||
|
|
||||||
// TODO: Optimization: use set fields_of_interest (UID / REV / LAST-MODIFIED)
|
// TODO: Optimization: use set fields_of_interest (UID / REV / LAST-MODIFIED)
|
||||||
|
|
||||||
ECalClientViewSyncHandler handler(viewPtr, boost::bind(list_revisions, _1, &revisions));
|
auto process = [&revisions] (const GSList *objects) {
|
||||||
|
const GSList *l;
|
||||||
|
|
||||||
|
for (l = objects; l; l = l->next) {
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
ICalComponent *icomp = (ICalComponent*)l->data;
|
||||||
|
#else
|
||||||
|
icalcomponent *icomp = (icalcomponent*)l->data;
|
||||||
|
#endif
|
||||||
|
EvolutionCalendarSource::ItemID id = EvolutionCalendarSource::getItemID(icomp);
|
||||||
|
string luid = id.getLUID();
|
||||||
|
string modTime = EvolutionCalendarSource::getItemModTime(icomp);
|
||||||
|
revisions[luid] = modTime;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ECalClientViewSyncHandler handler(viewPtr, process);
|
||||||
if (!handler.processSync(gerror)) {
|
if (!handler.processSync(gerror)) {
|
||||||
throwError(SE_HERE, "watching view", gerror);
|
throwError(SE_HERE, "watching view", gerror);
|
||||||
}
|
}
|
||||||
|
@ -440,14 +433,26 @@ void EvolutionCalendarSource::readItem(const string &luid, std::string &item, bo
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
ICalTimezone *
|
||||||
|
#else /* HAVE_LIBECAL_2_0 */
|
||||||
icaltimezone *
|
icaltimezone *
|
||||||
|
#endif /* HAVE_LIBECAL_2_0 */
|
||||||
my_tzlookup(const gchar *tzid,
|
my_tzlookup(const gchar *tzid,
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
gpointer ecalclient,
|
||||||
|
#else
|
||||||
gconstpointer ecalclient,
|
gconstpointer ecalclient,
|
||||||
|
#endif
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
icaltimezone *zone = NULL;
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
GError *local_error = NULL;
|
ICalTimezone *zone = nullptr;
|
||||||
|
#else
|
||||||
|
icaltimezone *zone = nullptr;
|
||||||
|
#endif
|
||||||
|
GError *local_error = nullptr;
|
||||||
|
|
||||||
if (e_cal_client_get_timezone_sync((ECalClient *)ecalclient, tzid, &zone, cancellable, &local_error)) {
|
if (e_cal_client_get_timezone_sync((ECalClient *)ecalclient, tzid, &zone, cancellable, &local_error)) {
|
||||||
return zone;
|
return zone;
|
||||||
|
@ -461,7 +466,7 @@ my_tzlookup(const gchar *tzid,
|
||||||
g_propagate_error (error, local_error);
|
g_propagate_error (error, local_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -504,7 +509,11 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
SE_LOG_DEBUG(getDisplayName(), "after replacing , with \\, in CATEGORIES:\n%s", data.c_str());
|
SE_LOG_DEBUG(getDisplayName(), "after replacing , with \\, in CATEGORIES:\n%s", data.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
eptr<ICalComponent> icomp(i_cal_component_new_from_string((char *)data.c_str()));
|
||||||
|
#else
|
||||||
eptr<icalcomponent> icomp(icalcomponent_new_from_string((char *)data.c_str()));
|
eptr<icalcomponent> icomp(icalcomponent_new_from_string((char *)data.c_str()));
|
||||||
|
#endif
|
||||||
|
|
||||||
if( !icomp ) {
|
if( !icomp ) {
|
||||||
throwError(SE_HERE, string("failure parsing ical") + data);
|
throwError(SE_HERE, string("failure parsing ical") + data);
|
||||||
|
@ -515,15 +524,24 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
// fix up TZIDs
|
// fix up TZIDs
|
||||||
if (
|
if (
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
!e_cal_client_check_timezones(icomp,
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
NULL,
|
!e_cal_client_check_timezones_sync(
|
||||||
|
#else
|
||||||
|
!e_cal_client_check_timezones(
|
||||||
|
#endif
|
||||||
|
icomp,
|
||||||
|
nullptr,
|
||||||
my_tzlookup,
|
my_tzlookup,
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
(gpointer)m_calendar.get(),
|
||||||
|
#else
|
||||||
(const void *)m_calendar.get(),
|
(const void *)m_calendar.get(),
|
||||||
NULL,
|
#endif
|
||||||
|
nullptr,
|
||||||
gerror)
|
gerror)
|
||||||
#else
|
#else
|
||||||
!e_cal_check_timezones(icomp,
|
!e_cal_check_timezones(icomp,
|
||||||
NULL,
|
nullptr,
|
||||||
e_cal_tzlookup_ecal,
|
e_cal_tzlookup_ecal,
|
||||||
(const void *)m_calendar.get(),
|
(const void *)m_calendar.get(),
|
||||||
gerror)
|
gerror)
|
||||||
|
@ -535,21 +553,35 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
|
|
||||||
// insert before adding/updating the event so that the new VTIMEZONE is
|
// insert before adding/updating the event so that the new VTIMEZONE is
|
||||||
// immediately available should anyone want it
|
// immediately available should anyone want it
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
for (ICalComponent *tcomp = i_cal_component_get_first_component(icomp, I_CAL_VTIMEZONE_COMPONENT);
|
||||||
|
tcomp;
|
||||||
|
g_object_unref (tcomp), tcomp = i_cal_component_get_next_component(icomp, I_CAL_VTIMEZONE_COMPONENT)) {
|
||||||
|
eptr<ICalTimezone> zone(i_cal_timezone_new(), "icaltimezone");
|
||||||
|
i_cal_timezone_set_component(zone, tcomp);
|
||||||
|
#else
|
||||||
for (icalcomponent *tcomp = icalcomponent_get_first_component(icomp, ICAL_VTIMEZONE_COMPONENT);
|
for (icalcomponent *tcomp = icalcomponent_get_first_component(icomp, ICAL_VTIMEZONE_COMPONENT);
|
||||||
tcomp;
|
tcomp;
|
||||||
tcomp = icalcomponent_get_next_component(icomp, ICAL_VTIMEZONE_COMPONENT)) {
|
tcomp = icalcomponent_get_next_component(icomp, ICAL_VTIMEZONE_COMPONENT)) {
|
||||||
eptr<icaltimezone> zone(icaltimezone_new(), "icaltimezone");
|
eptr<icaltimezone> zone(icaltimezone_new(), "icaltimezone");
|
||||||
icaltimezone_set_component(zone, tcomp);
|
icaltimezone_set_component(zone, tcomp);
|
||||||
|
#endif
|
||||||
|
|
||||||
GErrorCXX gerror;
|
GErrorCXX gerror;
|
||||||
const char *tzid = icaltimezone_get_tzid(zone);
|
const char *tzid;
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
tzid = i_cal_timezone_get_tzid(zone);
|
||||||
|
#else
|
||||||
|
tzid = icaltimezone_get_tzid(zone);
|
||||||
|
#endif
|
||||||
if (!tzid || !tzid[0]) {
|
if (!tzid || !tzid[0]) {
|
||||||
// cannot add a VTIMEZONE without TZID
|
// cannot add a VTIMEZONE without TZID
|
||||||
SE_LOG_DEBUG(getDisplayName(), "skipping VTIMEZONE without TZID");
|
SE_LOG_DEBUG(getDisplayName(), "skipping VTIMEZONE without TZID");
|
||||||
} else {
|
} else {
|
||||||
gboolean success =
|
gboolean success =
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
e_cal_client_add_timezone_sync(m_calendar, zone, NULL, gerror)
|
e_cal_client_add_timezone_sync(m_calendar, zone, nullptr, gerror)
|
||||||
#else
|
#else
|
||||||
e_cal_add_timezone(m_calendar, zone, gerror)
|
e_cal_add_timezone(m_calendar, zone, gerror)
|
||||||
#endif
|
#endif
|
||||||
|
@ -564,8 +596,14 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
// the component to update/add must be the
|
// the component to update/add must be the
|
||||||
// ICAL_VEVENT/VTODO_COMPONENT of the item,
|
// ICAL_VEVENT/VTODO_COMPONENT of the item,
|
||||||
// e_cal_create/modify_object() fail otherwise
|
// e_cal_create/modify_object() fail otherwise
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
ICalComponent *subcomp = i_cal_component_get_first_component(icomp,
|
||||||
|
getCompType());
|
||||||
|
#else
|
||||||
icalcomponent *subcomp = icalcomponent_get_first_component(icomp,
|
icalcomponent *subcomp = icalcomponent_get_first_component(icomp,
|
||||||
getCompType());
|
getCompType());
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!subcomp) {
|
if (!subcomp) {
|
||||||
throwError(SE_HERE, "extracting event");
|
throwError(SE_HERE, "extracting event");
|
||||||
}
|
}
|
||||||
|
@ -573,16 +611,20 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
// Remove LAST-MODIFIED: the Evolution Exchange Connector does not
|
// Remove LAST-MODIFIED: the Evolution Exchange Connector does not
|
||||||
// properly update this property if it is already present in the
|
// properly update this property if it is already present in the
|
||||||
// incoming data.
|
// incoming data.
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
e_cal_util_component_remove_property_by_kind(subcomp, I_CAL_LASTMODIFIED_PROPERTY, TRUE);
|
||||||
|
#else
|
||||||
icalproperty *modprop;
|
icalproperty *modprop;
|
||||||
while ((modprop = icalcomponent_get_first_property(subcomp, ICAL_LASTMODIFIED_PROPERTY)) != NULL) {
|
while ((modprop = icalcomponent_get_first_property(subcomp, ICAL_LASTMODIFIED_PROPERTY)) != nullptr) {
|
||||||
icalcomponent_remove_property(subcomp, modprop);
|
icalcomponent_remove_property(subcomp, modprop);
|
||||||
icalproperty_free(modprop);
|
icalproperty_free(modprop);
|
||||||
modprop = NULL;
|
modprop = nullptr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!update) {
|
if (!update) {
|
||||||
ItemID id = getItemID(subcomp);
|
ItemID id = getItemID(subcomp);
|
||||||
const char *uid = NULL;
|
const char *uid = nullptr;
|
||||||
|
|
||||||
// Trying to add a normal event which already exists leads to a
|
// Trying to add a normal event which already exists leads to a
|
||||||
// gerror->domain == E_CALENDAR_ERROR
|
// gerror->domain == E_CALENDAR_ERROR
|
||||||
|
@ -628,8 +670,11 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
// creating new objects works for normal events and detached occurrences alike
|
// creating new objects works for normal events and detached occurrences alike
|
||||||
if (
|
if (
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
e_cal_client_create_object_sync(m_calendar, subcomp, (gchar **)&uid,
|
e_cal_client_create_object_sync(m_calendar, subcomp,
|
||||||
NULL, gerror)
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
E_CAL_OPERATION_FLAG_NONE,
|
||||||
|
#endif
|
||||||
|
(gchar **)&uid, nullptr, gerror)
|
||||||
#else
|
#else
|
||||||
e_cal_create_object(m_calendar, subcomp, (gchar **)&uid, gerror)
|
e_cal_create_object(m_calendar, subcomp, (gchar **)&uid, gerror)
|
||||||
#endif
|
#endif
|
||||||
|
@ -650,12 +695,20 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
|
|
||||||
// Recreate any children removed earlier: when we get here,
|
// Recreate any children removed earlier: when we get here,
|
||||||
// the parent exists and we must update it.
|
// the parent exists and we must update it.
|
||||||
BOOST_FOREACH(boost::shared_ptr< eptr<icalcomponent> > &icalcomp, children) {
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
for (std::shared_ptr< eptr<ICalComponent> > &icalcomp: children) {
|
||||||
|
#else
|
||||||
|
for (std::shared_ptr< eptr<icalcomponent> > &icalcomp: children) {
|
||||||
|
#endif
|
||||||
if (
|
if (
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
!e_cal_client_modify_object_sync(m_calendar, *icalcomp,
|
!e_cal_client_modify_object_sync(m_calendar, *icalcomp,
|
||||||
CALOBJ_MOD_THIS, NULL,
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
gerror)
|
E_CAL_OBJ_MOD_THIS, E_CAL_OPERATION_FLAG_NONE,
|
||||||
|
#else
|
||||||
|
CALOBJ_MOD_THIS,
|
||||||
|
#endif
|
||||||
|
nullptr, gerror)
|
||||||
#else
|
#else
|
||||||
!e_cal_modify_object(m_calendar, *icalcomp,
|
!e_cal_modify_object(m_calendar, *icalcomp,
|
||||||
CALOBJ_MOD_THIS,
|
CALOBJ_MOD_THIS,
|
||||||
|
@ -679,13 +732,33 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
// RECURRENCE-ID
|
// RECURRENCE-ID
|
||||||
if (update) {
|
if (update) {
|
||||||
if (!id.m_uid.empty()) {
|
if (!id.m_uid.empty()) {
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
i_cal_component_set_uid(subcomp, id.m_uid.c_str());
|
||||||
|
#else
|
||||||
icalcomponent_set_uid(subcomp, id.m_uid.c_str());
|
icalcomponent_set_uid(subcomp, id.m_uid.c_str());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (!id.m_rid.empty()) {
|
if (!id.m_rid.empty()) {
|
||||||
// Reconstructing the RECURRENCE-ID is non-trivial,
|
// Reconstructing the RECURRENCE-ID is non-trivial,
|
||||||
// because our luid only contains the date-time, but
|
// because our luid only contains the date-time, but
|
||||||
// not the time zone. Only do the work if the event
|
// not the time zone. Only do the work if the event
|
||||||
// really doesn't have a RECURRENCE-ID.
|
// really doesn't have a RECURRENCE-ID.
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
ICalTime *rid;
|
||||||
|
rid = i_cal_component_get_recurrenceid(subcomp);
|
||||||
|
if (!rid || i_cal_time_is_null_time(rid)) {
|
||||||
|
// Preserve the original RECURRENCE-ID, including
|
||||||
|
// timezone, no matter what the update contains
|
||||||
|
// (might have wrong timezone or UTC).
|
||||||
|
eptr<ICalComponent> orig(retrieveItem(id));
|
||||||
|
ICalProperty *orig_rid = i_cal_component_get_first_property(orig, I_CAL_RECURRENCEID_PROPERTY);
|
||||||
|
if (orig_rid) {
|
||||||
|
i_cal_component_take_property(subcomp, i_cal_property_clone(orig_rid));
|
||||||
|
}
|
||||||
|
g_clear_object(&orig_rid);
|
||||||
|
}
|
||||||
|
g_clear_object(&rid);
|
||||||
|
#else
|
||||||
struct icaltimetype rid;
|
struct icaltimetype rid;
|
||||||
rid = icalcomponent_get_recurrenceid(subcomp);
|
rid = icalcomponent_get_recurrenceid(subcomp);
|
||||||
if (icaltime_is_null_time(rid)) {
|
if (icaltime_is_null_time(rid)) {
|
||||||
|
@ -698,6 +771,7 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
icalcomponent_add_property(subcomp, icalproperty_new_clone(orig_rid));
|
icalcomponent_add_property(subcomp, icalproperty_new_clone(orig_rid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,9 +782,9 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
// Therefore we have to use CALOBJ_MOD_ALL, but that removes
|
// Therefore we have to use CALOBJ_MOD_ALL, but that removes
|
||||||
// children.
|
// children.
|
||||||
bool hasChildren = false;
|
bool hasChildren = false;
|
||||||
LUIDs::const_iterator it = m_allLUIDs.find(id.m_uid);
|
auto it = m_allLUIDs.find(id.m_uid);
|
||||||
if (it != m_allLUIDs.end()) {
|
if (it != m_allLUIDs.end()) {
|
||||||
BOOST_FOREACH(const string &rid, it->second) {
|
for (const string &rid: it->second) {
|
||||||
if (!rid.empty()) {
|
if (!rid.empty()) {
|
||||||
hasChildren = true;
|
hasChildren = true;
|
||||||
break;
|
break;
|
||||||
|
@ -725,11 +799,14 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
ICalComps_t children = removeEvents(id.m_uid, true);
|
ICalComps_t children = removeEvents(id.m_uid, true);
|
||||||
|
|
||||||
// Parent is gone, too, and needs to be recreated.
|
// Parent is gone, too, and needs to be recreated.
|
||||||
const char *uid = NULL;
|
const char *uid = nullptr;
|
||||||
if (
|
if (
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
!e_cal_client_create_object_sync(m_calendar, subcomp, (char **)&uid,
|
!e_cal_client_create_object_sync(m_calendar, subcomp,
|
||||||
NULL, gerror)
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
E_CAL_OPERATION_FLAG_NONE,
|
||||||
|
#endif
|
||||||
|
(char **)&uid, nullptr, gerror)
|
||||||
#else
|
#else
|
||||||
!e_cal_create_object(m_calendar, subcomp, (char **)&uid, gerror)
|
!e_cal_create_object(m_calendar, subcomp, (char **)&uid, gerror)
|
||||||
#endif
|
#endif
|
||||||
|
@ -742,12 +819,20 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
|
|
||||||
// Recreate any children removed earlier: when we get here,
|
// Recreate any children removed earlier: when we get here,
|
||||||
// the parent exists and we must update it.
|
// the parent exists and we must update it.
|
||||||
BOOST_FOREACH(boost::shared_ptr< eptr<icalcomponent> > &icalcomp, children) {
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
for (std::shared_ptr< eptr<ICalComponent> > &icalcomp: children) {
|
||||||
|
#else
|
||||||
|
for (std::shared_ptr< eptr<icalcomponent> > &icalcomp: children) {
|
||||||
|
#endif
|
||||||
if (
|
if (
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
!e_cal_client_modify_object_sync(m_calendar, *icalcomp,
|
!e_cal_client_modify_object_sync(m_calendar, *icalcomp,
|
||||||
CALOBJ_MOD_THIS, NULL,
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
gerror)
|
E_CAL_OBJ_MOD_THIS, E_CAL_OPERATION_FLAG_NONE,
|
||||||
|
#else
|
||||||
|
CALOBJ_MOD_THIS,
|
||||||
|
#endif
|
||||||
|
nullptr, gerror)
|
||||||
#else
|
#else
|
||||||
!e_cal_modify_object(m_calendar, *icalcomp,
|
!e_cal_modify_object(m_calendar, *icalcomp,
|
||||||
CALOBJ_MOD_THIS,
|
CALOBJ_MOD_THIS,
|
||||||
|
@ -762,8 +847,12 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
if (
|
if (
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
!e_cal_client_modify_object_sync(m_calendar, subcomp,
|
!e_cal_client_modify_object_sync(m_calendar, subcomp,
|
||||||
CALOBJ_MOD_ALL, NULL,
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
gerror)
|
E_CAL_OBJ_MOD_ALL, E_CAL_OPERATION_FLAG_NONE,
|
||||||
|
#else
|
||||||
|
CALOBJ_MOD_ALL,
|
||||||
|
#endif
|
||||||
|
nullptr, gerror)
|
||||||
#else
|
#else
|
||||||
!e_cal_modify_object(m_calendar, subcomp,
|
!e_cal_modify_object(m_calendar, subcomp,
|
||||||
CALOBJ_MOD_ALL,
|
CALOBJ_MOD_ALL,
|
||||||
|
@ -778,8 +867,12 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
if (
|
if (
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
!e_cal_client_modify_object_sync(m_calendar, subcomp,
|
!e_cal_client_modify_object_sync(m_calendar, subcomp,
|
||||||
CALOBJ_MOD_THIS, NULL,
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
gerror)
|
E_CAL_OBJ_MOD_THIS, E_CAL_OPERATION_FLAG_NONE,
|
||||||
|
#else
|
||||||
|
CALOBJ_MOD_THIS,
|
||||||
|
#endif
|
||||||
|
nullptr, gerror)
|
||||||
#else
|
#else
|
||||||
!e_cal_modify_object(m_calendar, subcomp,
|
!e_cal_modify_object(m_calendar, subcomp,
|
||||||
CALOBJ_MOD_THIS,
|
CALOBJ_MOD_THIS,
|
||||||
|
@ -795,6 +888,11 @@ EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(co
|
||||||
modTime = getItemModTime(newid);
|
modTime = getItemModTime(newid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
// TODO: this object leaks when an exception is thrown. Store in smart pointer.
|
||||||
|
g_clear_object(&subcomp);
|
||||||
|
#endif
|
||||||
|
|
||||||
return InsertItemResult(newluid, modTime, state);
|
return InsertItemResult(newluid, modTime, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -802,16 +900,28 @@ EvolutionCalendarSource::ICalComps_t EvolutionCalendarSource::removeEvents(const
|
||||||
{
|
{
|
||||||
ICalComps_t events;
|
ICalComps_t events;
|
||||||
|
|
||||||
LUIDs::const_iterator it = m_allLUIDs.find(uid);
|
auto it = m_allLUIDs.find(uid);
|
||||||
if (it != m_allLUIDs.end()) {
|
if (it != m_allLUIDs.end()) {
|
||||||
BOOST_FOREACH(const string &rid, it->second) {
|
for (const string &rid: it->second) {
|
||||||
ItemID id(uid, rid);
|
ItemID id(uid, rid);
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
ICalComponent *icomp = retrieveItem(id);
|
||||||
|
#else
|
||||||
icalcomponent *icomp = retrieveItem(id);
|
icalcomponent *icomp = retrieveItem(id);
|
||||||
|
#endif
|
||||||
if (icomp) {
|
if (icomp) {
|
||||||
if (id.m_rid.empty() && returnOnlyChildren) {
|
if (id.m_rid.empty() && returnOnlyChildren) {
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
g_clear_object(&icomp);
|
||||||
|
#else
|
||||||
icalcomponent_free(icomp);
|
icalcomponent_free(icomp);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
events.push_back(ICalComps_t::value_type(new eptr<ICalComponent>(icomp)));
|
||||||
|
#else
|
||||||
events.push_back(ICalComps_t::value_type(new eptr<icalcomponent>(icomp)));
|
events.push_back(ICalComps_t::value_type(new eptr<icalcomponent>(icomp)));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -821,9 +931,13 @@ EvolutionCalendarSource::ICalComps_t EvolutionCalendarSource::removeEvents(const
|
||||||
GErrorCXX gerror;
|
GErrorCXX gerror;
|
||||||
if (!uid.empty() && // e_cal_client_remove_object_sync() in EDS 3.8 aborts the process for empty UID, other versions cannot succeed, so skip the call.
|
if (!uid.empty() && // e_cal_client_remove_object_sync() in EDS 3.8 aborts the process for empty UID, other versions cannot succeed, so skip the call.
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
!e_cal_client_remove_object_sync(m_calendar,
|
!e_cal_client_remove_object_sync(m_calendar, uid.c_str(), nullptr,
|
||||||
uid.c_str(), NULL, CALOBJ_MOD_ALL,
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
NULL, gerror)
|
E_CAL_OBJ_MOD_ALL, E_CAL_OPERATION_FLAG_NONE,
|
||||||
|
#else
|
||||||
|
CALOBJ_MOD_ALL,
|
||||||
|
#endif
|
||||||
|
nullptr, gerror)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
!e_cal_remove_object(m_calendar,
|
!e_cal_remove_object(m_calendar,
|
||||||
|
@ -862,14 +976,21 @@ void EvolutionCalendarSource::removeItem(const string &luid)
|
||||||
|
|
||||||
// recreate children
|
// recreate children
|
||||||
bool first = true;
|
bool first = true;
|
||||||
BOOST_FOREACH(boost::shared_ptr< eptr<icalcomponent> > &icalcomp, children) {
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
for (std::shared_ptr< eptr<ICalComponent> > &icalcomp: children) {
|
||||||
|
#else
|
||||||
|
for (std::shared_ptr< eptr<icalcomponent> > &icalcomp: children) {
|
||||||
|
#endif
|
||||||
if (first) {
|
if (first) {
|
||||||
char *uid;
|
char *uid;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
!e_cal_client_create_object_sync(m_calendar, *icalcomp, &uid,
|
!e_cal_client_create_object_sync(m_calendar, *icalcomp,
|
||||||
NULL, gerror)
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
E_CAL_OPERATION_FLAG_NONE,
|
||||||
|
#endif
|
||||||
|
&uid, nullptr, gerror)
|
||||||
#else
|
#else
|
||||||
!e_cal_create_object(m_calendar, *icalcomp, &uid, gerror)
|
!e_cal_create_object(m_calendar, *icalcomp, &uid, gerror)
|
||||||
#endif
|
#endif
|
||||||
|
@ -884,8 +1005,12 @@ void EvolutionCalendarSource::removeItem(const string &luid)
|
||||||
if (
|
if (
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
!e_cal_client_modify_object_sync(m_calendar, *icalcomp,
|
!e_cal_client_modify_object_sync(m_calendar, *icalcomp,
|
||||||
CALOBJ_MOD_THIS, NULL,
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
gerror)
|
E_CAL_OBJ_MOD_THIS, E_CAL_OPERATION_FLAG_NONE,
|
||||||
|
#else
|
||||||
|
CALOBJ_MOD_THIS,
|
||||||
|
#endif
|
||||||
|
nullptr, gerror)
|
||||||
#else
|
#else
|
||||||
!e_cal_modify_object(m_calendar, *icalcomp,
|
!e_cal_modify_object(m_calendar, *icalcomp,
|
||||||
CALOBJ_MOD_THIS,
|
CALOBJ_MOD_THIS,
|
||||||
|
@ -900,15 +1025,24 @@ void EvolutionCalendarSource::removeItem(const string &luid)
|
||||||
// workaround for EDS 2.32 API semantic: succeeds even if
|
// workaround for EDS 2.32 API semantic: succeeds even if
|
||||||
// detached recurrence doesn't exist and adds EXDATE,
|
// detached recurrence doesn't exist and adds EXDATE,
|
||||||
// therefore we have to check for existence first
|
// therefore we have to check for existence first
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
eptr<ICalComponent> item(retrieveItem(id));
|
||||||
|
#else
|
||||||
eptr<icalcomponent> item(retrieveItem(id));
|
eptr<icalcomponent> item(retrieveItem(id));
|
||||||
|
#endif
|
||||||
gboolean success = !item ? false :
|
gboolean success = !item ? false :
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
// TODO: is this necessary?
|
// TODO: is this necessary?
|
||||||
e_cal_client_remove_object_sync(m_calendar,
|
e_cal_client_remove_object_sync(m_calendar,
|
||||||
id.m_uid.c_str(),
|
id.m_uid.c_str(),
|
||||||
id.m_rid.c_str(),
|
id.m_rid.c_str(),
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
E_CAL_OBJ_MOD_ONLY_THIS,
|
||||||
|
E_CAL_OPERATION_FLAG_NONE,
|
||||||
|
#else
|
||||||
CALOBJ_MOD_ONLY_THIS,
|
CALOBJ_MOD_ONLY_THIS,
|
||||||
NULL,
|
#endif
|
||||||
|
nullptr,
|
||||||
gerror)
|
gerror)
|
||||||
#else
|
#else
|
||||||
e_cal_remove_object_with_mod(m_calendar,
|
e_cal_remove_object_with_mod(m_calendar,
|
||||||
|
@ -951,23 +1085,31 @@ void EvolutionCalendarSource::removeItem(const string &luid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
ICalComponent *EvolutionCalendarSource::retrieveItem(const ItemID &id)
|
||||||
|
#else
|
||||||
icalcomponent *EvolutionCalendarSource::retrieveItem(const ItemID &id)
|
icalcomponent *EvolutionCalendarSource::retrieveItem(const ItemID &id)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
GErrorCXX gerror;
|
GErrorCXX gerror;
|
||||||
icalcomponent *comp = NULL;
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
ICalComponent *comp = nullptr;
|
||||||
|
#else
|
||||||
|
icalcomponent *comp = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (
|
if (
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
!e_cal_client_get_object_sync(m_calendar,
|
!e_cal_client_get_object_sync(m_calendar,
|
||||||
id.m_uid.c_str(),
|
id.m_uid.c_str(),
|
||||||
!id.m_rid.empty() ? id.m_rid.c_str() : NULL,
|
!id.m_rid.empty() ? id.m_rid.c_str() : nullptr,
|
||||||
&comp,
|
&comp,
|
||||||
NULL,
|
nullptr,
|
||||||
gerror)
|
gerror)
|
||||||
#else
|
#else
|
||||||
!e_cal_get_object(m_calendar,
|
!e_cal_get_object(m_calendar,
|
||||||
id.m_uid.c_str(),
|
id.m_uid.c_str(),
|
||||||
!id.m_rid.empty() ? id.m_rid.c_str() : NULL,
|
!id.m_rid.empty() ? id.m_rid.c_str() : nullptr,
|
||||||
&comp,
|
&comp,
|
||||||
gerror)
|
gerror)
|
||||||
#endif
|
#endif
|
||||||
|
@ -981,7 +1123,11 @@ icalcomponent *EvolutionCalendarSource::retrieveItem(const ItemID &id)
|
||||||
if (!comp) {
|
if (!comp) {
|
||||||
throwError(SE_HERE, string("retrieving item: ") + id.getLUID());
|
throwError(SE_HERE, string("retrieving item: ") + id.getLUID());
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
eptr<ICalComponent> ptr(comp);
|
||||||
|
#else
|
||||||
eptr<icalcomponent> ptr(comp);
|
eptr<icalcomponent> ptr(comp);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* EDS bug: if a parent doesn't exist while a child does, and we ask
|
* EDS bug: if a parent doesn't exist while a child does, and we ask
|
||||||
|
@ -989,8 +1135,15 @@ icalcomponent *EvolutionCalendarSource::retrieveItem(const ItemID &id)
|
||||||
* turn it into a "not found" error.
|
* turn it into a "not found" error.
|
||||||
*/
|
*/
|
||||||
if (id.m_rid.empty()) {
|
if (id.m_rid.empty()) {
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
ICalTime *rid = i_cal_component_get_recurrenceid(comp);
|
||||||
|
if (!rid || i_cal_time_is_null_time(rid)) {
|
||||||
|
g_clear_object(&rid);
|
||||||
|
} else {
|
||||||
|
#else
|
||||||
struct icaltimetype rid = icalcomponent_get_recurrenceid(comp);
|
struct icaltimetype rid = icalcomponent_get_recurrenceid(comp);
|
||||||
if (!icaltime_is_null_time(rid)) {
|
if (!icaltime_is_null_time(rid)) {
|
||||||
|
#endif
|
||||||
throwError(SE_HERE, string("retrieving item: got child instead of parent: ") + id.m_uid);
|
throwError(SE_HERE, string("retrieving item: got child instead of parent: ") + id.m_uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1000,7 +1153,11 @@ icalcomponent *EvolutionCalendarSource::retrieveItem(const ItemID &id)
|
||||||
|
|
||||||
string EvolutionCalendarSource::retrieveItemAsString(const ItemID &id)
|
string EvolutionCalendarSource::retrieveItemAsString(const ItemID &id)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
eptr<ICalComponent> comp(retrieveItem(id));
|
||||||
|
#else
|
||||||
eptr<icalcomponent> comp(retrieveItem(id));
|
eptr<icalcomponent> comp(retrieveItem(id));
|
||||||
|
#endif
|
||||||
eptr<char> icalstr;
|
eptr<char> icalstr;
|
||||||
|
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
|
@ -1015,6 +1172,15 @@ string EvolutionCalendarSource::retrieveItemAsString(const ItemID &id)
|
||||||
// definition. Evolution GUI ignores the TZID and interprets
|
// definition. Evolution GUI ignores the TZID and interprets
|
||||||
// the times as local time. Do the same when exporting the
|
// the times as local time. Do the same when exporting the
|
||||||
// event by removing the bogus TZID.
|
// event by removing the bogus TZID.
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
ICalProperty *prop;
|
||||||
|
for (prop = i_cal_component_get_first_property (comp, I_CAL_ANY_PROPERTY);
|
||||||
|
prop;
|
||||||
|
g_object_unref(prop), prop = i_cal_component_get_next_property (comp, I_CAL_ANY_PROPERTY)) {
|
||||||
|
// removes only the *first* TZID - but there shouldn't be more than one
|
||||||
|
i_cal_property_remove_parameter_by_kind(prop, I_CAL_TZID_PARAMETER);
|
||||||
|
}
|
||||||
|
#else
|
||||||
icalproperty *prop = icalcomponent_get_first_property (comp,
|
icalproperty *prop = icalcomponent_get_first_property (comp,
|
||||||
ICAL_ANY_PROPERTY);
|
ICAL_ANY_PROPERTY);
|
||||||
|
|
||||||
|
@ -1024,6 +1190,7 @@ string EvolutionCalendarSource::retrieveItemAsString(const ItemID &id)
|
||||||
prop = icalcomponent_get_next_property (comp,
|
prop = icalcomponent_get_next_property (comp,
|
||||||
ICAL_ANY_PROPERTY);
|
ICAL_ANY_PROPERTY);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// now try again
|
// now try again
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
|
@ -1075,16 +1242,28 @@ string EvolutionCalendarSource::retrieveItemAsString(const ItemID &id)
|
||||||
std::string EvolutionCalendarSource::getDescription(const string &luid)
|
std::string EvolutionCalendarSource::getDescription(const string &luid)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
eptr<ICalComponent> comp(retrieveItem(ItemID(luid)));
|
||||||
|
#else
|
||||||
eptr<icalcomponent> comp(retrieveItem(ItemID(luid)));
|
eptr<icalcomponent> comp(retrieveItem(ItemID(luid)));
|
||||||
|
#endif
|
||||||
std::string descr;
|
std::string descr;
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
const char *summary = i_cal_component_get_summary(comp);
|
||||||
|
#else
|
||||||
const char *summary = icalcomponent_get_summary(comp);
|
const char *summary = icalcomponent_get_summary(comp);
|
||||||
|
#endif
|
||||||
if (summary && summary[0]) {
|
if (summary && summary[0]) {
|
||||||
descr += summary;
|
descr += summary;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS) {
|
if (m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS) {
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
const char *location = i_cal_component_get_location(comp);
|
||||||
|
#else
|
||||||
const char *location = icalcomponent_get_location(comp);
|
const char *location = icalcomponent_get_location(comp);
|
||||||
|
#endif
|
||||||
if (location && location[0]) {
|
if (location && location[0]) {
|
||||||
if (!descr.empty()) {
|
if (!descr.empty()) {
|
||||||
descr += ", ";
|
descr += ", ";
|
||||||
|
@ -1096,9 +1275,17 @@ std::string EvolutionCalendarSource::getDescription(const string &luid)
|
||||||
if (m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS &&
|
if (m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS &&
|
||||||
descr.empty()) {
|
descr.empty()) {
|
||||||
// fallback to first line of body text
|
// fallback to first line of body text
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
ICalProperty *desc = i_cal_component_get_first_property(comp, I_CAL_DESCRIPTION_PROPERTY);
|
||||||
|
#else
|
||||||
icalproperty *desc = icalcomponent_get_first_property(comp, ICAL_DESCRIPTION_PROPERTY);
|
icalproperty *desc = icalcomponent_get_first_property(comp, ICAL_DESCRIPTION_PROPERTY);
|
||||||
|
#endif
|
||||||
if (desc) {
|
if (desc) {
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
const char *text = i_cal_property_get_description(desc);
|
||||||
|
#else
|
||||||
const char *text = icalproperty_get_description(desc);
|
const char *text = icalproperty_get_description(desc);
|
||||||
|
#endif
|
||||||
if (text) {
|
if (text) {
|
||||||
const char *eol = strchr(text, '\n');
|
const char *eol = strchr(text, '\n');
|
||||||
if (eol) {
|
if (eol) {
|
||||||
|
@ -1107,6 +1294,9 @@ std::string EvolutionCalendarSource::getDescription(const string &luid)
|
||||||
descr = text;
|
descr = text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
g_object_unref(desc);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1144,7 +1334,11 @@ EvolutionCalendarSource::ItemID::ItemID(const string &luid)
|
||||||
|
|
||||||
EvolutionCalendarSource::ItemID EvolutionCalendarSource::getItemID(ECalComponent *ecomp)
|
EvolutionCalendarSource::ItemID EvolutionCalendarSource::getItemID(ECalComponent *ecomp)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
ICalComponent *icomp = e_cal_component_get_icalcomponent(ecomp);
|
||||||
|
#else
|
||||||
icalcomponent *icomp = e_cal_component_get_icalcomponent(ecomp);
|
icalcomponent *icomp = e_cal_component_get_icalcomponent(ecomp);
|
||||||
|
#endif
|
||||||
if (!icomp) {
|
if (!icomp) {
|
||||||
SE_THROW("internal error in getItemID(): ECalComponent without icalcomp");
|
SE_THROW("internal error in getItemID(): ECalComponent without icalcomp");
|
||||||
}
|
}
|
||||||
|
@ -1162,15 +1356,38 @@ EvolutionCalendarSource::ItemID EvolutionCalendarSource::getItemID(icalcomponent
|
||||||
icalTime2Str(rid));
|
icalTime2Str(rid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
EvolutionCalendarSource::ItemID EvolutionCalendarSource::getItemID(ICalComponent *icomp)
|
||||||
|
{
|
||||||
|
icalcomponent *native_icomp;
|
||||||
|
|
||||||
|
native_icomp = static_cast<icalcomponent *>(i_cal_object_get_native(I_CAL_OBJECT (icomp)));
|
||||||
|
if (!native_icomp) {
|
||||||
|
SE_THROW("internal error in getItemID(): ICalComponent without native icalcomp");
|
||||||
|
}
|
||||||
|
return getItemID(native_icomp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
string EvolutionCalendarSource::getItemModTime(ECalComponent *ecomp)
|
string EvolutionCalendarSource::getItemModTime(ECalComponent *ecomp)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
ICalTime *modTime;
|
||||||
|
modTime = e_cal_component_get_last_modified(ecomp);
|
||||||
|
eptr<ICalTime, ICalTime, UnrefFree<ICalTime> > modTimePtr(modTime);
|
||||||
|
#else
|
||||||
struct icaltimetype *modTime;
|
struct icaltimetype *modTime;
|
||||||
e_cal_component_get_last_modified(ecomp, &modTime);
|
e_cal_component_get_last_modified(ecomp, &modTime);
|
||||||
eptr<struct icaltimetype, struct icaltimetype, UnrefFree<struct icaltimetype> > modTimePtr(modTime);
|
eptr<struct icaltimetype, struct icaltimetype, UnrefFree<struct icaltimetype> > modTimePtr(modTime);
|
||||||
|
#endif
|
||||||
if (!modTimePtr) {
|
if (!modTimePtr) {
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
return icalTime2Str(modTimePtr.get());
|
||||||
|
#else
|
||||||
return icalTime2Str(*modTimePtr.get());
|
return icalTime2Str(*modTimePtr.get());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1179,7 +1396,11 @@ string EvolutionCalendarSource::getItemModTime(const ItemID &id)
|
||||||
if (!needChanges()) {
|
if (!needChanges()) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
eptr<ICalComponent> icomp(retrieveItem(id));
|
||||||
|
#else
|
||||||
eptr<icalcomponent> icomp(retrieveItem(id));
|
eptr<icalcomponent> icomp(retrieveItem(id));
|
||||||
|
#endif
|
||||||
return getItemModTime(icomp);
|
return getItemModTime(icomp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1194,6 +1415,15 @@ string EvolutionCalendarSource::getItemModTime(icalcomponent *icomp)
|
||||||
return icalTime2Str(modTime);
|
return icalTime2Str(modTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
string EvolutionCalendarSource::getItemModTime(ICalComponent *icomp)
|
||||||
|
{
|
||||||
|
icalcomponent *native_icomp = static_cast<icalcomponent *>(i_cal_object_get_native(I_CAL_OBJECT (icomp)));
|
||||||
|
|
||||||
|
return getItemModTime(native_icomp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
string EvolutionCalendarSource::icalTime2Str(const icaltimetype &tt)
|
string EvolutionCalendarSource::icalTime2Str(const icaltimetype &tt)
|
||||||
{
|
{
|
||||||
static const struct icaltimetype null = { 0 };
|
static const struct icaltimetype null = { 0 };
|
||||||
|
@ -1208,6 +1438,21 @@ string EvolutionCalendarSource::icalTime2Str(const icaltimetype &tt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
string EvolutionCalendarSource::icalTime2Str(const ICalTime *tt)
|
||||||
|
{
|
||||||
|
if (tt || !i_cal_time_is_valid_time (tt) || i_cal_time_is_null_time (tt)) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
eptr<char> timestr(i_cal_time_as_ical_string(tt));
|
||||||
|
if (!timestr) {
|
||||||
|
SE_THROW("cannot convert to time string");
|
||||||
|
}
|
||||||
|
return timestr.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SE_END_CXX
|
SE_END_CXX
|
||||||
|
|
||||||
#endif /* ENABLE_ECAL */
|
#endif /* ENABLE_ECAL */
|
||||||
|
|
|
@ -134,6 +134,9 @@ class EvolutionCalendarSource : public EvolutionSyncSource,
|
||||||
*/
|
*/
|
||||||
static ItemID getItemID(ECalComponent *ecomp);
|
static ItemID getItemID(ECalComponent *ecomp);
|
||||||
static ItemID getItemID(icalcomponent *icomp);
|
static ItemID getItemID(icalcomponent *icomp);
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
static ItemID getItemID(ICalComponent *icomp);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract modification string from calendar item.
|
* Extract modification string from calendar item.
|
||||||
|
@ -141,6 +144,9 @@ class EvolutionCalendarSource : public EvolutionSyncSource,
|
||||||
*/
|
*/
|
||||||
static string getItemModTime(ECalComponent *ecomp);
|
static string getItemModTime(ECalComponent *ecomp);
|
||||||
static string getItemModTime(icalcomponent *icomp);
|
static string getItemModTime(icalcomponent *icomp);
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
static string getItemModTime(ICalComponent *icomp);
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//
|
//
|
||||||
|
@ -182,8 +188,8 @@ class EvolutionCalendarSource : public EvolutionSyncSource,
|
||||||
m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS ? e_source_registry_ref_builtin_calendar :
|
m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS ? e_source_registry_ref_builtin_calendar :
|
||||||
m_type == EVOLUTION_CAL_SOURCE_TYPE_TASKS ? e_source_registry_ref_builtin_task_list :
|
m_type == EVOLUTION_CAL_SOURCE_TYPE_TASKS ? e_source_registry_ref_builtin_task_list :
|
||||||
m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS ? e_source_registry_ref_builtin_memo_list :
|
m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS ? e_source_registry_ref_builtin_memo_list :
|
||||||
NULL;
|
nullptr;
|
||||||
return ESourceCXX(ref ? ref(EDSRegistryLoader::getESourceRegistry()) : NULL, TRANSFER_REF);
|
return ESourceCXX(ref ? ref(EDSRegistryLoader::getESourceRegistry()) : nullptr, TRANSFER_REF);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ECalSourceType sourceType() const {
|
ECalSourceType sourceType() const {
|
||||||
|
@ -196,18 +202,30 @@ class EvolutionCalendarSource : public EvolutionSyncSource,
|
||||||
*
|
*
|
||||||
* caller has to free result
|
* caller has to free result
|
||||||
*/
|
*/
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
ICalComponent *retrieveItem(const ItemID &id);
|
||||||
|
#else
|
||||||
icalcomponent *retrieveItem(const ItemID &id);
|
icalcomponent *retrieveItem(const ItemID &id);
|
||||||
|
#endif
|
||||||
|
|
||||||
/** retrieve the item with the given luid as VCALENDAR string - may throw exception */
|
/** retrieve the item with the given luid as VCALENDAR string - may throw exception */
|
||||||
string retrieveItemAsString(const ItemID &id);
|
string retrieveItemAsString(const ItemID &id);
|
||||||
|
|
||||||
|
|
||||||
/** returns the type which the ical library uses for our components */
|
/** returns the type which the ical library uses for our components */
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
ICalComponentKind getCompType() {
|
||||||
|
return m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS ? I_CAL_VEVENT_COMPONENT :
|
||||||
|
m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS ? I_CAL_VJOURNAL_COMPONENT :
|
||||||
|
I_CAL_VTODO_COMPONENT;
|
||||||
|
}
|
||||||
|
#else
|
||||||
icalcomponent_kind getCompType() {
|
icalcomponent_kind getCompType() {
|
||||||
return m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS ? ICAL_VEVENT_COMPONENT :
|
return m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS ? ICAL_VEVENT_COMPONENT :
|
||||||
m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS ? ICAL_VJOURNAL_COMPONENT :
|
m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS ? ICAL_VJOURNAL_COMPONENT :
|
||||||
ICAL_VTODO_COMPONENT;
|
ICAL_VTODO_COMPONENT;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef USE_EDS_CLIENT
|
#ifndef USE_EDS_CLIENT
|
||||||
/** ECalAuthFunc which calls the authenticate() methods */
|
/** ECalAuthFunc which calls the authenticate() methods */
|
||||||
|
@ -239,6 +257,9 @@ class EvolutionCalendarSource : public EvolutionSyncSource,
|
||||||
* Convert to string in canonical representation.
|
* Convert to string in canonical representation.
|
||||||
*/
|
*/
|
||||||
static string icalTime2Str(const struct icaltimetype &tt);
|
static string icalTime2Str(const struct icaltimetype &tt);
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
static string icalTime2Str(const ICalTime *tt);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set of all existing objects. Initialized in the last call to
|
* A set of all existing objects. Initialized in the last call to
|
||||||
|
@ -263,7 +284,11 @@ class EvolutionCalendarSource : public EvolutionSyncSource,
|
||||||
* will destroy the smart pointer, which then calls
|
* will destroy the smart pointer, which then calls
|
||||||
* icalcomponent_free().
|
* icalcomponent_free().
|
||||||
*/
|
*/
|
||||||
typedef list< boost::shared_ptr< eptr<icalcomponent> > > ICalComps_t;
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
typedef list< std::shared_ptr< eptr<ICalComponent> > > ICalComps_t;
|
||||||
|
#else
|
||||||
|
typedef list< std::shared_ptr< eptr<icalcomponent> > > ICalComps_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility function which extracts all icalcomponents with
|
* Utility function which extracts all icalcomponents with
|
||||||
|
|
|
@ -27,11 +27,13 @@
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
|
||||||
static SyncSource *createSource(const SyncSourceParams ¶ms)
|
static std::unique_ptr<SyncSource> createSource(const SyncSourceParams ¶ms)
|
||||||
{
|
{
|
||||||
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
||||||
bool isMe;
|
bool isMe;
|
||||||
|
#ifdef ENABLE_ECAL
|
||||||
const bool enabled = true;
|
const bool enabled = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
EDSAbiWrapperInit();
|
EDSAbiWrapperInit();
|
||||||
|
|
||||||
|
@ -43,9 +45,9 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
sourceType.m_format == "text/x-vcalendar") {
|
sourceType.m_format == "text/x-vcalendar") {
|
||||||
return
|
return
|
||||||
#ifdef ENABLE_ECAL
|
#ifdef ENABLE_ECAL
|
||||||
enabled ? new EvolutionCalendarSource(EVOLUTION_CAL_SOURCE_TYPE_TASKS, params) :
|
enabled ? std::make_unique<EvolutionCalendarSource>(EVOLUTION_CAL_SOURCE_TYPE_TASKS, params) :
|
||||||
#endif
|
#endif
|
||||||
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
|
isMe ? RegisterSyncSource::InactiveSource(params) : nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,17 +56,17 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
if (sourceType.m_format == "" || sourceType.m_format == "text/plain") {
|
if (sourceType.m_format == "" || sourceType.m_format == "text/plain") {
|
||||||
return
|
return
|
||||||
#ifdef ENABLE_ECAL
|
#ifdef ENABLE_ECAL
|
||||||
enabled ? new EvolutionMemoSource(params) :
|
enabled ? std::make_unique<EvolutionMemoSource>(params) :
|
||||||
#endif
|
#endif
|
||||||
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
|
isMe ? RegisterSyncSource::InactiveSource(params) : nullptr;
|
||||||
} else if (sourceType.m_format == "text/calendar") {
|
} else if (sourceType.m_format == "text/calendar") {
|
||||||
return
|
return
|
||||||
#ifdef ENABLE_ECAL
|
#ifdef ENABLE_ECAL
|
||||||
enabled ? new EvolutionCalendarSource(EVOLUTION_CAL_SOURCE_TYPE_MEMOS, params) :
|
enabled ? std::make_unique<EvolutionCalendarSource>(EVOLUTION_CAL_SOURCE_TYPE_MEMOS, params) :
|
||||||
#endif
|
#endif
|
||||||
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
|
isMe ? RegisterSyncSource::InactiveSource(params) : nullptr;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,15 +78,15 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
sourceType.m_format == "text/x-vcalendar") {
|
sourceType.m_format == "text/x-vcalendar") {
|
||||||
return
|
return
|
||||||
#ifdef ENABLE_ECAL
|
#ifdef ENABLE_ECAL
|
||||||
enabled ? new EvolutionCalendarSource(EVOLUTION_CAL_SOURCE_TYPE_EVENTS, params) :
|
enabled ? std::make_unique<EvolutionCalendarSource>(EVOLUTION_CAL_SOURCE_TYPE_EVENTS, params) :
|
||||||
#endif
|
#endif
|
||||||
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
|
isMe ? RegisterSyncSource::InactiveSource(params) : nullptr;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterSyncSource registerMe("Evolution Calendar/Task List/Memos",
|
static RegisterSyncSource registerMe("Evolution Calendar/Task List/Memos",
|
||||||
|
@ -124,44 +126,44 @@ class EvolutionCalendarTest : public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static string addItem(boost::shared_ptr<TestingSyncSource> source,
|
static string addItem(TestingSyncSource &source,
|
||||||
string &data) {
|
string &data) {
|
||||||
SyncSourceRaw::InsertItemResult res = source->insertItemRaw("", data);
|
SyncSourceRaw::InsertItemResult res = source.insertItemRaw("", data);
|
||||||
return res.m_luid;
|
return res.m_luid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void testInstantiate() {
|
void testInstantiate() {
|
||||||
boost::shared_ptr<TestingSyncSource> source;
|
std::unique_ptr<TestingSyncSource> source;
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "calendar", true));
|
source = SyncSource::createTestingSource("calendar", "calendar", true);
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "evolution-calendar", true));
|
source = SyncSource::createTestingSource("calendar", "evolution-calendar", true);
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "Evolution Calendar:text/calendar", true));
|
source = SyncSource::createTestingSource("calendar", "Evolution Calendar:text/calendar", true);
|
||||||
|
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "tasks", true));
|
source = SyncSource::createTestingSource("calendar", "tasks", true);
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "evolution-tasks", true));
|
source = SyncSource::createTestingSource("calendar", "evolution-tasks", true);
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "Evolution Tasks", true));
|
source = SyncSource::createTestingSource("calendar", "Evolution Tasks", true);
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "Evolution Task List:text/calendar", true));
|
source = SyncSource::createTestingSource("calendar", "Evolution Task List:text/calendar", true);
|
||||||
|
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "memos", true));
|
source = SyncSource::createTestingSource("calendar", "memos", true);
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "evolution-memos", true));
|
source = SyncSource::createTestingSource("calendar", "evolution-memos", true);
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "Evolution Memos:text/plain", true));
|
source = SyncSource::createTestingSource("calendar", "Evolution Memos:text/plain", true);
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "Evolution Memos:text/calendar", true));
|
source = SyncSource::createTestingSource("calendar", "Evolution Memos:text/calendar", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testOpenDefaultCalendar() {
|
void testOpenDefaultCalendar() {
|
||||||
boost::shared_ptr<TestingSyncSource> source;
|
std::unique_ptr<TestingSyncSource> source;
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "evolution-calendar", true, NULL));
|
source = SyncSource::createTestingSource("calendar", "evolution-calendar", true, nullptr);
|
||||||
CPPUNIT_ASSERT_NO_THROW(source->open());
|
CPPUNIT_ASSERT_NO_THROW(source->open());
|
||||||
}
|
}
|
||||||
|
|
||||||
void testOpenDefaultTodo() {
|
void testOpenDefaultTodo() {
|
||||||
boost::shared_ptr<TestingSyncSource> source;
|
std::unique_ptr<TestingSyncSource> source;
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "evolution-tasks", true, NULL));
|
source = SyncSource::createTestingSource("calendar", "evolution-tasks", true, nullptr);
|
||||||
CPPUNIT_ASSERT_NO_THROW(source->open());
|
CPPUNIT_ASSERT_NO_THROW(source->open());
|
||||||
}
|
}
|
||||||
|
|
||||||
void testOpenDefaultMemo() {
|
void testOpenDefaultMemo() {
|
||||||
boost::shared_ptr<TestingSyncSource> source;
|
std::unique_ptr<TestingSyncSource> source;
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("calendar", "evolution-memos", true, NULL));
|
source = SyncSource::createTestingSource("calendar", "evolution-memos", true, nullptr);
|
||||||
CPPUNIT_ASSERT_NO_THROW(source->open());
|
CPPUNIT_ASSERT_NO_THROW(source->open());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,8 +173,8 @@ protected:
|
||||||
prefix = "SyncEvolution_Test_";
|
prefix = "SyncEvolution_Test_";
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<TestingSyncSource> source;
|
std::unique_ptr<TestingSyncSource> source;
|
||||||
source.reset((TestingSyncSource *)SyncSource::createTestingSource("eds_event", "evolution-calendar", true, prefix));
|
source = SyncSource::createTestingSource("eds_event", "evolution-calendar", true, prefix);
|
||||||
CPPUNIT_ASSERT_NO_THROW(source->open());
|
CPPUNIT_ASSERT_NO_THROW(source->open());
|
||||||
|
|
||||||
string newyork =
|
string newyork =
|
||||||
|
@ -212,7 +214,7 @@ protected:
|
||||||
"END:VCALENDAR\n";
|
"END:VCALENDAR\n";
|
||||||
|
|
||||||
string luid;
|
string luid;
|
||||||
CPPUNIT_ASSERT_NO_THROW(luid = addItem(source, newyork));
|
CPPUNIT_ASSERT_NO_THROW(luid = addItem(*source, newyork));
|
||||||
|
|
||||||
string newyork_suffix = newyork;
|
string newyork_suffix = newyork;
|
||||||
boost::replace_first(newyork_suffix,
|
boost::replace_first(newyork_suffix,
|
||||||
|
@ -221,7 +223,7 @@ protected:
|
||||||
boost::replace_all(newyork_suffix,
|
boost::replace_all(newyork_suffix,
|
||||||
"TZID:America/New_York",
|
"TZID:America/New_York",
|
||||||
"TZID://FOOBAR/America/New_York-SUFFIX");
|
"TZID://FOOBAR/America/New_York-SUFFIX");
|
||||||
CPPUNIT_ASSERT_NO_THROW(luid = addItem(source, newyork_suffix));
|
CPPUNIT_ASSERT_NO_THROW(luid = addItem(*source, newyork_suffix));
|
||||||
|
|
||||||
|
|
||||||
string notimezone =
|
string notimezone =
|
||||||
|
@ -242,7 +244,7 @@ protected:
|
||||||
"LAST-MODIFIED:20060416T205301Z\n"
|
"LAST-MODIFIED:20060416T205301Z\n"
|
||||||
"END:VEVENT\n"
|
"END:VEVENT\n"
|
||||||
"END:VCALENDAR\n";
|
"END:VCALENDAR\n";
|
||||||
CPPUNIT_ASSERT_NO_THROW(luid = addItem(source, notimezone));
|
CPPUNIT_ASSERT_NO_THROW(luid = addItem(*source, notimezone));
|
||||||
|
|
||||||
// fake VTIMEZONE where daylight saving starts on first Sunday in March
|
// fake VTIMEZONE where daylight saving starts on first Sunday in March
|
||||||
string fake_march =
|
string fake_march =
|
||||||
|
@ -279,7 +281,7 @@ protected:
|
||||||
"LAST-MODIFIED:20060416T205301Z\n"
|
"LAST-MODIFIED:20060416T205301Z\n"
|
||||||
"END:VEVENT\n"
|
"END:VEVENT\n"
|
||||||
"END:VCALENDAR\n";
|
"END:VCALENDAR\n";
|
||||||
CPPUNIT_ASSERT_NO_THROW(luid = addItem(source, fake_march));
|
CPPUNIT_ASSERT_NO_THROW(luid = addItem(*source, fake_march));
|
||||||
|
|
||||||
string fake_may = fake_march;
|
string fake_may = fake_march;
|
||||||
boost::replace_first(fake_may,
|
boost::replace_first(fake_may,
|
||||||
|
@ -294,10 +296,10 @@ protected:
|
||||||
boost::replace_first(fake_may,
|
boost::replace_first(fake_may,
|
||||||
"TZNAME:EST MARCH",
|
"TZNAME:EST MARCH",
|
||||||
"TZNAME:EST MAY");
|
"TZNAME:EST MAY");
|
||||||
CPPUNIT_ASSERT_NO_THROW(luid = addItem(source, fake_may));
|
CPPUNIT_ASSERT_NO_THROW(luid = addItem(*source, fake_may));
|
||||||
|
|
||||||
// insert again, shouldn't re-add timezone
|
// insert again, shouldn't re-add timezone
|
||||||
CPPUNIT_ASSERT_NO_THROW(luid = addItem(source, fake_may));
|
CPPUNIT_ASSERT_NO_THROW(luid = addItem(*source, fake_may));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <list>
|
#include <list>
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "EvolutionSyncSource.h"
|
#include "EvolutionSyncSource.h"
|
||||||
|
@ -41,8 +40,6 @@ using namespace std;
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/algorithm/string/join.hpp>
|
#include <boost/algorithm/string/join.hpp>
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/lambda/lambda.hpp>
|
|
||||||
|
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
|
|
||||||
|
@ -121,8 +118,8 @@ EvolutionSyncSource::Databases EvolutionContactSource::getDatabases()
|
||||||
E_SOURCE_EXTENSION_ADDRESS_BOOK,
|
E_SOURCE_EXTENSION_ADDRESS_BOOK,
|
||||||
e_source_registry_ref_default_address_book);
|
e_source_registry_ref_default_address_book);
|
||||||
#else
|
#else
|
||||||
ESourceList *sources = NULL;
|
ESourceList *sources = nullptr;
|
||||||
if (!e_book_get_addressbooks(&sources, NULL)) {
|
if (!e_book_get_addressbooks(&sources, nullptr)) {
|
||||||
Exception::throwError(SE_HERE, "unable to access address books");
|
Exception::throwError(SE_HERE, "unable to access address books");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,7 +287,7 @@ bool EvolutionContactSource::isEmpty()
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
class EBookClientViewSyncHandler {
|
class EBookClientViewSyncHandler {
|
||||||
public:
|
public:
|
||||||
typedef boost::function<void (const GSList *list)> Process_t;
|
typedef std::function<void (const GSList *list)> Process_t;
|
||||||
|
|
||||||
EBookClientViewSyncHandler(const EBookClientViewCXX &view,
|
EBookClientViewSyncHandler(const EBookClientViewCXX &view,
|
||||||
const Process_t &process) :
|
const Process_t &process) :
|
||||||
|
@ -300,12 +297,12 @@ class EBookClientViewSyncHandler {
|
||||||
|
|
||||||
bool process(GErrorCXX &gerror) {
|
bool process(GErrorCXX &gerror) {
|
||||||
// Listen for view signals
|
// Listen for view signals
|
||||||
m_view.connectSignal<void (EBookClientView *ebookview,
|
m_view.connectSignal<EBookClientView *,
|
||||||
const GSList *contacts)>("objects-added",
|
const GSList *>()("objects-added",
|
||||||
boost::bind(m_process, _2));
|
[this] (EBookClientView *, const GSList *list) { m_process(list); } );
|
||||||
m_view.connectSignal<void (EBookClientView *ebookview,
|
m_view.connectSignal<EBookClientView *,
|
||||||
const GError *error)>("complete",
|
const GError *>()("complete",
|
||||||
boost::bind(&EBookClientViewSyncHandler::completed, this, _2));
|
[this] (EBookClientView *, const GError *gerror) { completed(gerror); });
|
||||||
|
|
||||||
// Start the view
|
// Start the view
|
||||||
e_book_client_view_start (m_view, m_error);
|
e_book_client_view_start (m_view, m_error);
|
||||||
|
@ -316,7 +313,7 @@ class EBookClientViewSyncHandler {
|
||||||
|
|
||||||
// Async -> Sync
|
// Async -> Sync
|
||||||
m_loop.run();
|
m_loop.run();
|
||||||
e_book_client_view_stop (m_view, NULL);
|
e_book_client_view_stop (m_view, nullptr);
|
||||||
|
|
||||||
if (m_error) {
|
if (m_error) {
|
||||||
std::swap(gerror, m_error);
|
std::swap(gerror, m_error);
|
||||||
|
@ -337,39 +334,12 @@ class EBookClientViewSyncHandler {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Process list callback
|
// Process list callback
|
||||||
boost::function<void (const GSList *list)> m_process;
|
std::function<void (const GSList *list)> m_process;
|
||||||
// View watched
|
// View watched
|
||||||
EBookClientViewCXX m_view;
|
EBookClientViewCXX m_view;
|
||||||
// Possible error while watching the view
|
// Possible error while watching the view
|
||||||
GErrorCXX m_error;
|
GErrorCXX m_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void list_revisions(const GSList *contacts, EvolutionContactSource::RevisionMap_t *revisions)
|
|
||||||
{
|
|
||||||
const GSList *l;
|
|
||||||
|
|
||||||
for (l = contacts; l; l = l->next) {
|
|
||||||
EContact *contact = E_CONTACT(l->data);
|
|
||||||
if (!contact) {
|
|
||||||
SE_THROW("contact entry without data");
|
|
||||||
}
|
|
||||||
pair<string, string> revmapping;
|
|
||||||
const char *uid = (const char *)e_contact_get_const(contact,
|
|
||||||
E_CONTACT_UID);
|
|
||||||
if (!uid || !uid[0]) {
|
|
||||||
SE_THROW("contact entry without UID");
|
|
||||||
}
|
|
||||||
revmapping.first = uid;
|
|
||||||
const char *rev = (const char *)e_contact_get_const(contact,
|
|
||||||
E_CONTACT_REV);
|
|
||||||
if (!rev || !rev[0]) {
|
|
||||||
SE_THROW(string("contact entry without REV: ") + revmapping.first);
|
|
||||||
}
|
|
||||||
revmapping.second = rev;
|
|
||||||
revisions->insert(revmapping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void EvolutionContactSource::listAllItems(RevisionMap_t &revisions)
|
void EvolutionContactSource::listAllItems(RevisionMap_t &revisions)
|
||||||
|
@ -387,7 +357,7 @@ void EvolutionContactSource::listAllItems(RevisionMap_t &revisions)
|
||||||
sexp = buffer;
|
sexp = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!e_book_client_get_view_sync(m_addressbook, sexp, &view, NULL, gerror)) {
|
if (!e_book_client_get_view_sync(m_addressbook, sexp, &view, nullptr, gerror)) {
|
||||||
throwError(SE_HERE, "getting the view" , gerror);
|
throwError(SE_HERE, "getting the view" , gerror);
|
||||||
}
|
}
|
||||||
EBookClientViewCXX viewPtr = EBookClientViewCXX::steal(view);
|
EBookClientViewCXX viewPtr = EBookClientViewCXX::steal(view);
|
||||||
|
@ -402,7 +372,28 @@ void EvolutionContactSource::listAllItems(RevisionMap_t &revisions)
|
||||||
gerror.clear();
|
gerror.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
EBookClientViewSyncHandler handler(viewPtr, boost::bind(list_revisions, _1, &revisions));
|
auto process = [&revisions] (const GSList *contacts) {
|
||||||
|
const GSList *l;
|
||||||
|
|
||||||
|
for (l = contacts; l; l = l->next) {
|
||||||
|
EContact *contact = E_CONTACT(l->data);
|
||||||
|
if (!contact) {
|
||||||
|
SE_THROW("contact entry without data");
|
||||||
|
}
|
||||||
|
const char *uid = (const char *)e_contact_get_const(contact,
|
||||||
|
E_CONTACT_UID);
|
||||||
|
if (!uid || !uid[0]) {
|
||||||
|
SE_THROW("contact entry without UID");
|
||||||
|
}
|
||||||
|
const char *rev = (const char *)e_contact_get_const(contact,
|
||||||
|
E_CONTACT_REV);
|
||||||
|
if (!rev || !rev[0]) {
|
||||||
|
SE_THROW(string("contact entry without REV: ") + uid);
|
||||||
|
}
|
||||||
|
revisions[uid] = rev;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
EBookClientViewSyncHandler handler(viewPtr, process);
|
||||||
if (!handler.process(gerror)) {
|
if (!handler.process(gerror)) {
|
||||||
throwError(SE_HERE, "watching view", gerror);
|
throwError(SE_HERE, "watching view", gerror);
|
||||||
}
|
}
|
||||||
|
@ -456,7 +447,7 @@ string EvolutionContactSource::getRevision(const string &luid)
|
||||||
!e_book_client_get_contact_sync(m_addressbook,
|
!e_book_client_get_contact_sync(m_addressbook,
|
||||||
luid.c_str(),
|
luid.c_str(),
|
||||||
&contact,
|
&contact,
|
||||||
NULL,
|
nullptr,
|
||||||
gerror)
|
gerror)
|
||||||
#else
|
#else
|
||||||
!e_book_get_contact(m_addressbook,
|
!e_book_get_contact(m_addressbook,
|
||||||
|
@ -528,7 +519,7 @@ void EvolutionContactSource::getReadAheadOrder(ReadAheadOrder &order,
|
||||||
luids = m_nextLUIDs;
|
luids = m_nextLUIDs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvolutionContactSource::checkCacheForError(boost::shared_ptr<ContactCache> &cache)
|
void EvolutionContactSource::checkCacheForError(std::shared_ptr<ContactCache> &cache)
|
||||||
{
|
{
|
||||||
if (cache->m_gerror) {
|
if (cache->m_gerror) {
|
||||||
GErrorCXX gerror;
|
GErrorCXX gerror;
|
||||||
|
@ -544,10 +535,10 @@ void EvolutionContactSource::invalidateCachedContact(const std::string &luid)
|
||||||
invalidateCachedContact(m_contactCacheNext, luid);
|
invalidateCachedContact(m_contactCacheNext, luid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvolutionContactSource::invalidateCachedContact(boost::shared_ptr<ContactCache> &cache, const std::string &luid)
|
void EvolutionContactSource::invalidateCachedContact(std::shared_ptr<ContactCache> &cache, const std::string &luid)
|
||||||
{
|
{
|
||||||
if (cache) {
|
if (cache) {
|
||||||
ContactCache::iterator it = cache->find(luid);
|
auto it = cache->find(luid);
|
||||||
if (it != cache->end()) {
|
if (it != cache->end()) {
|
||||||
SE_LOG_DEBUG(getDisplayName(), "reading: remove contact %s from cache because of remove or update", luid.c_str());
|
SE_LOG_DEBUG(getDisplayName(), "reading: remove contact %s from cache because of remove or update", luid.c_str());
|
||||||
// If we happen to read that contact (unlikely), it'll be
|
// If we happen to read that contact (unlikely), it'll be
|
||||||
|
@ -591,7 +582,7 @@ bool EvolutionContactSource::getContact(const string &luid, EContact **contact,
|
||||||
return e_book_client_get_contact_sync(m_addressbook,
|
return e_book_client_get_contact_sync(m_addressbook,
|
||||||
luid.c_str(),
|
luid.c_str(),
|
||||||
contact,
|
contact,
|
||||||
NULL,
|
nullptr,
|
||||||
gerror);
|
gerror);
|
||||||
} else {
|
} else {
|
||||||
return getContactFromCache(luid, contact, gerror);
|
return getContactFromCache(luid, contact, gerror);
|
||||||
|
@ -600,7 +591,7 @@ bool EvolutionContactSource::getContact(const string &luid, EContact **contact,
|
||||||
|
|
||||||
bool EvolutionContactSource::getContactFromCache(const string &luid, EContact **contact, GErrorCXX &gerror)
|
bool EvolutionContactSource::getContactFromCache(const string &luid, EContact **contact, GErrorCXX &gerror)
|
||||||
{
|
{
|
||||||
*contact = NULL;
|
*contact = nullptr;
|
||||||
|
|
||||||
// Use ContactCache.
|
// Use ContactCache.
|
||||||
if (m_contactCache) {
|
if (m_contactCache) {
|
||||||
|
@ -609,7 +600,7 @@ bool EvolutionContactSource::getContactFromCache(const string &luid, EContact **
|
||||||
checkCacheForError(m_contactCache);
|
checkCacheForError(m_contactCache);
|
||||||
|
|
||||||
// Does the cache cover our item?
|
// Does the cache cover our item?
|
||||||
ContactCache::const_iterator it = m_contactCache->find(luid);
|
auto it = m_contactCache->find(luid);
|
||||||
if (it == m_contactCache->end()) {
|
if (it == m_contactCache->end()) {
|
||||||
if (m_contactCacheNext) {
|
if (m_contactCacheNext) {
|
||||||
SE_LOG_DEBUG(getDisplayName(), "reading: not in cache, try cache %s",
|
SE_LOG_DEBUG(getDisplayName(), "reading: not in cache, try cache %s",
|
||||||
|
@ -628,7 +619,7 @@ bool EvolutionContactSource::getContactFromCache(const string &luid, EContact **
|
||||||
SE_LOG_DEBUG(getDisplayName(), "reading: in %s cache", m_contactCache->m_running ? "running" : "loaded");
|
SE_LOG_DEBUG(getDisplayName(), "reading: in %s cache", m_contactCache->m_running ? "running" : "loaded");
|
||||||
if (m_contactCache->m_running) {
|
if (m_contactCache->m_running) {
|
||||||
m_cacheStalls++;
|
m_cacheStalls++;
|
||||||
GRunWhile(boost::lambda::var(m_contactCache->m_running));
|
GRunWhile([this] () { return this->m_contactCache->m_running; });
|
||||||
}
|
}
|
||||||
// Problem?
|
// Problem?
|
||||||
checkCacheForError(m_contactCache);
|
checkCacheForError(m_contactCache);
|
||||||
|
@ -673,7 +664,7 @@ static int MaxBatchSize()
|
||||||
return maxBatchSize;
|
return maxBatchSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<ContactCache> EvolutionContactSource::startReading(const std::string &luid, ReadingMode mode)
|
std::shared_ptr<ContactCache> EvolutionContactSource::startReading(const std::string &luid, ReadingMode mode)
|
||||||
{
|
{
|
||||||
SE_LOG_DEBUG(getDisplayName(), "reading: %s contact %s",
|
SE_LOG_DEBUG(getDisplayName(), "reading: %s contact %s",
|
||||||
mode == START ? "must read" :
|
mode == START ? "must read" :
|
||||||
|
@ -695,7 +686,7 @@ boost::shared_ptr<ContactCache> EvolutionContactSource::startReading(const std::
|
||||||
const Items_t &items = getAllItems();
|
const Items_t &items = getAllItems();
|
||||||
const Items_t &newItems = getNewItems();
|
const Items_t &newItems = getNewItems();
|
||||||
const Items_t &updatedItems = getUpdatedItems();
|
const Items_t &updatedItems = getUpdatedItems();
|
||||||
Items_t::const_iterator it = items.find(luid);
|
auto it = items.find(luid);
|
||||||
|
|
||||||
// Always read the requested item, even if not found in item list?
|
// Always read the requested item, even if not found in item list?
|
||||||
if (mode == START) {
|
if (mode == START) {
|
||||||
|
@ -727,7 +718,7 @@ boost::shared_ptr<ContactCache> EvolutionContactSource::startReading(const std::
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case READ_SELECTED_ITEMS: {
|
case READ_SELECTED_ITEMS: {
|
||||||
ReadAheadItems::const_iterator it = boost::find(std::make_pair(m_nextLUIDs.begin(), m_nextLUIDs.end()), luid);
|
auto it = boost::find(std::make_pair(m_nextLUIDs.begin(), m_nextLUIDs.end()), luid);
|
||||||
// Always read the requested item, even if not found in item list?
|
// Always read the requested item, even if not found in item list?
|
||||||
if (mode == START) {
|
if (mode == START) {
|
||||||
uids[0] = &luid;
|
uids[0] = &luid;
|
||||||
|
@ -767,10 +758,10 @@ boost::shared_ptr<ContactCache> EvolutionContactSource::startReading(const std::
|
||||||
m_readAheadOrder = READ_NONE;
|
m_readAheadOrder = READ_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<ContactCache> cache;
|
std::shared_ptr<ContactCache> cache;
|
||||||
if (size) {
|
if (size) {
|
||||||
// Prepare parameter for EDS C call. Ownership of query instances is in uidQueries array.
|
// Prepare parameter for EDS C call. Ownership of query instances is in uidQueries array.
|
||||||
boost::scoped_array<EBookQuery *> queries(new EBookQuery *[size]);
|
auto queries = std::make_unique<EBookQuery *[]>(size);
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
// This shouldn't compile because we don't specify how ownership is handled.
|
// This shouldn't compile because we don't specify how ownership is handled.
|
||||||
// The reset() method always bumps the ref count, which is not what we want here!
|
// The reset() method always bumps the ref count, which is not what we want here!
|
||||||
|
@ -787,52 +778,45 @@ boost::shared_ptr<ContactCache> EvolutionContactSource::startReading(const std::
|
||||||
cache->m_running = true;
|
cache->m_running = true;
|
||||||
cache->m_name = StringPrintf("%s-%s (%d)", uids[0]->c_str(), uids[size - 1]->c_str(), size);
|
cache->m_name = StringPrintf("%s-%s (%d)", uids[0]->c_str(), uids[size - 1]->c_str(), size);
|
||||||
cache->m_lastLUID = *uids[size - 1];
|
cache->m_lastLUID = *uids[size - 1];
|
||||||
BOOST_FOREACH (const std::string *uid, std::make_pair(uids.begin(), uids.begin() + size)) {
|
for (const std::string *uid: boost::make_iterator_range(uids.begin(), uids.begin() + size)) {
|
||||||
(*cache)[*uid] = EContactCXX();
|
(*cache)[*uid] = EContactCXX();
|
||||||
}
|
}
|
||||||
m_contactsFromDB += size;
|
m_contactsFromDB += size;
|
||||||
m_contactQueries++;
|
m_contactQueries++;
|
||||||
SYNCEVO_GLIB_CALL_ASYNC(e_book_client_get_contacts,
|
auto process = [this, cachePtr=std::weak_ptr<ContactCache>(cache)] (gboolean success, GSList *contactsPtr, const GError *gerror) noexcept {
|
||||||
boost::bind(&EvolutionContactSource::completedRead,
|
try {
|
||||||
this,
|
using ContactListCXX = GListCXX< EContact, GSList, GObjectDestructor<EContact> >;
|
||||||
boost::weak_ptr<ContactCache>(cache),
|
ContactListCXX contacts(contactsPtr); // transfers ownership
|
||||||
_1, _2, _3),
|
std::shared_ptr<ContactCache> cache = cachePtr.lock();
|
||||||
m_addressbook, sexp, NULL);
|
if (!cache) {
|
||||||
|
SE_LOG_DEBUG(getDisplayName(), "reading: contact read finished, results no longer needed: %s", gerror ? gerror->message : "<<successful>>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SE_LOG_DEBUG(getDisplayName(), "reading: contact read %s finished: %s",
|
||||||
|
cache->m_name.c_str(),
|
||||||
|
gerror ? gerror->message : "<<successful>>");
|
||||||
|
if (success) {
|
||||||
|
for (EContact *contact: contacts) {
|
||||||
|
const char *uid = (const char *)e_contact_get_const(contact, E_CONTACT_UID);
|
||||||
|
SE_LOG_DEBUG(getDisplayName(), "reading: contact read %s got %s", cache->m_name.c_str(), uid);
|
||||||
|
(*cache)[uid] = EContactCXX(contact, ADD_REF);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cache->m_gerror = gerror;
|
||||||
|
}
|
||||||
|
cache->m_running = false;
|
||||||
|
} catch (...) {
|
||||||
|
Exception::handle(HANDLE_EXCEPTION_FATAL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SYNCEVO_GLIB_CALL_ASYNC(e_book_client_get_contacts, process,
|
||||||
|
m_addressbook, sexp, nullptr);
|
||||||
SE_LOG_DEBUG(getDisplayName(), "reading: started contact read %s", cache->m_name.c_str());
|
SE_LOG_DEBUG(getDisplayName(), "reading: started contact read %s", cache->m_name.c_str());
|
||||||
}
|
}
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef GListCXX< EContact, GSList, GObjectDestructor<EContact> > ContactListCXX;
|
|
||||||
|
|
||||||
void EvolutionContactSource::completedRead(const boost::weak_ptr<ContactCache> &cachePtr, gboolean success, GSList *contactsPtr, const GError *gerror) throw()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
ContactListCXX contacts(contactsPtr); // transfers ownership
|
|
||||||
boost::shared_ptr<ContactCache> cache = cachePtr.lock();
|
|
||||||
if (!cache) {
|
|
||||||
SE_LOG_DEBUG(getDisplayName(), "reading: contact read finished, results no longer needed: %s", gerror ? gerror->message : "<<successful>>");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SE_LOG_DEBUG(getDisplayName(), "reading: contact read %s finished: %s",
|
|
||||||
cache->m_name.c_str(),
|
|
||||||
gerror ? gerror->message : "<<successful>>");
|
|
||||||
if (success) {
|
|
||||||
BOOST_FOREACH (EContact *contact, contacts) {
|
|
||||||
const char *uid = (const char *)e_contact_get_const(contact, E_CONTACT_UID);
|
|
||||||
SE_LOG_DEBUG(getDisplayName(), "reading: contact read %s got %s", cache->m_name.c_str(), uid);
|
|
||||||
(*cache)[uid] = EContactCXX(contact, ADD_REF);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cache->m_gerror = gerror;
|
|
||||||
}
|
|
||||||
cache->m_running = false;
|
|
||||||
} catch (...) {
|
|
||||||
Exception::handle(HANDLE_EXCEPTION_FATAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EvolutionContactSource::logCacheStats(Logger::Level level)
|
void EvolutionContactSource::logCacheStats(Logger::Level level)
|
||||||
{
|
{
|
||||||
SE_LOG(getDisplayName(), level,
|
SE_LOG(getDisplayName(), level,
|
||||||
|
@ -873,7 +857,7 @@ void EvolutionContactSource::readItem(const string &luid, std::string &item, boo
|
||||||
// Inline PHOTO data if exporting, leave VALUE=uri references unchanged
|
// Inline PHOTO data if exporting, leave VALUE=uri references unchanged
|
||||||
// when processing inside engine (will be inlined by engine as needed).
|
// when processing inside engine (will be inlined by engine as needed).
|
||||||
// The function for doing the inlining was added in EDS 3.4.
|
// The function for doing the inlining was added in EDS 3.4.
|
||||||
// In compatibility mode, we must check the function pointer for non-NULL.
|
// In compatibility mode, we must check the function pointer for non-nullptr.
|
||||||
// In direct call mode, the existence check is done by configure.
|
// In direct call mode, the existence check is done by configure.
|
||||||
if (raw) {
|
if (raw) {
|
||||||
#if defined(HAVE_E_CONTACT_INLINE_LOCAL_PHOTOS)
|
#if defined(HAVE_E_CONTACT_INLINE_LOCAL_PHOTOS)
|
||||||
|
@ -893,11 +877,11 @@ void EvolutionContactSource::readItem(const string &luid, std::string &item, boo
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
TrackingSyncSource::InsertItemResult EvolutionContactSource::checkBatchedInsert(const boost::shared_ptr<Pending> &pending)
|
TrackingSyncSource::InsertItemResult EvolutionContactSource::checkBatchedInsert(const std::shared_ptr<Pending> &pending)
|
||||||
{
|
{
|
||||||
SE_LOG_DEBUG(pending->m_name, "checking operation: %s", pending->m_status == MODIFYING ? "waiting" : "inserted");
|
SE_LOG_DEBUG(pending->m_name, "checking operation: %s", pending->m_status == MODIFYING ? "waiting" : "inserted");
|
||||||
if (pending->m_status == MODIFYING) {
|
if (pending->m_status == MODIFYING) {
|
||||||
return TrackingSyncSource::InsertItemResult(boost::bind(&EvolutionContactSource::checkBatchedInsert, this, pending));
|
return TrackingSyncSource::InsertItemResult([this, pending] () { return checkBatchedInsert(pending); });
|
||||||
}
|
}
|
||||||
if (pending->m_gerror) {
|
if (pending->m_gerror) {
|
||||||
pending->m_gerror.throwError(SE_HERE, pending->m_name);
|
pending->m_gerror.throwError(SE_HERE, pending->m_name);
|
||||||
|
@ -906,70 +890,6 @@ TrackingSyncSource::InsertItemResult EvolutionContactSource::checkBatchedInsert(
|
||||||
return TrackingSyncSource::InsertItemResult(pending->m_uid, newrev, ITEM_OKAY);
|
return TrackingSyncSource::InsertItemResult(pending->m_uid, newrev, ITEM_OKAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvolutionContactSource::completedAdd(const boost::shared_ptr<PendingContainer_t> &batched, gboolean success, GSList *uids, const GError *gerror) throw()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// The destructor ensures that the pending operations complete
|
|
||||||
// before destructing the instance, so our "this" pointer is
|
|
||||||
// always valid here.
|
|
||||||
SE_LOG_DEBUG(getDisplayName(), "batch add of %d contacts completed", (int)batched->size());
|
|
||||||
m_numRunningOperations--;
|
|
||||||
PendingContainer_t::iterator it = (*batched).begin();
|
|
||||||
GSList *uid = uids;
|
|
||||||
while (it != (*batched).end() && uid) {
|
|
||||||
SE_LOG_DEBUG((*it)->m_name, "completed: %s",
|
|
||||||
success ? "<<successfully>>" :
|
|
||||||
gerror ? gerror->message :
|
|
||||||
"<<unknown failure>>");
|
|
||||||
if (success) {
|
|
||||||
(*it)->m_uid = static_cast<gchar *>(uid->data);
|
|
||||||
// Get revision when engine checks the item.
|
|
||||||
(*it)->m_status = REVISION;
|
|
||||||
} else {
|
|
||||||
(*it)->m_status = DONE;
|
|
||||||
(*it)->m_gerror = gerror;
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
uid = uid->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (it != (*batched).end()) {
|
|
||||||
// Should never happen.
|
|
||||||
SE_LOG_DEBUG((*it)->m_name, "completed: missing uid?!");
|
|
||||||
(*it)->m_status = DONE;
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_slist_free_full(uids, g_free);
|
|
||||||
} catch (...) {
|
|
||||||
Exception::handle(HANDLE_EXCEPTION_FATAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EvolutionContactSource::completedUpdate(const boost::shared_ptr<PendingContainer_t> &batched, gboolean success, const GError *gerror) throw()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
SE_LOG_DEBUG(getDisplayName(), "batch update of %d contacts completed", (int)batched->size());
|
|
||||||
m_numRunningOperations--;
|
|
||||||
PendingContainer_t::iterator it = (*batched).begin();
|
|
||||||
while (it != (*batched).end()) {
|
|
||||||
SE_LOG_DEBUG((*it)->m_name, "completed: %s",
|
|
||||||
success ? "<<successfully>>" :
|
|
||||||
gerror ? gerror->message :
|
|
||||||
"<<unknown failure>>");
|
|
||||||
if (success) {
|
|
||||||
(*it)->m_status = REVISION;
|
|
||||||
} else {
|
|
||||||
(*it)->m_status = DONE;
|
|
||||||
(*it)->m_gerror = gerror;
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
} catch (...) {
|
|
||||||
Exception::handle(HANDLE_EXCEPTION_FATAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EvolutionContactSource::flushItemChanges()
|
void EvolutionContactSource::flushItemChanges()
|
||||||
{
|
{
|
||||||
if (!m_batchedAdd.empty()) {
|
if (!m_batchedAdd.empty()) {
|
||||||
|
@ -977,34 +897,94 @@ void EvolutionContactSource::flushItemChanges()
|
||||||
m_numRunningOperations++;
|
m_numRunningOperations++;
|
||||||
GListCXX<EContact, GSList> contacts;
|
GListCXX<EContact, GSList> contacts;
|
||||||
// Iterate backwards, push to front (cheaper for single-linked list) -> same order in the end.
|
// Iterate backwards, push to front (cheaper for single-linked list) -> same order in the end.
|
||||||
BOOST_REVERSE_FOREACH (const boost::shared_ptr<Pending> &pending, m_batchedAdd) {
|
for (const auto &pending: reverse(m_batchedAdd)) {
|
||||||
contacts.push_front(pending->m_contact.get());
|
contacts.push_front(pending->m_contact.get());
|
||||||
}
|
}
|
||||||
// Transfer content without copying and then copy only the shared pointer.
|
// Transfer content without copying and then copy only the shared pointer.
|
||||||
boost::shared_ptr<PendingContainer_t> batched(new PendingContainer_t);
|
auto batched = std::make_shared<PendingContainer_t>();
|
||||||
std::swap(*batched, m_batchedAdd);
|
std::swap(*batched, m_batchedAdd);
|
||||||
SYNCEVO_GLIB_CALL_ASYNC(e_book_client_add_contacts,
|
auto process = [this, batched] (gboolean success, GSList *uids, const GError *gerror) noexcept {
|
||||||
boost::bind(&EvolutionContactSource::completedAdd,
|
try {
|
||||||
this,
|
// The destructor ensures that the pending operations complete
|
||||||
batched,
|
// before destructing the instance, so our "this" pointer is
|
||||||
_1, _2, _3),
|
// always valid here.
|
||||||
m_addressbook, contacts, NULL);
|
SE_LOG_DEBUG(getDisplayName(), "batch add of %d contacts completed", (int)batched->size());
|
||||||
|
m_numRunningOperations--;
|
||||||
|
auto it = (*batched).begin();
|
||||||
|
GSList *uid = uids;
|
||||||
|
while (it != (*batched).end() && uid) {
|
||||||
|
SE_LOG_DEBUG((*it)->m_name, "completed: %s",
|
||||||
|
success ? "<<successfully>>" :
|
||||||
|
gerror ? gerror->message :
|
||||||
|
"<<unknown failure>>");
|
||||||
|
if (success) {
|
||||||
|
(*it)->m_uid = static_cast<gchar *>(uid->data);
|
||||||
|
// Get revision when engine checks the item.
|
||||||
|
(*it)->m_status = REVISION;
|
||||||
|
} else {
|
||||||
|
(*it)->m_status = DONE;
|
||||||
|
(*it)->m_gerror = gerror;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
uid = uid->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (it != (*batched).end()) {
|
||||||
|
// Should never happen.
|
||||||
|
SE_LOG_DEBUG((*it)->m_name, "completed: missing uid?!");
|
||||||
|
(*it)->m_status = DONE;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_slist_free_full(uids, g_free);
|
||||||
|
} catch (...) {
|
||||||
|
Exception::handle(HANDLE_EXCEPTION_FATAL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SYNCEVO_GLIB_CALL_ASYNC(e_book_client_add_contacts, process,
|
||||||
|
m_addressbook, contacts,
|
||||||
|
#ifdef HAVE_E_BOOK_OPERATION_FLAGS
|
||||||
|
E_BOOK_OPERATION_FLAG_NONE,
|
||||||
|
#endif
|
||||||
|
nullptr);
|
||||||
}
|
}
|
||||||
if (!m_batchedUpdate.empty()) {
|
if (!m_batchedUpdate.empty()) {
|
||||||
SE_LOG_DEBUG(getDisplayName(), "batch update of %d contacts starting", (int)m_batchedUpdate.size());
|
SE_LOG_DEBUG(getDisplayName(), "batch update of %d contacts starting", (int)m_batchedUpdate.size());
|
||||||
m_numRunningOperations++;
|
m_numRunningOperations++;
|
||||||
GListCXX<EContact, GSList> contacts;
|
GListCXX<EContact, GSList> contacts;
|
||||||
BOOST_REVERSE_FOREACH (const boost::shared_ptr<Pending> &pending, m_batchedUpdate) {
|
for (const auto &pending: reverse(m_batchedUpdate)) {
|
||||||
contacts.push_front(pending->m_contact.get());
|
contacts.push_front(pending->m_contact.get());
|
||||||
}
|
}
|
||||||
boost::shared_ptr<PendingContainer_t> batched(new PendingContainer_t);
|
auto batched = std::make_shared<PendingContainer_t>();
|
||||||
std::swap(*batched, m_batchedUpdate);
|
std::swap(*batched, m_batchedUpdate);
|
||||||
SYNCEVO_GLIB_CALL_ASYNC(e_book_client_modify_contacts,
|
auto process = [this, batched] (gboolean success, const GError *gerror) noexcept {
|
||||||
boost::bind(&EvolutionContactSource::completedUpdate,
|
try {
|
||||||
this,
|
SE_LOG_DEBUG(getDisplayName(), "batch update of %d contacts completed", (int)batched->size());
|
||||||
batched,
|
m_numRunningOperations--;
|
||||||
_1, _2),
|
auto it = (*batched).begin();
|
||||||
m_addressbook, contacts, NULL);
|
while (it != (*batched).end()) {
|
||||||
|
SE_LOG_DEBUG((*it)->m_name, "completed: %s",
|
||||||
|
success ? "<<successfully>>" :
|
||||||
|
gerror ? gerror->message :
|
||||||
|
"<<unknown failure>>");
|
||||||
|
if (success) {
|
||||||
|
(*it)->m_status = REVISION;
|
||||||
|
} else {
|
||||||
|
(*it)->m_status = DONE;
|
||||||
|
(*it)->m_gerror = gerror;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
Exception::handle(HANDLE_EXCEPTION_FATAL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SYNCEVO_GLIB_CALL_ASYNC(e_book_client_modify_contacts, process,
|
||||||
|
m_addressbook, contacts,
|
||||||
|
#ifdef HAVE_E_BOOK_OPERATION_FLAGS
|
||||||
|
E_BOOK_OPERATION_FLAG_NONE,
|
||||||
|
#endif
|
||||||
|
nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1013,7 +993,7 @@ void EvolutionContactSource::finishItemChanges()
|
||||||
if (m_numRunningOperations) {
|
if (m_numRunningOperations) {
|
||||||
SE_LOG_DEBUG(getDisplayName(), "waiting for %d pending operations to complete", m_numRunningOperations.get());
|
SE_LOG_DEBUG(getDisplayName(), "waiting for %d pending operations to complete", m_numRunningOperations.get());
|
||||||
while (m_numRunningOperations) {
|
while (m_numRunningOperations) {
|
||||||
g_main_context_iteration(NULL, true);
|
g_main_context_iteration(nullptr, true);
|
||||||
}
|
}
|
||||||
SE_LOG_DEBUG(getDisplayName(), "pending operations completed");
|
SE_LOG_DEBUG(getDisplayName(), "pending operations completed");
|
||||||
}
|
}
|
||||||
|
@ -1028,7 +1008,7 @@ EvolutionContactSource::insertItem(const string &uid, const std::string &item, b
|
||||||
if (contact) {
|
if (contact) {
|
||||||
e_contact_set(contact, E_CONTACT_UID,
|
e_contact_set(contact, E_CONTACT_UID,
|
||||||
uid.empty() ?
|
uid.empty() ?
|
||||||
NULL :
|
nullptr :
|
||||||
const_cast<char *>(uid.c_str()));
|
const_cast<char *>(uid.c_str()));
|
||||||
GErrorCXX gerror;
|
GErrorCXX gerror;
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
|
@ -1037,14 +1017,22 @@ EvolutionContactSource::insertItem(const string &uid, const std::string &item, b
|
||||||
case SYNCHRONOUS:
|
case SYNCHRONOUS:
|
||||||
if (uid.empty()) {
|
if (uid.empty()) {
|
||||||
gchar* newuid;
|
gchar* newuid;
|
||||||
if (!e_book_client_add_contact_sync(m_addressbook, contact, &newuid, NULL, gerror)) {
|
if (!e_book_client_add_contact_sync(m_addressbook, contact,
|
||||||
|
#ifdef HAVE_E_BOOK_OPERATION_FLAGS
|
||||||
|
E_BOOK_OPERATION_FLAG_NONE,
|
||||||
|
#endif
|
||||||
|
&newuid, nullptr, gerror)) {
|
||||||
throwError(SE_HERE, "add new contact", gerror);
|
throwError(SE_HERE, "add new contact", gerror);
|
||||||
}
|
}
|
||||||
PlainGStr newuidPtr(newuid);
|
PlainGStr newuidPtr(newuid);
|
||||||
string newrev = getRevision(newuid);
|
string newrev = getRevision(newuid);
|
||||||
return InsertItemResult(newuid, newrev, ITEM_OKAY);
|
return InsertItemResult(newuid, newrev, ITEM_OKAY);
|
||||||
} else {
|
} else {
|
||||||
if (!e_book_client_modify_contact_sync(m_addressbook, contact, NULL, gerror)) {
|
if (!e_book_client_modify_contact_sync(m_addressbook, contact,
|
||||||
|
#ifdef HAVE_E_BOOK_OPERATION_FLAGS
|
||||||
|
E_BOOK_OPERATION_FLAG_NONE,
|
||||||
|
#endif
|
||||||
|
nullptr, gerror)) {
|
||||||
throwError(SE_HERE, "updating contact "+ uid, gerror);
|
throwError(SE_HERE, "updating contact "+ uid, gerror);
|
||||||
}
|
}
|
||||||
string newrev = getRevision(uid);
|
string newrev = getRevision(uid);
|
||||||
|
@ -1058,7 +1046,7 @@ EvolutionContactSource::insertItem(const string &uid, const std::string &item, b
|
||||||
uid.empty() ? "add" : ("insert " + uid).c_str(),
|
uid.empty() ? "add" : ("insert " + uid).c_str(),
|
||||||
m_asyncOpCounter++);
|
m_asyncOpCounter++);
|
||||||
SE_LOG_DEBUG(name, "queueing for batched %s", uid.empty() ? "add" : "update");
|
SE_LOG_DEBUG(name, "queueing for batched %s", uid.empty() ? "add" : "update");
|
||||||
boost::shared_ptr<Pending> pending(new Pending);
|
auto pending = std::make_shared<Pending>();
|
||||||
pending->m_name = name;
|
pending->m_name = name;
|
||||||
pending->m_contact = contact;
|
pending->m_contact = contact;
|
||||||
pending->m_uid = uid;
|
pending->m_uid = uid;
|
||||||
|
@ -1069,7 +1057,7 @@ EvolutionContactSource::insertItem(const string &uid, const std::string &item, b
|
||||||
}
|
}
|
||||||
// SyncSource is going to live longer than Synthesis
|
// SyncSource is going to live longer than Synthesis
|
||||||
// engine, so using "this" is safe here.
|
// engine, so using "this" is safe here.
|
||||||
return InsertItemResult(boost::bind(&EvolutionContactSource::checkBatchedInsert, this, pending));
|
return InsertItemResult([this, pending] () { return checkBatchedInsert(pending); });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -1102,7 +1090,11 @@ void EvolutionContactSource::removeItem(const string &uid)
|
||||||
if (
|
if (
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
(invalidateCachedContact(uid),
|
(invalidateCachedContact(uid),
|
||||||
!e_book_client_remove_contact_by_uid_sync(m_addressbook, uid.c_str(), NULL, gerror))
|
!e_book_client_remove_contact_by_uid_sync(m_addressbook, uid.c_str(),
|
||||||
|
#ifdef HAVE_E_BOOK_OPERATION_FLAGS
|
||||||
|
E_BOOK_OPERATION_FLAG_NONE,
|
||||||
|
#endif
|
||||||
|
nullptr, gerror))
|
||||||
#else
|
#else
|
||||||
!e_book_remove_contact(m_addressbook, uid.c_str(), gerror)
|
!e_book_remove_contact(m_addressbook, uid.c_str(), gerror)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -137,7 +137,7 @@ class EvolutionContactSource : public EvolutionSyncSource,
|
||||||
|
|
||||||
Pending() : m_status(MODIFYING) {}
|
Pending() : m_status(MODIFYING) {}
|
||||||
};
|
};
|
||||||
typedef std::list< boost::shared_ptr<Pending> >PendingContainer_t;
|
typedef std::list< std::shared_ptr<Pending> >PendingContainer_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Batched "contact add/update" operations.
|
* Batched "contact add/update" operations.
|
||||||
|
@ -148,14 +148,12 @@ class EvolutionContactSource : public EvolutionSyncSource,
|
||||||
PendingContainer_t m_batchedUpdate;
|
PendingContainer_t m_batchedUpdate;
|
||||||
InitState<int> m_numRunningOperations;
|
InitState<int> m_numRunningOperations;
|
||||||
|
|
||||||
InsertItemResult checkBatchedInsert(const boost::shared_ptr<Pending> &pending);
|
InsertItemResult checkBatchedInsert(const std::shared_ptr<Pending> &pending);
|
||||||
void completedAdd(const boost::shared_ptr<PendingContainer_t> &batched, gboolean success, /* const GStringListFreeCXX &uids */ GSList *uids, const GError *gerror) throw ();
|
|
||||||
void completedUpdate(const boost::shared_ptr<PendingContainer_t> &batched, gboolean success, const GError *gerror) throw ();
|
|
||||||
virtual void flushItemChanges();
|
virtual void flushItemChanges();
|
||||||
virtual void finishItemChanges();
|
virtual void finishItemChanges();
|
||||||
|
|
||||||
// Read-ahead of item data.
|
// Read-ahead of item data.
|
||||||
boost::shared_ptr<ContactCache> m_contactCache, m_contactCacheNext;
|
std::shared_ptr<ContactCache> m_contactCache, m_contactCacheNext;
|
||||||
int m_cacheMisses, m_cacheStalls;
|
int m_cacheMisses, m_cacheStalls;
|
||||||
int m_contactReads; /**< number of readItemAsKey() calls */
|
int m_contactReads; /**< number of readItemAsKey() calls */
|
||||||
int m_contactsFromDB; /**< number of contacts requested from DB (including ones not found) */
|
int m_contactsFromDB; /**< number of contacts requested from DB (including ones not found) */
|
||||||
|
@ -164,9 +162,9 @@ class EvolutionContactSource : public EvolutionSyncSource,
|
||||||
ReadAheadOrder m_readAheadOrder;
|
ReadAheadOrder m_readAheadOrder;
|
||||||
ReadAheadItems m_nextLUIDs;
|
ReadAheadItems m_nextLUIDs;
|
||||||
|
|
||||||
void checkCacheForError(boost::shared_ptr<ContactCache> &cache);
|
void checkCacheForError(std::shared_ptr<ContactCache> &cache);
|
||||||
void invalidateCachedContact(const std::string &luid);
|
void invalidateCachedContact(const std::string &luid);
|
||||||
void invalidateCachedContact(boost::shared_ptr<ContactCache> &cache, const std::string &luid);
|
void invalidateCachedContact(std::shared_ptr<ContactCache> &cache, const std::string &luid);
|
||||||
bool getContact(const string &luid, EContact **contact, GErrorCXX &gerror);
|
bool getContact(const string &luid, EContact **contact, GErrorCXX &gerror);
|
||||||
bool getContactFromCache(const string &luid, EContact **contact, GErrorCXX &gerror);
|
bool getContactFromCache(const string &luid, EContact **contact, GErrorCXX &gerror);
|
||||||
enum ReadingMode
|
enum ReadingMode
|
||||||
|
@ -174,8 +172,7 @@ class EvolutionContactSource : public EvolutionSyncSource,
|
||||||
START, /**< luid is needed, must be read */
|
START, /**< luid is needed, must be read */
|
||||||
CONTINUE /**< luid is from old request, find next ones */
|
CONTINUE /**< luid is from old request, find next ones */
|
||||||
};
|
};
|
||||||
boost::shared_ptr<ContactCache> startReading(const std::string &luid, ReadingMode mode);
|
std::shared_ptr<ContactCache> startReading(const std::string &luid, ReadingMode mode);
|
||||||
void completedRead(const boost::weak_ptr<ContactCache> &cachePtr, gboolean success, GSList *contactsPtr, const GError *gerror) throw();
|
|
||||||
void logCacheStats(Logger::Level level);
|
void logCacheStats(Logger::Level level);
|
||||||
|
|
||||||
// Use the information provided to us to implement read-ahead efficiently.
|
// Use the information provided to us to implement read-ahead efficiently.
|
||||||
|
|
|
@ -24,12 +24,14 @@
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
|
||||||
static SyncSource *createSource(const SyncSourceParams ¶ms)
|
static std::unique_ptr<SyncSource> createSource(const SyncSourceParams ¶ms)
|
||||||
{
|
{
|
||||||
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
||||||
bool isMe = sourceType.m_backend == "Evolution Address Book";
|
bool isMe = sourceType.m_backend == "Evolution Address Book";
|
||||||
bool maybeMe = sourceType.m_backend == "addressbook";
|
bool maybeMe = sourceType.m_backend == "addressbook";
|
||||||
|
#ifdef ENABLE_EBOOK
|
||||||
const bool enabled = true;
|
const bool enabled = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
EDSAbiWrapperInit();
|
EDSAbiWrapperInit();
|
||||||
|
|
||||||
|
@ -37,18 +39,18 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
if (sourceType.m_format == "text/x-vcard") {
|
if (sourceType.m_format == "text/x-vcard") {
|
||||||
return
|
return
|
||||||
#ifdef ENABLE_EBOOK
|
#ifdef ENABLE_EBOOK
|
||||||
enabled ? new EvolutionContactSource(params, EVC_FORMAT_VCARD_21) :
|
enabled ? std::make_unique<EvolutionContactSource>(params, EVC_FORMAT_VCARD_21) :
|
||||||
#endif
|
#endif
|
||||||
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
|
isMe ? RegisterSyncSource::InactiveSource(params) : nullptr;
|
||||||
} else if (sourceType.m_format == "" || sourceType.m_format == "text/vcard") {
|
} else if (sourceType.m_format == "" || sourceType.m_format == "text/vcard") {
|
||||||
return
|
return
|
||||||
#ifdef ENABLE_EBOOK
|
#ifdef ENABLE_EBOOK
|
||||||
enabled ? new EvolutionContactSource(params, EVC_FORMAT_VCARD_30) :
|
enabled ? std::make_unique<EvolutionContactSource>(params, EVC_FORMAT_VCARD_30) :
|
||||||
#endif
|
#endif
|
||||||
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
|
isMe ? RegisterSyncSource::InactiveSource(params) : nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterSyncSource registerMe("Evolution Address Book",
|
static RegisterSyncSource registerMe("Evolution Address Book",
|
||||||
|
@ -77,13 +79,13 @@ class EvolutionContactTest : public CppUnit::TestFixture {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void testInstantiate() {
|
void testInstantiate() {
|
||||||
boost::shared_ptr<SyncSource> source;
|
std::unique_ptr<SyncSource> source;
|
||||||
source.reset(SyncSource::createTestingSource("addressbook", "addressbook", true));
|
source = SyncSource::createTestingSource("addressbook", "addressbook", true);
|
||||||
source.reset(SyncSource::createTestingSource("addressbook", "contacts", true));
|
source = SyncSource::createTestingSource("addressbook", "contacts", true);
|
||||||
source.reset(SyncSource::createTestingSource("addressbook", "evolution-contacts", true));
|
source = SyncSource::createTestingSource("addressbook", "evolution-contacts", true);
|
||||||
source.reset(SyncSource::createTestingSource("addressbook", "Evolution Contacts", true));
|
source = SyncSource::createTestingSource("addressbook", "Evolution Contacts", true);
|
||||||
source.reset(SyncSource::createTestingSource("addressbook", "Evolution Address Book:text/x-vcard", true));
|
source = SyncSource::createTestingSource("addressbook", "Evolution Address Book:text/x-vcard", true);
|
||||||
source.reset(SyncSource::createTestingSource("addressbook", "Evolution Address Book:text/vcard", true));
|
source = SyncSource::createTestingSource("addressbook", "Evolution Address Book:text/vcard", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,47 +95,8 @@ protected:
|
||||||
*/
|
*/
|
||||||
void testImport() {
|
void testImport() {
|
||||||
// this only tests that we can instantiate something under the type "addressbook";
|
// this only tests that we can instantiate something under the type "addressbook";
|
||||||
// it might not be an EvolutionContactSource
|
auto source21 = SyncSource::createTestingSource("evolutioncontactsource21", "evolution-contacts:text/x-vcard", true);
|
||||||
boost::shared_ptr<EvolutionContactSource> source21(dynamic_cast<EvolutionContactSource *>(SyncSource::createTestingSource("evolutioncontactsource21", "evolution-contacts:text/x-vcard", true)));
|
auto source30 = SyncSource::createTestingSource("evolutioncontactsource30", "Evolution Address Book:text/vcard", true);
|
||||||
boost::shared_ptr<EvolutionContactSource> source30(dynamic_cast<EvolutionContactSource *>(SyncSource::createTestingSource("evolutioncontactsource30", "Evolution Address Book:text/vcard", true)));
|
|
||||||
string parsed;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// TODO: enable testing of incoming items again. Right now preparse() doesn't
|
|
||||||
// do anything and needs to be replaced with Synthesis mechanisms.
|
|
||||||
|
|
||||||
// SF bug 1796086: sync with EGW: lost or messed up telephones
|
|
||||||
parsed = "BEGIN:VCARD\r\nVERSION:3.0\r\nTEL;CELL:cell\r\nEND:VCARD\r\n";
|
|
||||||
CPPUNIT_ASSERT_EQUAL(parsed,
|
|
||||||
preparse(*source21,
|
|
||||||
"BEGIN:VCARD\nVERSION:2.1\nTEL;CELL:cell\nEND:VCARD\n",
|
|
||||||
"text/x-vcard"));
|
|
||||||
|
|
||||||
parsed = "BEGIN:VCARD\r\nVERSION:3.0\r\nTEL;TYPE=CAR:car\r\nEND:VCARD\r\n";
|
|
||||||
CPPUNIT_ASSERT_EQUAL(parsed,
|
|
||||||
preparse(*source21,
|
|
||||||
"BEGIN:VCARD\nVERSION:2.1\nTEL;TYPE=CAR:car\nEND:VCARD\n",
|
|
||||||
"text/x-vcard"));
|
|
||||||
|
|
||||||
parsed = "BEGIN:VCARD\r\nVERSION:3.0\r\nTEL;TYPE=HOME:home\r\nEND:VCARD\r\n";
|
|
||||||
CPPUNIT_ASSERT_EQUAL(parsed,
|
|
||||||
preparse(*source21,
|
|
||||||
"BEGIN:VCARD\nVERSION:2.1\nTEL:home\nEND:VCARD\n",
|
|
||||||
"text/x-vcard"));
|
|
||||||
|
|
||||||
// TYPE=PARCEL not supported by Evolution, used to represent Evolutions TYPE=OTHER
|
|
||||||
parsed = "BEGIN:VCARD\r\nVERSION:3.0\r\nTEL;TYPE=OTHER:other\r\nEND:VCARD\r\n";
|
|
||||||
CPPUNIT_ASSERT_EQUAL(parsed,
|
|
||||||
preparse(*source21,
|
|
||||||
"BEGIN:VCARD\nVERSION:2.1\nTEL;TYPE=PARCEL:other\nEND:VCARD\n",
|
|
||||||
"text/x-vcard"));
|
|
||||||
|
|
||||||
parsed = "BEGIN:VCARD\r\nVERSION:3.0\r\nTEL;TYPE=HOME;TYPE=VOICE:cell\r\nEND:VCARD\r\n";
|
|
||||||
CPPUNIT_ASSERT_EQUAL(parsed,
|
|
||||||
preparse(*source21,
|
|
||||||
"BEGIN:VCARD\nVERSION:2.1\nTEL;TYPE=HOME,VOICE:cell\nEND:VCARD\n",
|
|
||||||
"text/x-vcard"));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,9 @@ void EvolutionSyncSource::getDatabasesFromRegistry(SyncSource::Databases &result
|
||||||
{
|
{
|
||||||
ESourceRegistryCXX registry = EDSRegistryLoader::getESourceRegistry();
|
ESourceRegistryCXX registry = EDSRegistryLoader::getESourceRegistry();
|
||||||
ESourceListCXX sources(e_source_registry_list_sources(registry, extension));
|
ESourceListCXX sources(e_source_registry_list_sources(registry, extension));
|
||||||
ESourceCXX def(refDef ? refDef(registry) : NULL,
|
ESourceCXX def(refDef ? refDef(registry) : nullptr,
|
||||||
TRANSFER_REF);
|
TRANSFER_REF);
|
||||||
BOOST_FOREACH (ESource *source, sources) {
|
for (ESource *source: sources) {
|
||||||
result.push_back(Database(e_source_get_display_name(source),
|
result.push_back(Database(e_source_get_display_name(source),
|
||||||
e_source_get_uid(source),
|
e_source_get_uid(source),
|
||||||
e_source_equal(def, source)));
|
e_source_equal(def, source)));
|
||||||
|
@ -58,7 +58,7 @@ static void handleErrorCB(EClient */*client*/, const gchar *error_msg, gpointer
|
||||||
|
|
||||||
EClientCXX EvolutionSyncSource::openESource(const char *extension,
|
EClientCXX EvolutionSyncSource::openESource(const char *extension,
|
||||||
ESource *(*refBuiltin)(ESourceRegistry *),
|
ESource *(*refBuiltin)(ESourceRegistry *),
|
||||||
const boost::function<EClient *(ESource *, GError **gerror)> &newClient)
|
const std::function<EClient *(ESource *, GError **gerror)> &newClient)
|
||||||
{
|
{
|
||||||
EClientCXX client;
|
EClientCXX client;
|
||||||
GErrorCXX gerror;
|
GErrorCXX gerror;
|
||||||
|
@ -66,7 +66,6 @@ EClientCXX EvolutionSyncSource::openESource(const char *extension,
|
||||||
ESourceListCXX sources(e_source_registry_list_sources(registry, extension));
|
ESourceListCXX sources(e_source_registry_list_sources(registry, extension));
|
||||||
string id = getDatabaseID();
|
string id = getDatabaseID();
|
||||||
ESource *source = findSource(sources, id);
|
ESource *source = findSource(sources, id);
|
||||||
bool created = false;
|
|
||||||
|
|
||||||
if (!source) {
|
if (!source) {
|
||||||
if (refBuiltin && (id.empty() || id == "<<system>>")) {
|
if (refBuiltin && (id.empty() || id == "<<system>>")) {
|
||||||
|
@ -78,7 +77,6 @@ EClientCXX EvolutionSyncSource::openESource(const char *extension,
|
||||||
} else {
|
} else {
|
||||||
throwError(SE_HERE, string("database not found: '") + id + "'");
|
throwError(SE_HERE, string("database not found: '") + id + "'");
|
||||||
}
|
}
|
||||||
created = true;
|
|
||||||
} else {
|
} else {
|
||||||
client = EClientCXX::steal(newClient(source, gerror));
|
client = EClientCXX::steal(newClient(source, gerror));
|
||||||
}
|
}
|
||||||
|
@ -95,19 +93,19 @@ EClientCXX EvolutionSyncSource::openESource(const char *extension,
|
||||||
(void *)"Evolution Data Server has died unexpectedly.");
|
(void *)"Evolution Data Server has died unexpectedly.");
|
||||||
|
|
||||||
|
|
||||||
|
int retries = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
// Always allow EDS to create the database. "only-if-exists =
|
// Always allow EDS to create the database. "only-if-exists =
|
||||||
// true" does not make sense.
|
// true" does not make sense.
|
||||||
if (!e_client_open_sync(client, false, NULL, gerror)) {
|
if (!e_client_open_sync(client, false, nullptr, gerror)) {
|
||||||
if (gerror && g_error_matches(gerror, E_CLIENT_ERROR, E_CLIENT_ERROR_BUSY)) {
|
if (retries < 5) {
|
||||||
|
// EDS 3.18 and 3.26 have various race conditions during startup.
|
||||||
|
// Try a few times.
|
||||||
|
// https://bugzilla.gnome.org/show_bug.cgi?id=791306
|
||||||
|
SE_LOG_DEBUG(NULL, "Opening EDS source: ignoring error, trying again: %s", gerror->message);
|
||||||
gerror.clear();
|
gerror.clear();
|
||||||
sleep(1);
|
sleep(1);
|
||||||
} else if (created) {
|
retries++;
|
||||||
// Opening newly created address books often failed in
|
|
||||||
// old EDS releases - try again. Probably covered by
|
|
||||||
// more recently added E_CLIENT_ERROR_BUSY check above.
|
|
||||||
gerror.clear();
|
|
||||||
sleep(5);
|
|
||||||
} else {
|
} else {
|
||||||
throwError(SE_HERE, "opening database", gerror);
|
throwError(SE_HERE, "opening database", gerror);
|
||||||
}
|
}
|
||||||
|
@ -155,7 +153,7 @@ SyncSource::Database EvolutionSyncSource::createDatabase(const Database &databas
|
||||||
if (!g_key_file_load_from_data(keyfile, ini, len, G_KEY_FILE_NONE, gerror)) {
|
if (!g_key_file_load_from_data(keyfile, ini, len, G_KEY_FILE_NONE, gerror)) {
|
||||||
gerror.throwError(SE_HERE, "parsing ESource .ini data");
|
gerror.throwError(SE_HERE, "parsing ESource .ini data");
|
||||||
}
|
}
|
||||||
PlainGStrArray keys(g_key_file_get_keys(keyfile, mainSection, NULL, gerror));
|
PlainGStrArray keys(g_key_file_get_keys(keyfile, mainSection, nullptr, gerror));
|
||||||
if (!keys) {
|
if (!keys) {
|
||||||
gerror.throwError(SE_HERE, "listing keys in main section");
|
gerror.throwError(SE_HERE, "listing keys in main section");
|
||||||
}
|
}
|
||||||
|
@ -168,7 +166,7 @@ SyncSource::Database EvolutionSyncSource::createDatabase(const Database &databas
|
||||||
}
|
}
|
||||||
g_key_file_set_string(keyfile, mainSection, "DisplayName", database.m_name.c_str());
|
g_key_file_set_string(keyfile, mainSection, "DisplayName", database.m_name.c_str());
|
||||||
g_key_file_set_boolean(keyfile, mainSection, "Enabled", true);
|
g_key_file_set_boolean(keyfile, mainSection, "Enabled", true);
|
||||||
ini = g_key_file_to_data(keyfile, &len, NULL);
|
ini = g_key_file_to_data(keyfile, &len, nullptr);
|
||||||
const char *configDir = g_get_user_config_dir();
|
const char *configDir = g_get_user_config_dir();
|
||||||
int fd;
|
int fd;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
|
@ -213,7 +211,7 @@ SyncSource::Database EvolutionSyncSource::createDatabase(const Database &databas
|
||||||
while (!ESourceCXX(e_source_registry_ref_source(registry, uid.c_str()), TRANSFER_REF)) {
|
while (!ESourceCXX(e_source_registry_ref_source(registry, uid.c_str()), TRANSFER_REF)) {
|
||||||
// This will block forever if called from the non-main-thread.
|
// This will block forever if called from the non-main-thread.
|
||||||
// Don't do that...
|
// Don't do that...
|
||||||
g_main_context_iteration(NULL, true);
|
g_main_context_iteration(nullptr, true);
|
||||||
}
|
}
|
||||||
SE_LOG_DEBUG(getDisplayName(), "ESourceRegistry has new ESource %s", uid.c_str());
|
SE_LOG_DEBUG(getDisplayName(), "ESourceRegistry has new ESource %s", uid.c_str());
|
||||||
|
|
||||||
|
@ -221,7 +219,7 @@ SyncSource::Database EvolutionSyncSource::createDatabase(const Database &databas
|
||||||
// UUID. Does not work! evolution-source-registry simply overwrites the
|
// UUID. Does not work! evolution-source-registry simply overwrites the
|
||||||
// file that we created earlier.
|
// file that we created earlier.
|
||||||
// ESourceCXX source(e_source_new_with_uid(uid.c_str(),
|
// ESourceCXX source(e_source_new_with_uid(uid.c_str(),
|
||||||
// NULL, gerror),
|
// nullptr, gerror),
|
||||||
// TRANSFER_REF);
|
// TRANSFER_REF);
|
||||||
// e_source_set_display_name(source, "syncevolution-fake");
|
// e_source_set_display_name(source, "syncevolution-fake");
|
||||||
// e_source_set_parent(source, "local-stub");
|
// e_source_set_parent(source, "local-stub");
|
||||||
|
@ -229,7 +227,7 @@ SyncSource::Database EvolutionSyncSource::createDatabase(const Database &databas
|
||||||
// sources.push_back(source.ref()); // ESourceListCXX unrefs sources it points to
|
// sources.push_back(source.ref()); // ESourceListCXX unrefs sources it points to
|
||||||
// if (!e_source_registry_create_sources_sync(registry,
|
// if (!e_source_registry_create_sources_sync(registry,
|
||||||
// sources,
|
// sources,
|
||||||
// NULL,
|
// nullptr,
|
||||||
// gerror)) {
|
// gerror)) {
|
||||||
// gerror.throwError(SE_HERE, StringPrintf("creating EDS database of type %s with name '%s'%s%s",
|
// gerror.throwError(SE_HERE, StringPrintf("creating EDS database of type %s with name '%s'%s%s",
|
||||||
// sourceExtension(),
|
// sourceExtension(),
|
||||||
|
@ -252,7 +250,7 @@ void EvolutionSyncSource::deleteDatabase(const std::string &uri, RemoveData remo
|
||||||
uri.c_str()));
|
uri.c_str()));
|
||||||
}
|
}
|
||||||
GErrorCXX gerror;
|
GErrorCXX gerror;
|
||||||
if (!e_source_remove_sync(source, NULL, gerror)) {
|
if (!e_source_remove_sync(source, nullptr, gerror)) {
|
||||||
throwError(SE_HERE, StringPrintf("deleting EDS database with URI '%s'", uri.c_str()),
|
throwError(SE_HERE, StringPrintf("deleting EDS database with URI '%s'", uri.c_str()),
|
||||||
gerror);
|
gerror);
|
||||||
}
|
}
|
||||||
|
@ -266,10 +264,10 @@ void EvolutionSyncSource::deleteDatabase(const std::string &uri, RemoveData remo
|
||||||
// This is equivalent to "rm -rf $XDG_DATA_HOME/evolution/*/<uuid>".
|
// This is equivalent to "rm -rf $XDG_DATA_HOME/evolution/*/<uuid>".
|
||||||
std::string basedir = StringPrintf("%s/evolution", g_get_user_data_dir());
|
std::string basedir = StringPrintf("%s/evolution", g_get_user_data_dir());
|
||||||
if (isDir(basedir)) {
|
if (isDir(basedir)) {
|
||||||
BOOST_FOREACH (const std::string &kind, ReadDir(basedir)) {
|
for (const std::string &kind: ReadDir(basedir)) {
|
||||||
std::string subdir = basedir + "/" + kind;
|
std::string subdir = basedir + "/" + kind;
|
||||||
if (isDir(subdir)) {
|
if (isDir(subdir)) {
|
||||||
BOOST_FOREACH (const std::string &source, ReadDir(subdir)) {
|
for (const std::string &source: ReadDir(subdir)) {
|
||||||
// We assume that the UUID of the database
|
// We assume that the UUID of the database
|
||||||
// consists only of characters which can be
|
// consists only of characters which can be
|
||||||
// used in the directory name, i.e., no
|
// used in the directory name, i.e., no
|
||||||
|
@ -296,7 +294,7 @@ ESource *EvolutionSyncSource::findSource(const ESourceListCXX &list, const strin
|
||||||
finalID = id;
|
finalID = id;
|
||||||
} else {
|
} else {
|
||||||
// Nothing selected specifically, use the one marked as default.
|
// Nothing selected specifically, use the one marked as default.
|
||||||
BOOST_FOREACH(const Database &db, getDatabases()) {
|
for (const Database &db: getDatabases()) {
|
||||||
if (db.m_isDefault) {
|
if (db.m_isDefault) {
|
||||||
finalID = db.m_uri;
|
finalID = db.m_uri;
|
||||||
break;
|
break;
|
||||||
|
@ -305,7 +303,7 @@ ESource *EvolutionSyncSource::findSource(const ESourceListCXX &list, const strin
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_EDS_CLIENT
|
#ifdef USE_EDS_CLIENT
|
||||||
BOOST_FOREACH (ESource *source, list) {
|
for (ESource *source: list) {
|
||||||
bool found =
|
bool found =
|
||||||
!finalID.compare(e_source_get_display_name(source)) ||
|
!finalID.compare(e_source_get_display_name(source)) ||
|
||||||
!finalID.compare(e_source_get_uid(source));
|
!finalID.compare(e_source_get_uid(source));
|
||||||
|
@ -329,7 +327,7 @@ ESource *EvolutionSyncSource::findSource(const ESourceListCXX &list, const strin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvolutionSyncSource::throwError(const SourceLocation &where, const string &action, GErrorCXX &gerror)
|
void EvolutionSyncSource::throwError(const SourceLocation &where, const string &action, GErrorCXX &gerror)
|
||||||
|
|
|
@ -71,7 +71,7 @@ class EvolutionSyncSource : public TrackingSyncSource
|
||||||
ESource *(*getDef)(ESourceRegistry *));
|
ESource *(*getDef)(ESourceRegistry *));
|
||||||
EClientCXX openESource(const char *extension,
|
EClientCXX openESource(const char *extension,
|
||||||
ESource *(*refBuiltin)(ESourceRegistry *),
|
ESource *(*refBuiltin)(ESourceRegistry *),
|
||||||
const boost::function<EClient *(ESource *, GError **gerror)> &newClient);
|
const std::function<EClient *(ESource *, GError **gerror)> &newClient);
|
||||||
|
|
||||||
// Implementation of SyncSource calls which only works when using EDS Client API
|
// Implementation of SyncSource calls which only works when using EDS Client API
|
||||||
// and EDS > 3.4. Older EDS has no way of creating sources easily (or at all).
|
// and EDS > 3.4. Older EDS has no way of creating sources easily (or at all).
|
||||||
|
@ -90,7 +90,7 @@ class EvolutionSyncSource : public TrackingSyncSource
|
||||||
*
|
*
|
||||||
* @param list a list previously obtained from Gnome
|
* @param list a list previously obtained from Gnome
|
||||||
* @param id a string identifying the data source: either its name or uri
|
* @param id a string identifying the data source: either its name or uri
|
||||||
* @return pointer to source (caller owns reference) or NULL if not found
|
* @return pointer to source (caller owns reference) or nullptr if not found
|
||||||
*/
|
*/
|
||||||
ESource *findSource(const ESourceListCXX &list,
|
ESource *findSource(const ESourceListCXX &list,
|
||||||
const string &id);
|
const string &id);
|
||||||
|
@ -124,7 +124,7 @@ class EvolutionAsync {
|
||||||
public:
|
public:
|
||||||
EvolutionAsync()
|
EvolutionAsync()
|
||||||
{
|
{
|
||||||
m_loop = GMainLoopStealCXX(g_main_loop_new(NULL, TRUE));
|
m_loop = GMainLoopStealCXX(g_main_loop_new(nullptr, TRUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** start processing events */
|
/** start processing events */
|
||||||
|
|
|
@ -15,13 +15,23 @@ $anymissing"
|
||||||
|
|
||||||
dnl check for Evolution packages
|
dnl check for Evolution packages
|
||||||
PKG_CHECK_MODULES(EPACKAGE, libedataserver-1.2, EDSFOUND=yes, [EDSFOUND=no])
|
PKG_CHECK_MODULES(EPACKAGE, libedataserver-1.2, EDSFOUND=yes, [EDSFOUND=no])
|
||||||
PKG_CHECK_MODULES(ECAL, libecal-1.2, ECALFOUND=yes, [ECALFOUND=no])
|
PKG_CHECK_MODULES(ECAL, libecal-2.0, ECALFOUND=yes, [ECALFOUND=no])
|
||||||
PKG_CHECK_MODULES(EBOOK, libebook-1.2, EBOOKFOUND=yes, [EBOOKFOUND=no])
|
PKG_CHECK_MODULES(EBOOK, libebook-1.2, EBOOKFOUND=yes, [EBOOKFOUND=no])
|
||||||
|
|
||||||
|
if test "$ECALFOUND" = "yes"; then
|
||||||
|
AC_DEFINE(HAVE_LIBECAL_2_0, 1, [libecal 2.0])
|
||||||
|
else
|
||||||
|
PKG_CHECK_MODULES(ECAL, libecal-1.2, ECALFOUND=yes, [ECALFOUND=no])
|
||||||
|
fi
|
||||||
|
|
||||||
PKG_CHECK_MODULES(EBOOK_VERSION, [libebook-1.2 >= 3.3],
|
PKG_CHECK_MODULES(EBOOK_VERSION, [libebook-1.2 >= 3.3],
|
||||||
[AC_DEFINE(HAVE_E_CONTACT_INLINE_LOCAL_PHOTOS, 1, [have e_contact_inline_local_photos()])],
|
[AC_DEFINE(HAVE_E_CONTACT_INLINE_LOCAL_PHOTOS, 1, [have e_contact_inline_local_photos()])],
|
||||||
[true])
|
[true])
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(EBOOK_VERSION_3_33, [libebook-1.2 >= 3.33.2],
|
||||||
|
[AC_DEFINE(HAVE_E_BOOK_OPERATION_FLAGS, 1, [have EBookOperationFlags])],
|
||||||
|
[true])
|
||||||
|
|
||||||
SE_ARG_ENABLE_BACKEND(ebook, evolution,
|
SE_ARG_ENABLE_BACKEND(ebook, evolution,
|
||||||
[AS_HELP_STRING([--disable-ebook],
|
[AS_HELP_STRING([--disable-ebook],
|
||||||
[disable access to Evolution addressbooks (must be used to compile without it)])],
|
[disable access to Evolution addressbooks (must be used to compile without it)])],
|
||||||
|
|
|
@ -414,7 +414,11 @@ gboolean e_cal_check_timezones(icalcomponent *comp,
|
||||||
goto done;
|
goto done;
|
||||||
nomem:
|
nomem:
|
||||||
/* set gerror for "out of memory" if possible, otherwise abort via g_error() */
|
/* set gerror for "out of memory" if possible, otherwise abort via g_error() */
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
*error = g_error_new(E_CLIENT_ERROR, E_CLIENT_ERROR_OTHER_ERROR, "out of memory");
|
||||||
|
#else
|
||||||
*error = g_error_new(E_CALENDAR_ERROR, E_CALENDAR_STATUS_OTHER_ERROR, "out of memory");
|
*error = g_error_new(E_CALENDAR_ERROR, E_CALENDAR_STATUS_OTHER_ERROR, "out of memory");
|
||||||
|
#endif
|
||||||
if (!*error) {
|
if (!*error) {
|
||||||
g_error("e_cal_check_timezones(): out of memory, cannot proceed - sorry!");
|
g_error("e_cal_check_timezones(): out of memory, cannot proceed - sorry!");
|
||||||
}
|
}
|
||||||
|
@ -451,6 +455,10 @@ icaltimezone *e_cal_tzlookup_ecal(const char *tzid,
|
||||||
const void *custom,
|
const void *custom,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_LIBECAL_2_0
|
||||||
|
g_propagate_error(error, e_client_error_create(E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
ECal *ecal = (ECal *)custom;
|
ECal *ecal = (ECal *)custom;
|
||||||
icaltimezone *zone = NULL;
|
icaltimezone *zone = NULL;
|
||||||
|
|
||||||
|
@ -470,6 +478,7 @@ icaltimezone *e_cal_tzlookup_ecal(const char *tzid,
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -137,7 +137,7 @@ void FileSyncSource::open()
|
||||||
|
|
||||||
bool FileSyncSource::isEmpty()
|
bool FileSyncSource::isEmpty()
|
||||||
{
|
{
|
||||||
DIR *dir = NULL;
|
DIR *dir = nullptr;
|
||||||
bool empty = true;
|
bool empty = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -197,7 +197,7 @@ void FileSyncSource::listAllItems(RevisionMap_t &revisions)
|
||||||
SE_LOG_DEBUG(getDisplayName(), "continue listing items in file source");
|
SE_LOG_DEBUG(getDisplayName(), "continue listing items in file source");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(const string &entry, dirContent) {
|
for (const string &entry: dirContent) {
|
||||||
string filename = createFilename(entry);
|
string filename = createFilename(entry);
|
||||||
string revision = getATimeString(filename);
|
string revision = getATimeString(filename);
|
||||||
long entrynum = atoll(entry.c_str());
|
long entrynum = atoll(entry.c_str());
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
|
||||||
static SyncSource *createSource(const SyncSourceParams ¶ms)
|
static std::unique_ptr<SyncSource> createSource(const SyncSourceParams ¶ms)
|
||||||
{
|
{
|
||||||
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
||||||
// The string returned by getSourceType() is always the one
|
// The string returned by getSourceType() is always the one
|
||||||
|
@ -34,7 +34,7 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
#ifndef ENABLE_FILE
|
#ifndef ENABLE_FILE
|
||||||
// tell SyncEvolution if the user wanted to use a disabled sync source,
|
// tell SyncEvolution if the user wanted to use a disabled sync source,
|
||||||
// otherwise let it continue searching
|
// otherwise let it continue searching
|
||||||
return isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
|
return isMe ? RegisterSyncSource::InactiveSource(params) : nullptr;
|
||||||
#else
|
#else
|
||||||
// Also recognize one of the standard types?
|
// Also recognize one of the standard types?
|
||||||
// Not in the FileSyncSource!
|
// Not in the FileSyncSource!
|
||||||
|
@ -43,12 +43,12 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
if (isMe || maybeMe) {
|
if (isMe || maybeMe) {
|
||||||
// The FileSyncSource always needs the database format.
|
// The FileSyncSource always needs the database format.
|
||||||
if (!sourceType.m_localFormat.empty()) {
|
if (!sourceType.m_localFormat.empty()) {
|
||||||
return new FileSyncSource(params, sourceType.m_localFormat);
|
return std::make_unique<FileSyncSource>(params, sourceType.m_localFormat);
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,10 +88,10 @@ class FileSyncSourceUnitTest : public CppUnit::TestFixture {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void testInstantiate() {
|
void testInstantiate() {
|
||||||
boost::shared_ptr<SyncSource> source;
|
std::unique_ptr<SyncSource> source;
|
||||||
source.reset(SyncSource::createTestingSource("file", "file:text/vcard:3.0", true));
|
source = SyncSource::createTestingSource("file", "file:text/vcard:3.0", true);
|
||||||
source.reset(SyncSource::createTestingSource("file", "file:text/plain:1.0", true));
|
source = SyncSource::createTestingSource("file", "file:text/plain:1.0", true);
|
||||||
source.reset(SyncSource::createTestingSource("file", "Files in one directory:text/x-vcard:2.1", true));
|
source = SyncSource::createTestingSource("file", "Files in one directory:text/x-vcard:2.1", true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,63 +21,26 @@
|
||||||
|
|
||||||
#ifdef USE_GNOME_KEYRING
|
#ifdef USE_GNOME_KEYRING
|
||||||
|
|
||||||
extern "C" {
|
#include <libsecret/secret.h>
|
||||||
#include <gnome-keyring.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "GNOMEPlatform.h"
|
#include "GNOMEPlatform.h"
|
||||||
|
|
||||||
#include <syncevo/Exception.h>
|
#include <syncevo/Exception.h>
|
||||||
#include <syncevo/UserInterface.h>
|
#include <syncevo/UserInterface.h>
|
||||||
#include <syncevo/SyncConfig.h>
|
#include <syncevo/SyncConfig.h>
|
||||||
|
#include <syncevo/GLibSupport.h>
|
||||||
|
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
|
||||||
// Occasionally, libgnome-keyring fails with the following error messages:
|
|
||||||
// Gkr: received an invalid, unencryptable, or non-utf8 secret
|
|
||||||
// Gkr: call to daemon returned an invalid response: (null).(null)
|
|
||||||
//
|
|
||||||
// We work around that by retrying the operation a few times, for at
|
|
||||||
// most this period of time. Didn't really help, so disable it for now
|
|
||||||
// by using a zero duration.
|
|
||||||
static const double GNOMEKeyringRetryDuration = 2; // seconds
|
|
||||||
static const double GNOMEKeyringRetryInterval = 0.1; // seconds
|
|
||||||
|
|
||||||
/**
|
|
||||||
* libgnome-keyring has an internal gkr_reset_session()
|
|
||||||
* method which gets called when the "org.freedesktop.secrets"
|
|
||||||
* disconnects from the D-Bus session bus.
|
|
||||||
*
|
|
||||||
* We cannot call that method directly, but we can get it called by
|
|
||||||
* faking the "disconnect" signal. That works because
|
|
||||||
* on_connection_filter() in gkr-operation.c doesn't check who the
|
|
||||||
* sender of the signal is.
|
|
||||||
*
|
|
||||||
* Once gkr_reset_session() got called, the next operation will
|
|
||||||
* re-establish the connection. After the failure above, the second
|
|
||||||
* attempt usually works.
|
|
||||||
*
|
|
||||||
* Any other client using libgnome-keyring will also be tricked into
|
|
||||||
* disconnecting temporarily. That should be fine, any running
|
|
||||||
* operation will continue to run and complete (?).
|
|
||||||
*/
|
|
||||||
static void FlushGNOMEKeyring()
|
|
||||||
{
|
|
||||||
// Invoking dbus-send is easier than writing this in C++.
|
|
||||||
// Besides, it ensures that the signal comes from some other
|
|
||||||
// process. Not sure whether signals are sent back to the sender.
|
|
||||||
system("dbus-send --session --type=signal /org/freedesktop/DBus org.freedesktop.DBus.NameOwnerChanged string:'org.freedesktop.secrets' string:':9.99' string:''");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GNOME keyring distinguishes between empty and unset
|
* GNOME keyring distinguishes between empty and unset
|
||||||
* password keys. This function returns NULL for an
|
* password keys. This function returns nullptr for an
|
||||||
* empty std::string.
|
* empty std::string.
|
||||||
*/
|
*/
|
||||||
inline const char *passwdStr(const std::string &str)
|
inline const char *passwdStr(const std::string &str)
|
||||||
{
|
{
|
||||||
return str.empty() ? NULL : str.c_str();
|
return str.empty() ? nullptr : str.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool UseGNOMEKeyring(const InitStateTri &keyring)
|
static bool UseGNOMEKeyring(const InitStateTri &keyring)
|
||||||
|
@ -97,6 +60,56 @@ static bool UseGNOMEKeyring(const InitStateTri &keyring)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LibSecretHash : public GHashTableCXX
|
||||||
|
{
|
||||||
|
std::list<std::string> m_buffer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LibSecretHash(const ConfigPasswordKey &key) :
|
||||||
|
GHashTableCXX(g_hash_table_new(g_str_hash, g_str_equal), TRANSFER_REF)
|
||||||
|
{
|
||||||
|
// see https://developer.gnome.org/libsecret/0.16/libsecret-SecretSchema.html#SECRET-SCHEMA-COMPAT-NETWORK:CAPS
|
||||||
|
insert("user", key.user);
|
||||||
|
insert("domain", key.domain);
|
||||||
|
insert("server", key.server);
|
||||||
|
insert("object", key.object);
|
||||||
|
insert("protocol", key.protocol);
|
||||||
|
insert("authtype", key.authtype);
|
||||||
|
if (key.port) {
|
||||||
|
std::string value = StringPrintf("%d", key.port);
|
||||||
|
insert("port", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Keys are expected to be constants and not copied. Values are copied. */
|
||||||
|
void insert(const char *key, const std::string &value)
|
||||||
|
{
|
||||||
|
if (!value.empty()) {
|
||||||
|
m_buffer.push_back(value);
|
||||||
|
g_hash_table_insert(get(),
|
||||||
|
const_cast<char *>(key),
|
||||||
|
const_cast<char *>(m_buffer.back().c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sometimes libsecret and GNOME Keyring fail to initialize
|
||||||
|
* the encryption: https://bugzilla.gnome.org/show_bug.cgi?id=778357
|
||||||
|
* If that happens, then trying with a new SecretService instance
|
||||||
|
* may work.
|
||||||
|
*
|
||||||
|
* When libsecret detects that, we get a well-defined error.
|
||||||
|
* When GNOME Keyring detects it, the error is less obvious.
|
||||||
|
*/
|
||||||
|
static bool IsSharedSecretError(const GErrorCXX &gerror)
|
||||||
|
{
|
||||||
|
bool result = gerror.matches(SECRET_ERROR, SECRET_ERROR_PROTOCOL) /* = "received an invalid or unencryptable secret" */ ||
|
||||||
|
strstr(gerror->message, "The secret was transferred or encrypted in an invalid way");
|
||||||
|
SE_LOG_DEBUG(NULL, "IsSharedSecretError: %d/%d/%s: %s", (int)gerror->domain, (int)gerror->code, gerror->message, result ? "yes" : "no");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool GNOMELoadPasswordSlot(const InitStateTri &keyring,
|
bool GNOMELoadPasswordSlot(const InitStateTri &keyring,
|
||||||
const std::string &passwordName,
|
const std::string &passwordName,
|
||||||
const std::string &descr,
|
const std::string &descr,
|
||||||
|
@ -108,46 +121,49 @@ bool GNOMELoadPasswordSlot(const InitStateTri &keyring,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GnomeKeyringResult result = GNOME_KEYRING_RESULT_OK;
|
LibSecretHash hash(key);
|
||||||
GList* list;
|
for (int i = 0; ; i++ ) {
|
||||||
Timespec start = Timespec::monotonic();
|
GErrorCXX gerror;
|
||||||
double sleepSecs = 0;
|
PlainGStr result(secret_password_lookupv_sync(SECRET_SCHEMA_COMPAT_NETWORK,
|
||||||
do {
|
hash,
|
||||||
if (sleepSecs != 0) {
|
nullptr,
|
||||||
SE_LOG_DEBUG(NULL, "%s: previous attempt to load password '%s' from GNOME keyring failed, will try again: %s",
|
gerror));
|
||||||
key.description.c_str(),
|
|
||||||
key.toString().c_str(),
|
|
||||||
gnome_keyring_result_to_message(result));
|
|
||||||
FlushGNOMEKeyring();
|
|
||||||
Sleep(sleepSecs);
|
|
||||||
}
|
|
||||||
result = gnome_keyring_find_network_password_sync(passwdStr(key.user),
|
|
||||||
passwdStr(key.domain),
|
|
||||||
passwdStr(key.server),
|
|
||||||
passwdStr(key.object),
|
|
||||||
passwdStr(key.protocol),
|
|
||||||
passwdStr(key.authtype),
|
|
||||||
key.port,
|
|
||||||
&list);
|
|
||||||
sleepSecs = GNOMEKeyringRetryInterval;
|
|
||||||
} while (result != GNOME_KEYRING_RESULT_OK &&
|
|
||||||
(Timespec::monotonic() - start).duration() < GNOMEKeyringRetryDuration);
|
|
||||||
|
|
||||||
// if find password stored in gnome keyring
|
// if find password stored in gnome keyring
|
||||||
if(result == GNOME_KEYRING_RESULT_OK && list && list->data ) {
|
if (gerror) {
|
||||||
GnomeKeyringNetworkPasswordData *key_data;
|
/* It is uncertain whether we end up here at all when such
|
||||||
key_data = (GnomeKeyringNetworkPasswordData*)list->data;
|
an error occurs. Check just in case. */
|
||||||
password = std::string(key_data->password);
|
if (IsSharedSecretError(gerror) &&
|
||||||
gnome_keyring_network_password_list_free(list);
|
i < 3) {
|
||||||
SE_LOG_DEBUG(NULL, "%s: loaded password from GNOME keyring using %s",
|
SE_LOG_DEBUG(NULL, "disconnecting secret service: %u/%d = %s", gerror->domain, gerror->code, gerror->message);
|
||||||
key.description.c_str(),
|
secret_service_disconnect();
|
||||||
key.toString().c_str());
|
} else {
|
||||||
} else {
|
gerror.throwError(SE_HERE, StringPrintf("looking up password '%s'", descr.c_str()));
|
||||||
SE_LOG_DEBUG(NULL, "password not in GNOME keyring using %s: %s",
|
}
|
||||||
key.toString().c_str(),
|
} else if (result.get()) {
|
||||||
result == GNOME_KEYRING_RESULT_NO_MATCH ? "no match" :
|
SE_LOG_DEBUG(NULL, "%s: loaded password from GNOME keyring using %s",
|
||||||
result != GNOME_KEYRING_RESULT_OK ? gnome_keyring_result_to_message(result) :
|
key.description.c_str(),
|
||||||
"empty result list");
|
key.toString().c_str());
|
||||||
|
password = result;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* There have been cases where "received an invalid or
|
||||||
|
* unencryptable secret" was printed to the console right
|
||||||
|
* before we end up here. Apparently the error doesn't
|
||||||
|
* get propagated properly to us.
|
||||||
|
*
|
||||||
|
* To cope with that, we try to disconnect and check again.
|
||||||
|
*/
|
||||||
|
if (i < 3) {
|
||||||
|
SE_LOG_DEBUG(NULL, "disconnecting secret service: password not found");
|
||||||
|
secret_service_disconnect();
|
||||||
|
} else {
|
||||||
|
SE_LOG_DEBUG(NULL, "password not in GNOME keyring using %s",
|
||||||
|
key.toString().c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -173,40 +189,38 @@ bool GNOMESavePasswordSlot(const InitStateTri &keyring,
|
||||||
key.toString().c_str()));
|
key.toString().c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
guint32 itemId;
|
LibSecretHash hash(key);
|
||||||
GnomeKeyringResult result = GNOME_KEYRING_RESULT_OK;
|
std::string label;
|
||||||
// write password to keyring
|
if (!key.user.empty() && !key.server.empty()) {
|
||||||
Timespec start = Timespec::monotonic();
|
// This emulates the behavior of libgnomekeyring.
|
||||||
double sleepSecs = 0;
|
label = key.user + "@" + key.server;
|
||||||
do {
|
} else {
|
||||||
if (sleepSecs != 0) {
|
label = passwordName;
|
||||||
SE_LOG_DEBUG(NULL, "%s: previous attempt to save password '%s' in GNOME keyring failed, will try again: %s",
|
}
|
||||||
key.description.c_str(),
|
for (int i = 0; ; i++) {
|
||||||
key.toString().c_str(),
|
GErrorCXX gerror;
|
||||||
gnome_keyring_result_to_message(result));
|
gboolean result = secret_password_storev_sync(SECRET_SCHEMA_COMPAT_NETWORK,
|
||||||
FlushGNOMEKeyring();
|
hash,
|
||||||
Sleep(sleepSecs);
|
nullptr,
|
||||||
}
|
label.c_str(),
|
||||||
result = gnome_keyring_set_network_password_sync(NULL,
|
password.c_str(),
|
||||||
passwdStr(key.user),
|
nullptr,
|
||||||
passwdStr(key.domain),
|
gerror);
|
||||||
passwdStr(key.server),
|
if (result) {
|
||||||
passwdStr(key.object),
|
SE_LOG_DEBUG(NULL, "saved password in GNOME keyring using %s", key.toString().c_str());
|
||||||
passwdStr(key.protocol),
|
break;
|
||||||
passwdStr(key.authtype),
|
}
|
||||||
key.port,
|
|
||||||
password.c_str(),
|
if (IsSharedSecretError(gerror) &&
|
||||||
&itemId);
|
i < 3) {
|
||||||
sleepSecs = GNOMEKeyringRetryInterval;
|
SE_LOG_DEBUG(NULL, "disconnecting secret service: %u/%d = %s", gerror->domain, gerror->code, gerror->message);
|
||||||
} while (result != GNOME_KEYRING_RESULT_OK &&
|
secret_service_disconnect();
|
||||||
(Timespec::monotonic() - start).duration() < GNOMEKeyringRetryDuration);
|
} else {
|
||||||
if (result != GNOME_KEYRING_RESULT_OK) {
|
gerror.throwError(SE_HERE, StringPrintf("%s: saving password '%s' in GNOME keyring",
|
||||||
Exception::throwError(SE_HERE, StringPrintf("%s: saving password '%s' in GNOME keyring failed: %s",
|
key.description.c_str(),
|
||||||
key.description.c_str(),
|
key.toString().c_str()));
|
||||||
key.toString().c_str(),
|
}
|
||||||
gnome_keyring_result_to_message(result)));
|
|
||||||
}
|
}
|
||||||
SE_LOG_DEBUG(NULL, "saved password in GNOME keyring using %s", key.toString().c_str());
|
|
||||||
|
|
||||||
// handled
|
// handled
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
PKG_CHECK_MODULES(KEYRING, [gnome-keyring-1 >= 2.20], HAVE_KEYRING=yes, HAVE_KEYRING=no)
|
# According to https://developer.gnome.org/libsecret/0.16/libsecret-Password-storage.html#secret-password-store-sync
|
||||||
|
# the simple API was still considered unstable. All supported distros
|
||||||
|
# now have 0.18 where the API is stable.
|
||||||
|
PKG_CHECK_MODULES(KEYRING, [libsecret-1 >= 0.18], HAVE_KEYRING=yes, HAVE_KEYRING=no)
|
||||||
AC_ARG_ENABLE(gnome-keyring,
|
AC_ARG_ENABLE(gnome-keyring,
|
||||||
AS_HELP_STRING([--enable-gnome-keyring],
|
AS_HELP_STRING([--enable-gnome-keyring],
|
||||||
[enables or disables support for the GNOME keyring; default is on if development files are available]),
|
[enables or disables support for the GNOME keyring via libsecret; default is on if development files are available]),
|
||||||
[enable_gnome_keyring="$enableval"
|
[enable_gnome_keyring="$enableval"
|
||||||
test "$enable_gnome_keyring" = "yes" || test "$enable_gnome_keyring" = "no" || AC_MSG_ERROR([invalid value for --enable-gnome-keyring: $enable_gnome_keyring])
|
test "$enable_gnome_keyring" = "yes" || test "$enable_gnome_keyring" = "no" || AC_MSG_ERROR([invalid value for --enable-gnome-keyring: $enable_gnome_keyring])
|
||||||
test "$enable_gnome_keyring" = "no" || test "$HAVE_KEYRING" = "yes" || AC_MSG_ERROR([gnome-keyring-1 pkg >= 2.20 not found, needed for --enable-gnome-keyring])],
|
test "$enable_gnome_keyring" = "no" || test "$HAVE_KEYRING" = "yes" || AC_MSG_ERROR([libsecret-1 >= 0.18 not found, needed for --enable-gnome-keyring])],
|
||||||
enable_gnome_keyring="$HAVE_KEYRING")
|
enable_gnome_keyring="$HAVE_KEYRING")
|
||||||
if test $enable_gnome_keyring = "yes"; then
|
if test $enable_gnome_keyring = "yes"; then
|
||||||
have_keyring=yes
|
have_keyring=yes
|
||||||
|
|
|
@ -36,11 +36,11 @@ public:
|
||||||
" using an account created and managed with GNOME Control Center.")
|
" using an account created and managed with GNOME Control Center.")
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual boost::shared_ptr<AuthProvider> create(const InitStateString &username,
|
virtual std::shared_ptr<AuthProvider> create(const InitStateString &username,
|
||||||
const InitStateString &password)
|
const InitStateString &password)
|
||||||
{
|
{
|
||||||
// Returning NULL if not enabled...
|
// Returning nullptr if not enabled...
|
||||||
boost::shared_ptr<AuthProvider> provider;
|
std::shared_ptr<AuthProvider> provider;
|
||||||
#ifdef USE_GOA
|
#ifdef USE_GOA
|
||||||
provider = createGOAAuthProvider(username, password);
|
provider = createGOAAuthProvider(username, password);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include <gdbus-cxx-bridge.h>
|
#include <gdbus-cxx-bridge.h>
|
||||||
|
|
||||||
#include <boost/algorithm/string/join.hpp>
|
#include <boost/algorithm/string/join.hpp>
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -65,7 +64,7 @@ class GOAManager : private GDBusCXX::DBusRemoteObject
|
||||||
Properties
|
Properties
|
||||||
> Interfaces;
|
> Interfaces;
|
||||||
typedef std::map<GDBusCXX::DBusObject_t, Interfaces> ManagedObjects;
|
typedef std::map<GDBusCXX::DBusObject_t, Interfaces> ManagedObjects;
|
||||||
GDBusCXX::DBusClientCall1<ManagedObjects> m_getManagedObjects;
|
GDBusCXX::DBusClientCall<ManagedObjects> m_getManagedObjects;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GOAManager(const GDBusCXX::DBusConnectionPtr &conn);
|
GOAManager(const GDBusCXX::DBusConnectionPtr &conn);
|
||||||
|
@ -75,7 +74,7 @@ class GOAManager : private GDBusCXX::DBusRemoteObject
|
||||||
* (the unique user visible string). The account must support OAuth2,
|
* (the unique user visible string). The account must support OAuth2,
|
||||||
* otherwise an error is thrown.
|
* otherwise an error is thrown.
|
||||||
*/
|
*/
|
||||||
boost::shared_ptr<GOAAccount> lookupAccount(const std::string &representationID);
|
std::shared_ptr<GOAAccount> lookupAccount(const std::string &representationID);
|
||||||
};
|
};
|
||||||
|
|
||||||
class GOAAccount
|
class GOAAccount
|
||||||
|
@ -88,8 +87,8 @@ public:
|
||||||
GOAAccount(const GDBusCXX::DBusConnectionPtr &conn,
|
GOAAccount(const GDBusCXX::DBusConnectionPtr &conn,
|
||||||
const std::string &path);
|
const std::string &path);
|
||||||
|
|
||||||
GDBusCXX::DBusClientCall1<int32_t> m_ensureCredentials;
|
GDBusCXX::DBusClientCall<int32_t> m_ensureCredentials;
|
||||||
GDBusCXX::DBusClientCall1<std::string> m_getAccessToken;
|
GDBusCXX::DBusClientCall<std::string> m_getAccessToken;
|
||||||
};
|
};
|
||||||
|
|
||||||
GOAManager::GOAManager(const GDBusCXX::DBusConnectionPtr &conn) :
|
GOAManager::GOAManager(const GDBusCXX::DBusConnectionPtr &conn) :
|
||||||
|
@ -98,7 +97,7 @@ GOAManager::GOAManager(const GDBusCXX::DBusConnectionPtr &conn) :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<GOAAccount> GOAManager::lookupAccount(const std::string &username)
|
std::shared_ptr<GOAAccount> GOAManager::lookupAccount(const std::string &username)
|
||||||
{
|
{
|
||||||
SE_LOG_DEBUG(NULL, "Looking up all accounts in GNOME Online Accounts, searching for '%s'.", username.c_str());
|
SE_LOG_DEBUG(NULL, "Looking up all accounts in GNOME Online Accounts, searching for '%s'.", username.c_str());
|
||||||
ManagedObjects objects = m_getManagedObjects();
|
ManagedObjects objects = m_getManagedObjects();
|
||||||
|
@ -107,26 +106,26 @@ boost::shared_ptr<GOAAccount> GOAManager::lookupAccount(const std::string &usern
|
||||||
bool unique = true;
|
bool unique = true;
|
||||||
bool hasOAuth2 = false;
|
bool hasOAuth2 = false;
|
||||||
std::vector<std::string> accounts;
|
std::vector<std::string> accounts;
|
||||||
BOOST_FOREACH (const ManagedObjects::value_type &object, objects) {
|
for (const auto &object: objects) {
|
||||||
const GDBusCXX::DBusObject_t &path = object.first;
|
const GDBusCXX::DBusObject_t &path = object.first;
|
||||||
const Interfaces &interfaces = object.second;
|
const Interfaces &interfaces = object.second;
|
||||||
// boost::adaptors::keys() would be nicer, but is not available on Ubuntu Lucid.
|
// boost::adaptors::keys() would be nicer, but is not available on Ubuntu Lucid.
|
||||||
std::list<std::string> interfaceKeys;
|
std::list<std::string> interfaceKeys;
|
||||||
BOOST_FOREACH (const Interfaces::value_type &entry, interfaces) {
|
for (const auto &entry: interfaces) {
|
||||||
interfaceKeys.push_back(entry.first);
|
interfaceKeys.push_back(entry.first);
|
||||||
}
|
}
|
||||||
SE_LOG_DEBUG(NULL, "GOA object %s implements %s", path.c_str(),
|
SE_LOG_DEBUG(NULL, "GOA object %s implements %s", path.c_str(),
|
||||||
boost::join(interfaceKeys, ", ").c_str());
|
boost::join(interfaceKeys, ", ").c_str());
|
||||||
Interfaces::const_iterator it = interfaces.find(GOA_ACCOUNT_INTERFACE);
|
auto it = interfaces.find(GOA_ACCOUNT_INTERFACE);
|
||||||
if (it != interfaces.end()) {
|
if (it != interfaces.end()) {
|
||||||
const Properties &properties = it->second;
|
const Properties &properties = it->second;
|
||||||
Properties::const_iterator id = properties.find(GOA_ACCOUNT_ID);
|
auto id = properties.find(GOA_ACCOUNT_ID);
|
||||||
Properties::const_iterator presentationID = properties.find(GOA_ACCOUNT_PRESENTATION_IDENTITY);
|
auto presentationID = properties.find(GOA_ACCOUNT_PRESENTATION_IDENTITY);
|
||||||
if (id != properties.end() &&
|
if (id != properties.end() &&
|
||||||
presentationID != properties.end()) {
|
presentationID != properties.end()) {
|
||||||
const std::string &idStr = boost::get<std::string>(id->second);
|
const std::string &idStr = boost::get<std::string>(id->second);
|
||||||
const std::string &presentationIDStr = boost::get<std::string>(presentationID->second);
|
const std::string &presentationIDStr = boost::get<std::string>(presentationID->second);
|
||||||
Properties::const_iterator provider = properties.find(GOA_ACCOUNT_PROVIDER_NAME);
|
auto provider = properties.find(GOA_ACCOUNT_PROVIDER_NAME);
|
||||||
std::string description = StringPrintf("%s, %s = %s",
|
std::string description = StringPrintf("%s, %s = %s",
|
||||||
provider == properties.end() ? "???" : boost::get<std::string>(provider->second).c_str(),
|
provider == properties.end() ? "???" : boost::get<std::string>(provider->second).c_str(),
|
||||||
presentationIDStr.c_str(),
|
presentationIDStr.c_str(),
|
||||||
|
@ -173,7 +172,7 @@ boost::shared_ptr<GOAAccount> GOAManager::lookupAccount(const std::string &usern
|
||||||
username.c_str()));
|
username.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<GOAAccount> account(new GOAAccount(getConnection(), accountPath));
|
auto account = std::make_shared<GOAAccount>(getConnection(), accountPath);
|
||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,10 +187,10 @@ GOAAccount::GOAAccount(const GDBusCXX::DBusConnectionPtr &conn,
|
||||||
|
|
||||||
class GOAAuthProvider : public AuthProvider
|
class GOAAuthProvider : public AuthProvider
|
||||||
{
|
{
|
||||||
boost::shared_ptr<GOAAccount> m_account;
|
std::shared_ptr<GOAAccount> m_account;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GOAAuthProvider(const boost::shared_ptr<GOAAccount> &account) :
|
GOAAuthProvider(const std::shared_ptr<GOAAccount> &account) :
|
||||||
m_account(account)
|
m_account(account)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -209,13 +208,13 @@ public:
|
||||||
virtual std::string getUsername() const { return ""; }
|
virtual std::string getUsername() const { return ""; }
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::shared_ptr<AuthProvider> createGOAAuthProvider(const InitStateString &username,
|
std::shared_ptr<AuthProvider> createGOAAuthProvider(const InitStateString &username,
|
||||||
const InitStateString &password)
|
const InitStateString &password)
|
||||||
{
|
{
|
||||||
// Because we share the connection, hopefully this won't be too expensive.
|
// Because we share the connection, hopefully this won't be too expensive.
|
||||||
GDBusCXX::DBusErrorCXX err;
|
GDBusCXX::DBusErrorCXX err;
|
||||||
GDBusCXX::DBusConnectionPtr conn = dbus_get_bus_connection("SESSION",
|
GDBusCXX::DBusConnectionPtr conn = dbus_get_bus_connection("SESSION",
|
||||||
NULL,
|
nullptr,
|
||||||
false,
|
false,
|
||||||
&err);
|
&err);
|
||||||
if (!conn) {
|
if (!conn) {
|
||||||
|
@ -223,8 +222,8 @@ boost::shared_ptr<AuthProvider> createGOAAuthProvider(const InitStateString &use
|
||||||
}
|
}
|
||||||
|
|
||||||
GOAManager manager(conn);
|
GOAManager manager(conn);
|
||||||
boost::shared_ptr<GOAAccount> account = manager.lookupAccount(username);
|
std::shared_ptr<GOAAccount> account = manager.lookupAccount(username);
|
||||||
boost::shared_ptr<AuthProvider> provider(new GOAAuthProvider(account));
|
auto provider = std::make_shared<GOAAuthProvider>(account);
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,13 +21,13 @@
|
||||||
|
|
||||||
#include <syncevo/util.h>
|
#include <syncevo/util.h>
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <memory>
|
||||||
|
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
|
||||||
class AuthProvider;
|
class AuthProvider;
|
||||||
boost::shared_ptr<AuthProvider> createGOAAuthProvider(const InitStateString &username,
|
std::shared_ptr<AuthProvider> createGOAAuthProvider(const InitStateString &username,
|
||||||
const InitStateString &password);
|
const InitStateString &password);
|
||||||
|
|
||||||
SE_END_CXX
|
SE_END_CXX
|
||||||
|
|
|
@ -216,7 +216,7 @@ KCalExtendedSource::KCalExtendedSource(const SyncSourceParams ¶ms, Type type
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_data = NULL;
|
m_data = nullptr;
|
||||||
m_type = type;
|
m_type = type;
|
||||||
m_delete_run = 0;
|
m_delete_run = 0;
|
||||||
m_insert_run = 0;
|
m_insert_run = 0;
|
||||||
|
@ -311,8 +311,8 @@ void KCalExtendedSource::open()
|
||||||
mKCal::Notebook::List notebookList = m_data->m_storage->notebooks();
|
mKCal::Notebook::List notebookList = m_data->m_storage->notebooks();
|
||||||
mKCal::Notebook::List::Iterator it;
|
mKCal::Notebook::List::Iterator it;
|
||||||
|
|
||||||
for ( it = notebookList.begin(); it != notebookList.end(); ++it ) {
|
for (auto notebook: notebookList) {
|
||||||
if ( name == (*it)->name() ) {
|
if ( name == notebook->name() ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388,19 +388,19 @@ KCalExtendedSource::Databases KCalExtendedSource::getDatabases()
|
||||||
}
|
}
|
||||||
mKCal::Notebook::List notebookList = m_data->m_storage->notebooks();
|
mKCal::Notebook::List notebookList = m_data->m_storage->notebooks();
|
||||||
mKCal::Notebook::List::Iterator it;
|
mKCal::Notebook::List::Iterator it;
|
||||||
for ( it = notebookList.begin(); it != notebookList.end(); ++it ) {
|
for (auto notebook: notebookList) {
|
||||||
#ifdef ENABLE_MAEMO
|
#ifdef ENABLE_MAEMO
|
||||||
string name = (*it)->name().toStdString();
|
string name = notebook->name().toStdString();
|
||||||
string uid = (*it)->uid().toStdString();
|
string uid = notebook->uid().toStdString();
|
||||||
// For notes, we need a different default database:
|
// For notes, we need a different default database:
|
||||||
// Notes (uid:66666666-7777-8888-9999-000000000000)
|
// Notes (uid:66666666-7777-8888-9999-000000000000)
|
||||||
bool isDefault = (m_type != Journal) ?
|
bool isDefault = (m_type != Journal) ?
|
||||||
(*it)->isDefault() :
|
notebook->isDefault() :
|
||||||
(uid == "66666666-7777-8888-9999-000000000000");
|
(uid == "66666666-7777-8888-9999-000000000000");
|
||||||
result.push_back(Database( name, "uid:" + uid, isDefault ));
|
result.push_back(Database( name, "uid:" + uid, isDefault ));
|
||||||
#else
|
#else
|
||||||
bool isDefault = (*it)->isDefault();
|
bool isDefault = notebook->isDefault();
|
||||||
result.push_back(Database( (*it)->name().toStdString(),
|
result.push_back(Database( notebook->name().toStdString(),
|
||||||
(m_data->m_storage).staticCast<mKCal::SqliteStorage>()->databaseName().toStdString(),
|
(m_data->m_storage).staticCast<mKCal::SqliteStorage>()->databaseName().toStdString(),
|
||||||
isDefault));
|
isDefault));
|
||||||
#endif
|
#endif
|
||||||
|
@ -447,7 +447,7 @@ std::string KCalExtendedSource::endSync(bool success)
|
||||||
if (!m_data->m_storage->save()) {
|
if (!m_data->m_storage->save()) {
|
||||||
throwError(SE_HERE, "could not save calendar");
|
throwError(SE_HERE, "could not save calendar");
|
||||||
}
|
}
|
||||||
time_t modtime = time(NULL);
|
time_t modtime = time(nullptr);
|
||||||
// Saving set the modified time stamps of all items needed
|
// Saving set the modified time stamps of all items needed
|
||||||
// saving, so ensure that we sleep for one second starting now.
|
// saving, so ensure that we sleep for one second starting now.
|
||||||
// Must sleep before taking the time stamp for the anchor,
|
// Must sleep before taking the time stamp for the anchor,
|
||||||
|
@ -456,7 +456,7 @@ std::string KCalExtendedSource::endSync(bool success)
|
||||||
time_t current = modtime;
|
time_t current = modtime;
|
||||||
do {
|
do {
|
||||||
sleep(1 - (current - modtime));
|
sleep(1 - (current - modtime));
|
||||||
current = time(NULL);
|
current = time(nullptr);
|
||||||
} while (current - modtime < 1);
|
} while (current - modtime < 1);
|
||||||
m_delete_run = 0;
|
m_delete_run = 0;
|
||||||
m_insert_run = 0;
|
m_insert_run = 0;
|
||||||
|
@ -531,7 +531,7 @@ TestingSyncSource::InsertItemResult KCalExtendedSource::insertItem(const string
|
||||||
if (source) {
|
if (source) {
|
||||||
KCalCore::ICalTimeZones *target = m_data->m_calendar->timeZones();
|
KCalCore::ICalTimeZones *target = m_data->m_calendar->timeZones();
|
||||||
if (target) {
|
if (target) {
|
||||||
BOOST_FOREACH(const KCalCore::ICalTimeZone &zone, source->zones().values()) {
|
for (const auto &zone: source->zones().values()) {
|
||||||
target->add(zone);
|
target->add(zone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
|
||||||
static SyncSource *createSource(const SyncSourceParams ¶ms)
|
static std::unique_ptr<SyncSource> createSource(const SyncSourceParams ¶ms)
|
||||||
{
|
{
|
||||||
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
||||||
bool isMe = sourceType.m_backend == "mkcal-events";
|
bool isMe = sourceType.m_backend == "mkcal-events";
|
||||||
|
@ -39,7 +39,7 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
#ifdef ENABLE_KCALEXTENDED
|
#ifdef ENABLE_KCALEXTENDED
|
||||||
true ? new KCalExtendedSource(params, KCalExtendedSource::Event) :
|
true ? new KCalExtendedSource(params, KCalExtendedSource::Event) :
|
||||||
#endif
|
#endif
|
||||||
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
|
isMe ? RegisterSyncSource::InactiveSource(params) : nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
#ifdef ENABLE_KCALEXTENDED
|
#ifdef ENABLE_KCALEXTENDED
|
||||||
true ? new KCalExtendedSource(params, KCalExtendedSource::Todo) :
|
true ? new KCalExtendedSource(params, KCalExtendedSource::Todo) :
|
||||||
#endif
|
#endif
|
||||||
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
|
isMe ? RegisterSyncSource::InactiveSource(params) : nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,11 +71,11 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
#ifdef ENABLE_KCALEXTENDED
|
#ifdef ENABLE_KCALEXTENDED
|
||||||
true ? new KCalExtendedSource(params, KCalExtendedSource::Journal) :
|
true ? new KCalExtendedSource(params, KCalExtendedSource::Journal) :
|
||||||
#endif
|
#endif
|
||||||
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
|
isMe ? RegisterSyncSource::InactiveSource(params) : nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterSyncSource registerMe("KCalExtended",
|
static RegisterSyncSource registerMe("KCalExtended",
|
||||||
|
@ -126,8 +126,8 @@ class KCalExtendedSourceUnitTest : public CppUnit::TestFixture {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void testInstantiate() {
|
void testInstantiate() {
|
||||||
boost::shared_ptr<SyncSource> source;
|
std::unique_ptr<SyncSource> source;
|
||||||
source.reset(SyncSource::createTestingSource("KCalExtended", "KCalExtended:text/calendar:2.0", true));
|
source = SyncSource::createTestingSource("KCalExtended", "KCalExtended:text/calendar:2.0", true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ void KDEInitMainSlot(const char *appname)
|
||||||
|
|
||||||
//QCoreApplication *app;
|
//QCoreApplication *app;
|
||||||
int argc = 1;
|
int argc = 1;
|
||||||
static char *argv[] = { const_cast<char *>(appname), NULL };
|
static char *argv[] = { const_cast<char *>(appname), nullptr };
|
||||||
KAboutData aboutData(// The program name used internally.
|
KAboutData aboutData(// The program name used internally.
|
||||||
"syncevolution",
|
"syncevolution",
|
||||||
// The message catalog name
|
// The message catalog name
|
||||||
|
@ -99,8 +99,8 @@ void KDEInitMainSlot(const char *appname)
|
||||||
// Don't allow KApplication to mess with SIGINT/SIGTERM.
|
// Don't allow KApplication to mess with SIGINT/SIGTERM.
|
||||||
// Restore current behavior after construction.
|
// Restore current behavior after construction.
|
||||||
struct sigaction oldsigint, oldsigterm;
|
struct sigaction oldsigint, oldsigterm;
|
||||||
sigaction(SIGINT, NULL, &oldsigint);
|
sigaction(SIGINT, nullptr, &oldsigint);
|
||||||
sigaction(SIGTERM, NULL, &oldsigterm);
|
sigaction(SIGTERM, nullptr, &oldsigterm);
|
||||||
|
|
||||||
// Explicitly disable GUI mode in the KApplication. Otherwise
|
// Explicitly disable GUI mode in the KApplication. Otherwise
|
||||||
// the whole binary will fail to run when there is no X11
|
// the whole binary will fail to run when there is no X11
|
||||||
|
@ -109,8 +109,8 @@ void KDEInitMainSlot(const char *appname)
|
||||||
//To stop KApplication from spawning it's own DBus Service ... Will have to patch KApplication about this
|
//To stop KApplication from spawning it's own DBus Service ... Will have to patch KApplication about this
|
||||||
QDBusConnection::sessionBus().unregisterService("org.syncevolution.syncevolution-"+QString::number(getpid()));
|
QDBusConnection::sessionBus().unregisterService("org.syncevolution.syncevolution-"+QString::number(getpid()));
|
||||||
|
|
||||||
sigaction(SIGINT, &oldsigint, NULL);
|
sigaction(SIGINT, &oldsigint, nullptr);
|
||||||
sigaction(SIGTERM, &oldsigterm, NULL);
|
sigaction(SIGTERM, &oldsigterm, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,8 +67,8 @@ MaemoCalendarSource::MaemoCalendarSource(int EntryType, int EntryFormat,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mc = CMulticalendar::MCInstance();
|
mc = CMulticalendar::MCInstance();
|
||||||
cal = NULL;
|
cal = nullptr;
|
||||||
conv = NULL;
|
conv = nullptr;
|
||||||
if (!mc) {
|
if (!mc) {
|
||||||
throwError(SE_HERE, "Could not connect to Maemo Calendar backend");
|
throwError(SE_HERE, "Could not connect to Maemo Calendar backend");
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ std::string MaemoCalendarSource::getMimeType() const
|
||||||
"text/calendar+plain" :
|
"text/calendar+plain" :
|
||||||
"text/calendar";
|
"text/calendar";
|
||||||
case VCAL_TYPE: return "text/x-calendar";
|
case VCAL_TYPE: return "text/x-calendar";
|
||||||
default: return NULL;
|
default: return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ std::string MaemoCalendarSource::getMimeVersion() const
|
||||||
case -1: return "1.0";
|
case -1: return "1.0";
|
||||||
case ICAL_TYPE: return "2.0";
|
case ICAL_TYPE: return "2.0";
|
||||||
case VCAL_TYPE: return "1.0";
|
case VCAL_TYPE: return "1.0";
|
||||||
default: return NULL;
|
default: return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,9 +155,9 @@ bool MaemoCalendarSource::isEmpty()
|
||||||
void MaemoCalendarSource::close()
|
void MaemoCalendarSource::close()
|
||||||
{
|
{
|
||||||
delete conv;
|
delete conv;
|
||||||
conv = NULL;
|
conv = nullptr;
|
||||||
delete cal;
|
delete cal;
|
||||||
cal = NULL;
|
cal = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaemoCalendarSource::Databases MaemoCalendarSource::getDatabases()
|
MaemoCalendarSource::Databases MaemoCalendarSource::getDatabases()
|
||||||
|
@ -170,7 +170,7 @@ MaemoCalendarSource::Databases MaemoCalendarSource::getDatabases()
|
||||||
vector< CCalendar * > calendars = mc->getListCalFromMc();
|
vector< CCalendar * > calendars = mc->getListCalFromMc();
|
||||||
Databases result;
|
Databases result;
|
||||||
|
|
||||||
BOOST_FOREACH(CCalendar * c, calendars) {
|
for (CCalendar * c: calendars) {
|
||||||
int id = c->getCalendarId();
|
int id = c->getCalendarId();
|
||||||
ostringstream uri;
|
ostringstream uri;
|
||||||
uri << "id:" << id;
|
uri << "id:" << id;
|
||||||
|
@ -204,7 +204,7 @@ void MaemoCalendarSource::listAllItems(RevisionMap_t &revisions)
|
||||||
// components of the specified type, so just ignore it for now
|
// components of the specified type, so just ignore it for now
|
||||||
if (!comps.size())
|
if (!comps.size())
|
||||||
break;
|
break;
|
||||||
BOOST_FOREACH(CComponent * c, comps) {
|
for (CComponent * c: comps) {
|
||||||
revisions[c->getId()] = get_revision(c);
|
revisions[c->getId()] = get_revision(c);
|
||||||
// Testing shows that the backend doesn't free the memory itself
|
// Testing shows that the backend doesn't free the memory itself
|
||||||
delete c;
|
delete c;
|
||||||
|
@ -219,7 +219,7 @@ void MaemoCalendarSource::listAllItems(RevisionMap_t &revisions)
|
||||||
// desirable, given the N900's limited memory.
|
// desirable, given the N900's limited memory.
|
||||||
int err;
|
int err;
|
||||||
vector< string > ids = cal->getIdList(entry_type, err);
|
vector< string > ids = cal->getIdList(entry_type, err);
|
||||||
BOOST_FOREACH(std::string& id, ids) {
|
for (std::string& id: ids) {
|
||||||
CComponent *c = cal->getEntry(id, entry_type, err);
|
CComponent *c = cal->getEntry(id, entry_type, err);
|
||||||
if (!c)
|
if (!c)
|
||||||
{
|
{
|
||||||
|
@ -278,7 +278,7 @@ TrackingSyncSource::InsertItemResult MaemoCalendarSource::insertItem(const strin
|
||||||
throwError(SE_HERE, string("no events in ical: ") + item);
|
throwError(SE_HERE, string("no events in ical: ") + item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vector< CComponent * >::iterator it = comps.begin();
|
vector< CComponent * auto it = comps.begin();
|
||||||
if (comps.size() > 1) {
|
if (comps.size() > 1) {
|
||||||
for (; it != comps.end(); ++it) {
|
for (; it != comps.end(); ++it) {
|
||||||
delete (*it);
|
delete (*it);
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
|
||||||
static SyncSource *createSource(const SyncSourceParams ¶ms)
|
static std::unique_ptr<SyncSource> createSource(const SyncSourceParams ¶ms)
|
||||||
{
|
{
|
||||||
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
||||||
bool isMe = sourceType.m_backend == "Maemo Calendar";
|
bool isMe = sourceType.m_backend == "Maemo Calendar";
|
||||||
|
@ -35,11 +35,11 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
|
|
||||||
if (isMe || maybeMe) {
|
if (isMe || maybeMe) {
|
||||||
if (sourceType.m_format == "" || sourceType.m_format == "text/calendar") {
|
if (sourceType.m_format == "" || sourceType.m_format == "text/calendar") {
|
||||||
return new MaemoCalendarSource(EVENT, ICAL_TYPE, params);
|
return std::make_unique<MaemoCalendarSource>(EVENT, ICAL_TYPE, params);
|
||||||
} else if (sourceType.m_format == "text/x-vcalendar") {
|
} else if (sourceType.m_format == "text/x-vcalendar") {
|
||||||
return new MaemoCalendarSource(EVENT, VCAL_TYPE, params);
|
return std::make_unique<MaemoCalendarSource>(EVENT, VCAL_TYPE, params);
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -52,11 +52,11 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
|
|
||||||
if (isMe || maybeMe) {
|
if (isMe || maybeMe) {
|
||||||
if (sourceType.m_format == "" || sourceType.m_format == "text/calendar") {
|
if (sourceType.m_format == "" || sourceType.m_format == "text/calendar") {
|
||||||
return new MaemoCalendarSource(TODO, ICAL_TYPE, params);
|
return std::make_unique<MaemoCalendarSource>(TODO, ICAL_TYPE, params);
|
||||||
} else if (sourceType.m_format == "text/x-vcalendar") {
|
} else if (sourceType.m_format == "text/x-vcalendar") {
|
||||||
return new MaemoCalendarSource(TODO, VCAL_TYPE, params);
|
return std::make_unique<MaemoCalendarSource>(TODO, VCAL_TYPE, params);
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -69,18 +69,18 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
|
|
||||||
if (isMe || maybeMe) {
|
if (isMe || maybeMe) {
|
||||||
if (sourceType.m_format == "" || sourceType.m_format == "text/calendar") {
|
if (sourceType.m_format == "" || sourceType.m_format == "text/calendar") {
|
||||||
return new MaemoCalendarSource(JOURNAL, ICAL_TYPE, params);
|
return std::make_unique<MaemoCalendarSource>(JOURNAL, ICAL_TYPE, params);
|
||||||
} else if (sourceType.m_format == "text/x-vcalendar") {
|
} else if (sourceType.m_format == "text/x-vcalendar") {
|
||||||
return new MaemoCalendarSource(JOURNAL, VCAL_TYPE, params);
|
return std::make_unique<MaemoCalendarSource>(JOURNAL, VCAL_TYPE, params);
|
||||||
} else if (sourceType.m_format == "text/plain") {
|
} else if (sourceType.m_format == "text/plain") {
|
||||||
return new MaemoCalendarSource(JOURNAL, -1, params);
|
return std::make_unique<MaemoCalendarSource>(JOURNAL, -1, params);
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterSyncSource registerMe("Maemo Calendar/Tasks/Notes",
|
static RegisterSyncSource registerMe("Maemo Calendar/Tasks/Notes",
|
||||||
|
@ -115,10 +115,10 @@ class MaemoCalendarSourceUnitTest : public CppUnit::TestFixture {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void testInstantiate() {
|
void testInstantiate() {
|
||||||
boost::shared_ptr<SyncSource> source;
|
std::unique_ptr<SyncSource> source;
|
||||||
source.reset(SyncSource::createTestingSource("calendar", "calendar", true));
|
source = SyncSource::createTestingSource("calendar", "calendar", true);
|
||||||
source.reset(SyncSource::createTestingSource("calendar", "maemo-events", true));
|
source = SyncSource::createTestingSource("calendar", "maemo-events", true);
|
||||||
source.reset(SyncSource::createTestingSource("calendar", "Maemo Calendar:text/calendar", true));
|
source = SyncSource::createTestingSource("calendar", "Maemo Calendar:text/calendar", true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,14 +23,17 @@
|
||||||
#include <syncevo/GLibSupport.h>
|
#include <syncevo/GLibSupport.h>
|
||||||
#include <syncevo/GVariantSupport.h>
|
#include <syncevo/GVariantSupport.h>
|
||||||
#include <syncevo/SoupTransportAgent.h>
|
#include <syncevo/SoupTransportAgent.h>
|
||||||
|
#include <syncevo/CurlTransportAgent.h>
|
||||||
#include <json.h>
|
#include <json.h>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
|
||||||
class RefreshTokenAuthProvider : public AuthProvider
|
class RefreshTokenAuthProvider : public AuthProvider
|
||||||
{
|
{
|
||||||
boost::shared_ptr<HTTPTransportAgent> m_agent;
|
std::shared_ptr<HTTPTransportAgent> m_agent;
|
||||||
std::string m_tokenHost;
|
std::string m_tokenHost;
|
||||||
std::string m_tokenPath;
|
std::string m_tokenPath;
|
||||||
std::string m_scope;
|
std::string m_scope;
|
||||||
|
@ -46,6 +49,13 @@ public:
|
||||||
const char* clientID,
|
const char* clientID,
|
||||||
const char* clientSecret,
|
const char* clientSecret,
|
||||||
const char* refreshToken) :
|
const char* refreshToken) :
|
||||||
|
m_agent(
|
||||||
|
#ifdef ENABLE_LIBSOUP
|
||||||
|
make_weak_shared::make<SoupTransportAgent>(static_cast<GMainLoop *>(nullptr))
|
||||||
|
#elif defined(ENABLE_LIBCURL)
|
||||||
|
std::make_shared<CurlTransportAgent>()
|
||||||
|
#endif
|
||||||
|
),
|
||||||
m_tokenHost(tokenHost),
|
m_tokenHost(tokenHost),
|
||||||
m_tokenPath(tokenPath),
|
m_tokenPath(tokenPath),
|
||||||
m_scope(scope),
|
m_scope(scope),
|
||||||
|
@ -53,12 +63,6 @@ public:
|
||||||
m_clientSecret(clientSecret),
|
m_clientSecret(clientSecret),
|
||||||
m_refreshToken(refreshToken)
|
m_refreshToken(refreshToken)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_LIBSOUP
|
|
||||||
boost::shared_ptr<SoupTransportAgent> agent(new SoupTransportAgent(static_cast<GMainLoop *>(NULL)));
|
|
||||||
m_agent = agent;
|
|
||||||
#elif defined(ENABLE_LIBCURL)
|
|
||||||
m_agent = new CurlTransportAgent();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool methodIsSupported(AuthMethod method) const { return method == AUTH_METHOD_OAUTH2; }
|
virtual bool methodIsSupported(AuthMethod method) const { return method == AUTH_METHOD_OAUTH2; }
|
||||||
|
@ -157,15 +161,15 @@ public:
|
||||||
virtual std::string getUsername() const { return ""; }
|
virtual std::string getUsername() const { return ""; }
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::shared_ptr<AuthProvider> createOAuth2AuthProvider(const InitStateString &username,
|
std::shared_ptr<AuthProvider> createOAuth2AuthProvider(const InitStateString &username,
|
||||||
const InitStateString &password)
|
const InitStateString &password)
|
||||||
{
|
{
|
||||||
// Expected content of parameter GVariant.
|
// Expected content of parameter GVariant.
|
||||||
boost::shared_ptr<GVariantType> hashtype(g_variant_type_new("a{ss}"), g_variant_type_free);
|
std::shared_ptr<GVariantType> hashtype(g_variant_type_new("a{ss}"), g_variant_type_free);
|
||||||
|
|
||||||
// 'username' is the part after oauth2: which we can parse directly.
|
// 'username' is the part after oauth2: which we can parse directly.
|
||||||
GErrorCXX gerror;
|
GErrorCXX gerror;
|
||||||
GVariantStealCXX parametersVar(g_variant_parse(hashtype.get(), username.c_str(), NULL, NULL, gerror));
|
GVariantStealCXX parametersVar(g_variant_parse(hashtype.get(), username.c_str(), nullptr, nullptr, gerror));
|
||||||
if (!parametersVar) {
|
if (!parametersVar) {
|
||||||
gerror.throwError(SE_HERE, "parsing 'oauth2:' username");
|
gerror.throwError(SE_HERE, "parsing 'oauth2:' username");
|
||||||
}
|
}
|
||||||
|
@ -206,7 +210,7 @@ boost::shared_ptr<AuthProvider> createOAuth2AuthProvider(const InitStateString &
|
||||||
if (password.empty()) {
|
if (password.empty()) {
|
||||||
SE_THROW("need refresh token provided as password");
|
SE_THROW("need refresh token provided as password");
|
||||||
}
|
}
|
||||||
boost::shared_ptr<AuthProvider> provider(new RefreshTokenAuthProvider(tokenHost, tokenPath, scope, clientID, clientSecret, password.c_str()));
|
auto provider = std::make_shared<RefreshTokenAuthProvider>(tokenHost, tokenPath, scope, clientID, clientSecret, password.c_str());
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,13 +21,13 @@
|
||||||
|
|
||||||
#include <syncevo/util.h>
|
#include <syncevo/util.h>
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <memory>
|
||||||
|
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
|
||||||
class AuthProvider;
|
class AuthProvider;
|
||||||
boost::shared_ptr<AuthProvider> createOAuth2AuthProvider(const InitStateString &username,
|
std::shared_ptr<AuthProvider> createOAuth2AuthProvider(const InitStateString &username,
|
||||||
const InitStateString &password);
|
const InitStateString &password);
|
||||||
|
|
||||||
SE_END_CXX
|
SE_END_CXX
|
||||||
|
|
|
@ -41,10 +41,10 @@ public:
|
||||||
" 'Scope', 'ClientID', 'ClientSecret'\n")
|
" 'Scope', 'ClientID', 'ClientSecret'\n")
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual boost::shared_ptr<AuthProvider> create(const InitStateString &username,
|
virtual std::shared_ptr<AuthProvider> create(const InitStateString &username,
|
||||||
const InitStateString &password)
|
const InitStateString &password)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<AuthProvider> provider;
|
std::shared_ptr<AuthProvider> provider;
|
||||||
provider = createOAuth2AuthProvider(username, password);
|
provider = createOAuth2AuthProvider(username, password);
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
#include "PbapSyncSource.h"
|
#include "PbapSyncSource.h"
|
||||||
|
|
||||||
#include <boost/assign/list_of.hpp>
|
|
||||||
#include <boost/algorithm/string/case_conv.hpp>
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
#include <boost/tokenizer.hpp>
|
#include <boost/tokenizer.hpp>
|
||||||
|
|
||||||
|
@ -33,8 +32,8 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <pcrecpp.h>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
#include <syncevo/GLibSupport.h> // PBAP backend does not compile without GLib.
|
#include <syncevo/GLibSupport.h> // PBAP backend does not compile without GLib.
|
||||||
#include <syncevo/util.h>
|
#include <syncevo/util.h>
|
||||||
|
@ -45,7 +44,6 @@
|
||||||
#include "gdbus-cxx-bridge.h"
|
#include "gdbus-cxx-bridge.h"
|
||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
#include <synthesis/SDK_util.h>
|
#include <synthesis/SDK_util.h>
|
||||||
|
|
||||||
|
@ -64,7 +62,7 @@ SE_BEGIN_CXX
|
||||||
#define OBC_TRANSFER_INTERFACE_NEW "org.bluez.obex.Transfer"
|
#define OBC_TRANSFER_INTERFACE_NEW "org.bluez.obex.Transfer"
|
||||||
#define OBC_TRANSFER_INTERFACE_NEW5 "org.bluez.obex.Transfer1"
|
#define OBC_TRANSFER_INTERFACE_NEW5 "org.bluez.obex.Transfer1"
|
||||||
|
|
||||||
typedef std::map<int, pcrecpp::StringPiece> Content;
|
typedef std::map<int, StringPiece> Content;
|
||||||
typedef std::list<std::string> ContactQueue;
|
typedef std::list<std::string> ContactQueue;
|
||||||
typedef std::list<std::string> Properties;
|
typedef std::list<std::string> Properties;
|
||||||
typedef boost::variant< std::string, Properties, uint16_t > Bluez5Values;
|
typedef boost::variant< std::string, Properties, uint16_t > Bluez5Values;
|
||||||
|
@ -146,7 +144,7 @@ struct PullParams
|
||||||
*
|
*
|
||||||
* Note that GetSize() is specified as returning the number of entries in
|
* Note that GetSize() is specified as returning the number of entries in
|
||||||
* the selected phonebook object that are actually used (i.e. indexes that
|
* the selected phonebook object that are actually used (i.e. indexes that
|
||||||
* correspond to non-NULL entries). This is relevant if contacts get
|
* correspond to non-nullptr entries). This is relevant if contacts get
|
||||||
* deleted after starting the session. In that case, the algorithm above
|
* deleted after starting the session. In that case, the algorithm above
|
||||||
* will not necessarily read all contacts. Here's an example:
|
* will not necessarily read all contacts. Here's an example:
|
||||||
* offsets #0 till #99, with contacts #10 till #19 deleted
|
* offsets #0 till #99, with contacts #10 till #19 deleted
|
||||||
|
@ -226,7 +224,7 @@ class PullAll
|
||||||
|
|
||||||
uint16_t m_numContacts; // Number of existing contacts, according to GetSize() or after downloading.
|
uint16_t m_numContacts; // Number of existing contacts, according to GetSize() or after downloading.
|
||||||
uint16_t m_currentContact; // Numbered starting with zero according to discovery in addVCards.
|
uint16_t m_currentContact; // Numbered starting with zero according to discovery in addVCards.
|
||||||
boost::shared_ptr<PbapSession> m_session; // Only set when there is a transfer ongoing.
|
std::shared_ptr<PbapSession> m_session; // Only set when there is a transfer ongoing.
|
||||||
size_t m_tmpFileOffset; // Number of bytes already parsed.
|
size_t m_tmpFileOffset; // Number of bytes already parsed.
|
||||||
uint16_t m_transferOffset; // First contact requested as part of current transfer.
|
uint16_t m_transferOffset; // First contact requested as part of current transfer.
|
||||||
uint16_t m_initialOffset; // First contact request by first transfer.
|
uint16_t m_initialOffset; // First contact request by first transfer.
|
||||||
|
@ -247,8 +245,8 @@ public:
|
||||||
~PullAll();
|
~PullAll();
|
||||||
|
|
||||||
std::string getNextID();
|
std::string getNextID();
|
||||||
bool getContact(const char *id, pcrecpp::StringPiece &vcard);
|
bool getContact(const char *id, StringPiece &vcard);
|
||||||
const char *addVCards(int startIndex, const pcrecpp::StringPiece &content);
|
const char *addVCards(int startIndex, const StringPiece &content, bool eof);
|
||||||
};
|
};
|
||||||
|
|
||||||
PullAll::PullAll() :
|
PullAll::PullAll() :
|
||||||
|
@ -269,15 +267,16 @@ PullAll::~PullAll()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
class PbapSession : private boost::noncopyable {
|
class PbapSession : private boost::noncopyable, public enable_weak_from_this<PbapSession> {
|
||||||
public:
|
public:
|
||||||
static boost::shared_ptr<PbapSession> create(PbapSyncSource &parent);
|
// Construct via make_weak_shared.
|
||||||
|
friend make_weak_shared;
|
||||||
|
|
||||||
void initSession(const std::string &address, const std::string &format);
|
void initSession(const std::string &address, const std::string &format);
|
||||||
|
|
||||||
typedef std::map<std::string, pcrecpp::StringPiece> Content;
|
typedef std::map<std::string, StringPiece> Content;
|
||||||
|
|
||||||
boost::shared_ptr<PullAll> startPullAll(const PullParams &pullParams);
|
std::shared_ptr<PullAll> startPullAll(const PullParams &pullParams);
|
||||||
void continuePullAll(PullAll &state);
|
void continuePullAll(PullAll &state);
|
||||||
void checkForError(); // Throws exception if transfer failed.
|
void checkForError(); // Throws exception if transfer failed.
|
||||||
Timespec transferComplete() const;
|
Timespec transferComplete() const;
|
||||||
|
@ -290,8 +289,7 @@ private:
|
||||||
PbapSession(PbapSyncSource &parent);
|
PbapSession(PbapSyncSource &parent);
|
||||||
|
|
||||||
PbapSyncSource &m_parent;
|
PbapSyncSource &m_parent;
|
||||||
boost::weak_ptr<PbapSession> m_self;
|
std::unique_ptr<GDBusCXX::DBusRemoteObject> m_client;
|
||||||
std::auto_ptr<GDBusCXX::DBusRemoteObject> m_client;
|
|
||||||
bool m_frozen;
|
bool m_frozen;
|
||||||
enum {
|
enum {
|
||||||
OBEXD_OLD, // obexd < 0.47
|
OBEXD_OLD, // obexd < 0.47
|
||||||
|
@ -333,28 +331,25 @@ private:
|
||||||
Transfers m_transfers;
|
Transfers m_transfers;
|
||||||
std::string m_currentTransfer;
|
std::string m_currentTransfer;
|
||||||
|
|
||||||
std::auto_ptr<GDBusCXX::SignalWatch3<GDBusCXX::Path_t, std::string, std::string> >
|
std::unique_ptr<GDBusCXX::SignalWatch<GDBusCXX::Path_t, std::string, std::string> >
|
||||||
m_errorSignal;
|
m_errorSignal;
|
||||||
void errorCb(const GDBusCXX::Path_t &path, const std::string &error,
|
|
||||||
const std::string &msg);
|
|
||||||
|
|
||||||
// Bluez 5
|
// Bluez 5
|
||||||
typedef GDBusCXX::SignalWatch4<GDBusCXX::Path_t, std::string, Params, std::vector<std::string> > PropChangedSignal_t;
|
typedef GDBusCXX::SignalWatch<GDBusCXX::Path_t, std::string, Params, std::vector<std::string> > PropChangedSignal_t;
|
||||||
std::auto_ptr<PropChangedSignal_t> m_propChangedSignal;
|
std::unique_ptr<PropChangedSignal_t> m_propChangedSignal;
|
||||||
void propChangedCb(const GDBusCXX::Path_t &path,
|
void propChangedCb(const GDBusCXX::Path_t &path,
|
||||||
const std::string &interface,
|
const std::string &interface,
|
||||||
const Params &changed,
|
const Params &changed,
|
||||||
const std::vector<std::string> &invalidated);
|
const std::vector<std::string> &invalidated);
|
||||||
|
|
||||||
// new obexd API
|
// new obexd API
|
||||||
typedef GDBusCXX::SignalWatch1<GDBusCXX::Path_t> CompleteSignal_t;
|
typedef GDBusCXX::SignalWatch<GDBusCXX::Path_t> CompleteSignal_t;
|
||||||
std::auto_ptr<CompleteSignal_t> m_completeSignal;
|
std::unique_ptr<CompleteSignal_t> m_completeSignal;
|
||||||
void completeCb(const GDBusCXX::Path_t &path);
|
typedef GDBusCXX::SignalWatch<GDBusCXX::Path_t, std::string, boost::variant<int64_t> > PropertyChangedSignal_t;
|
||||||
typedef GDBusCXX::SignalWatch3<GDBusCXX::Path_t, std::string, boost::variant<int64_t> > PropertyChangedSignal_t;
|
std::unique_ptr<PropertyChangedSignal_t> m_propertyChangedSignal;
|
||||||
std::auto_ptr<PropertyChangedSignal_t> m_propertyChangedSignal;
|
|
||||||
void propertyChangedCb(const GDBusCXX::Path_t &path, const std::string &name, const boost::variant<int64_t> &value);
|
void propertyChangedCb(const GDBusCXX::Path_t &path, const std::string &name, const boost::variant<int64_t> &value);
|
||||||
|
|
||||||
std::auto_ptr<GDBusCXX::DBusRemoteObject> m_session;
|
std::unique_ptr<GDBusCXX::DBusRemoteObject> m_session;
|
||||||
};
|
};
|
||||||
|
|
||||||
PbapSession::PbapSession(PbapSyncSource &parent) :
|
PbapSession::PbapSession(PbapSyncSource &parent) :
|
||||||
|
@ -363,13 +358,6 @@ PbapSession::PbapSession(PbapSyncSource &parent) :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<PbapSession> PbapSession::create(PbapSyncSource &parent)
|
|
||||||
{
|
|
||||||
boost::shared_ptr<PbapSession> session(new PbapSession(parent));
|
|
||||||
session->m_self = session;
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PbapSession::propChangedCb(const GDBusCXX::Path_t &path,
|
void PbapSession::propChangedCb(const GDBusCXX::Path_t &path,
|
||||||
const std::string &interface,
|
const std::string &interface,
|
||||||
const Params &changed,
|
const Params &changed,
|
||||||
|
@ -377,7 +365,7 @@ void PbapSession::propChangedCb(const GDBusCXX::Path_t &path,
|
||||||
{
|
{
|
||||||
// Called for a path which matches the current session, so we know
|
// Called for a path which matches the current session, so we know
|
||||||
// that the signal is for our transfer. Only need to check the status.
|
// that the signal is for our transfer. Only need to check the status.
|
||||||
Params::const_iterator it = changed.find("Status");
|
auto it = changed.find("Status");
|
||||||
if (it != changed.end()) {
|
if (it != changed.end()) {
|
||||||
std::string status = boost::get<std::string>(it->second);
|
std::string status = boost::get<std::string>(it->second);
|
||||||
SE_LOG_DEBUG(NULL, "OBEXD transfer %s: %s",
|
SE_LOG_DEBUG(NULL, "OBEXD transfer %s: %s",
|
||||||
|
@ -399,7 +387,7 @@ void PbapSession::propChangedCb(const GDBusCXX::Path_t &path,
|
||||||
OBC_TRANSFER_INTERFACE_NEW5,
|
OBC_TRANSFER_INTERFACE_NEW5,
|
||||||
OBC_SERVICE_NEW5,
|
OBC_SERVICE_NEW5,
|
||||||
true);
|
true);
|
||||||
GDBusCXX::DBusClientCall0(transfer, "Suspend")();
|
GDBusCXX::DBusClientCall<>(transfer, "Suspend")();
|
||||||
SE_LOG_DEBUG(NULL, "successfully suspended transfer when it became active");
|
SE_LOG_DEBUG(NULL, "successfully suspended transfer when it became active");
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// Ignore all errors here. The worst that can happen is that
|
// Ignore all errors here. The worst that can happen is that
|
||||||
|
@ -413,24 +401,6 @@ void PbapSession::propChangedCb(const GDBusCXX::Path_t &path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PbapSession::completeCb(const GDBusCXX::Path_t &path)
|
|
||||||
{
|
|
||||||
SE_LOG_DEBUG(NULL, "obexd transfer %s completed", path.c_str());
|
|
||||||
m_transfers[path] = Completion::now();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PbapSession::errorCb(const GDBusCXX::Path_t &path,
|
|
||||||
const std::string &error,
|
|
||||||
const std::string &msg)
|
|
||||||
{
|
|
||||||
SE_LOG_DEBUG(NULL, "obexd transfer %s failed: %s %s",
|
|
||||||
path.c_str(), error.c_str(), msg.c_str());
|
|
||||||
Completion &completion = m_transfers[path];
|
|
||||||
completion.m_transferComplete = Timespec::monotonic();
|
|
||||||
completion.m_transferErrorCode = error;
|
|
||||||
completion.m_transferErrorMsg = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PbapSession::propertyChangedCb(const GDBusCXX::Path_t &path,
|
void PbapSession::propertyChangedCb(const GDBusCXX::Path_t &path,
|
||||||
const std::string &name,
|
const std::string &name,
|
||||||
const boost::variant<int64_t> &value)
|
const boost::variant<int64_t> &value)
|
||||||
|
@ -448,35 +418,36 @@ void PbapSession::propertyChangedCb(const GDBusCXX::Path_t &path,
|
||||||
Properties PbapSession::supportedProperties() const
|
Properties PbapSession::supportedProperties() const
|
||||||
{
|
{
|
||||||
Properties props;
|
Properties props;
|
||||||
static const std::set<std::string> supported =
|
static const std::set<std::string> supported = {
|
||||||
boost::assign::list_of("VERSION")
|
"VERSION",
|
||||||
("FN")
|
"FN",
|
||||||
("N")
|
"N",
|
||||||
("PHOTO")
|
"PHOTO",
|
||||||
("BDAY")
|
"BDAY",
|
||||||
("ADR")
|
"ADR",
|
||||||
("LABEL")
|
"LABEL",
|
||||||
("TEL")
|
"TEL",
|
||||||
("EMAIL")
|
"EMAIL",
|
||||||
("MAILER")
|
"MAILER",
|
||||||
("TZ")
|
"TZ",
|
||||||
("GEO")
|
"GEO",
|
||||||
("TITLE")
|
"TITLE",
|
||||||
("ROLE")
|
"ROLE",
|
||||||
("LOGO")
|
"LOGO",
|
||||||
("AGENT")
|
"AGENT",
|
||||||
("ORG")
|
"ORG",
|
||||||
("NOTE")
|
"NOTE",
|
||||||
("REV")
|
"REV",
|
||||||
("SOUND")
|
"SOUND",
|
||||||
("URL")
|
"URL",
|
||||||
("UID")
|
"UID",
|
||||||
("KEY")
|
"KEY",
|
||||||
("NICKNAME")
|
"NICKNAME",
|
||||||
("CATEGORIES")
|
"CATEGORIES",
|
||||||
("CLASS");
|
"CLASS"
|
||||||
|
};
|
||||||
|
|
||||||
BOOST_FOREACH (const std::string &prop, m_filterFields) {
|
for (const std::string &prop: m_filterFields) {
|
||||||
// Be conservative and only ask for properties that we
|
// Be conservative and only ask for properties that we
|
||||||
// really know how to use. obexd also lists the bit field
|
// really know how to use. obexd also lists the bit field
|
||||||
// strings ("BIT01") but phones have been seen to reject
|
// strings ("BIT01") but phones have been seen to reject
|
||||||
|
@ -500,14 +471,15 @@ void PbapSession::initSession(const std::string &address, const std::string &for
|
||||||
// 3.0:^PHOTO = download in vCard 3.0 format, excluding PHOTO
|
// 3.0:^PHOTO = download in vCard 3.0 format, excluding PHOTO
|
||||||
// 2.1:PHOTO = download in vCard 2.1 format, only the PHOTO
|
// 2.1:PHOTO = download in vCard 2.1 format, only the PHOTO
|
||||||
|
|
||||||
std::string version;
|
const static std::regex re(R"del((?:(2\.1|3\.0):?)?(\^?)([-a-zA-Z,]*))del");
|
||||||
std::string tmp;
|
std::smatch match;
|
||||||
std::string properties;
|
if (!std::regex_match(format, match, re)) {
|
||||||
const pcrecpp::RE re("(?:(2\\.1|3\\.0):?)?(\\^?)([-a-zA-Z,]*)");
|
|
||||||
if (!re.FullMatch(format, &version, &tmp, &properties)) {
|
|
||||||
m_parent.throwError(SE_HERE, StringPrintf("invalid specification of PBAP vCard format (databaseFormat): %s",
|
m_parent.throwError(SE_HERE, StringPrintf("invalid specification of PBAP vCard format (databaseFormat): %s",
|
||||||
format.c_str()));
|
format.c_str()));
|
||||||
}
|
}
|
||||||
|
std::string version = match[1];
|
||||||
|
std::string tmp = match[2];
|
||||||
|
std::string properties = match[3];
|
||||||
char negated = tmp.c_str()[0];
|
char negated = tmp.c_str()[0];
|
||||||
if (version.empty()) {
|
if (version.empty()) {
|
||||||
// same default as in obexd
|
// same default as in obexd
|
||||||
|
@ -525,7 +497,7 @@ void PbapSession::initSession(const std::string &address, const std::string &for
|
||||||
params["Target"] = std::string("PBAP");
|
params["Target"] = std::string("PBAP");
|
||||||
|
|
||||||
std::string session;
|
std::string session;
|
||||||
GDBusCXX::DBusConnectionPtr conn = GDBusCXX::dbus_get_bus_connection("SESSION", NULL, true, NULL);
|
GDBusCXX::DBusConnectionPtr conn = GDBusCXX::dbus_get_bus_connection("SESSION", nullptr, true, nullptr);
|
||||||
|
|
||||||
// We must attempt to use the new interface(s), otherwise we won't know whether
|
// We must attempt to use the new interface(s), otherwise we won't know whether
|
||||||
// the daemon exists or can be started.
|
// the daemon exists or can be started.
|
||||||
|
@ -537,7 +509,7 @@ void PbapSession::initSession(const std::string &address, const std::string &for
|
||||||
try {
|
try {
|
||||||
SE_LOG_DEBUG(NULL, "trying to use bluez 5 obexd service %s", OBC_SERVICE_NEW5);
|
SE_LOG_DEBUG(NULL, "trying to use bluez 5 obexd service %s", OBC_SERVICE_NEW5);
|
||||||
session =
|
session =
|
||||||
GDBusCXX::DBusClientCall1<GDBusCXX::DBusObject_t>(*m_client, "CreateSession")(address, params);
|
GDBusCXX::DBusClientCall<GDBusCXX::DBusObject_t>(*m_client, "CreateSession")(address, params);
|
||||||
} catch (const std::exception &error) {
|
} catch (const std::exception &error) {
|
||||||
if (!strstr(error.what(), "org.freedesktop.DBus.Error.ServiceUnknown") &&
|
if (!strstr(error.what(), "org.freedesktop.DBus.Error.ServiceUnknown") &&
|
||||||
!strstr(error.what(), "org.freedesktop.DBus.Error.UnknownObject")) {
|
!strstr(error.what(), "org.freedesktop.DBus.Error.UnknownObject")) {
|
||||||
|
@ -556,7 +528,7 @@ void PbapSession::initSession(const std::string &address, const std::string &for
|
||||||
try {
|
try {
|
||||||
SE_LOG_DEBUG(NULL, "trying to use new obexd service %s", OBC_SERVICE_NEW);
|
SE_LOG_DEBUG(NULL, "trying to use new obexd service %s", OBC_SERVICE_NEW);
|
||||||
session =
|
session =
|
||||||
GDBusCXX::DBusClientCall1<GDBusCXX::DBusObject_t>(*m_client, "CreateSession")(address, params);
|
GDBusCXX::DBusClientCall<GDBusCXX::DBusObject_t>(*m_client, "CreateSession")(address, params);
|
||||||
} catch (const std::exception &error) {
|
} catch (const std::exception &error) {
|
||||||
if (!strstr(error.what(), "org.freedesktop.DBus.Error.ServiceUnknown")) {
|
if (!strstr(error.what(), "org.freedesktop.DBus.Error.ServiceUnknown")) {
|
||||||
throw;
|
throw;
|
||||||
|
@ -573,7 +545,7 @@ void PbapSession::initSession(const std::string &address, const std::string &for
|
||||||
m_client.reset(new GDBusCXX::DBusRemoteObject(conn, "/", OBC_CLIENT_INTERFACE,
|
m_client.reset(new GDBusCXX::DBusRemoteObject(conn, "/", OBC_CLIENT_INTERFACE,
|
||||||
OBC_SERVICE, true));
|
OBC_SERVICE, true));
|
||||||
params["Destination"] = std::string(address);
|
params["Destination"] = std::string(address);
|
||||||
session = GDBusCXX::DBusClientCall1<GDBusCXX::DBusObject_t>(*m_client, "CreateSession")(params);
|
session = GDBusCXX::DBusClientCall<GDBusCXX::DBusObject_t>(*m_client, "CreateSession")(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session.empty()) {
|
if (session.empty()) {
|
||||||
|
@ -598,7 +570,7 @@ void PbapSession::initSession(const std::string &address, const std::string &for
|
||||||
// pointer and ignore callback when the instance is already gone.
|
// pointer and ignore callback when the instance is already gone.
|
||||||
// Should not happen with signals (destructing the class unregisters
|
// Should not happen with signals (destructing the class unregisters
|
||||||
// the watch), but very well may happen in asynchronous method
|
// the watch), but very well may happen in asynchronous method
|
||||||
// calls. Therefore maintain m_self and show how to use it here.
|
// calls.
|
||||||
if (m_obexAPI == BLUEZ5) {
|
if (m_obexAPI == BLUEZ5) {
|
||||||
// Bluez 5
|
// Bluez 5
|
||||||
m_propChangedSignal.reset(new PropChangedSignal_t
|
m_propChangedSignal.reset(new PropChangedSignal_t
|
||||||
|
@ -607,7 +579,12 @@ void PbapSession::initSession(const std::string &address, const std::string &for
|
||||||
"org.freedesktop.DBus.Properties",
|
"org.freedesktop.DBus.Properties",
|
||||||
"PropertiesChanged",
|
"PropertiesChanged",
|
||||||
GDBusCXX::SignalFilter::SIGNAL_FILTER_PATH_PREFIX)));
|
GDBusCXX::SignalFilter::SIGNAL_FILTER_PATH_PREFIX)));
|
||||||
m_propChangedSignal->activate(boost::bind(&PbapSession::propChangedCb, m_self, _1, _2, _3, _4));
|
m_propChangedSignal->activate([self=weak_from_this()] (const GDBusCXX::Path_t &path, const std::string &interface, const Params &changed, const std::vector<std::string> &invalidated) {
|
||||||
|
auto lock = self.lock();
|
||||||
|
if (lock) {
|
||||||
|
lock->propChangedCb(path, interface, changed, invalidated);
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// obexd >= 0.47
|
// obexd >= 0.47
|
||||||
m_completeSignal.reset(new CompleteSignal_t
|
m_completeSignal.reset(new CompleteSignal_t
|
||||||
|
@ -616,16 +593,32 @@ void PbapSession::initSession(const std::string &address, const std::string &for
|
||||||
OBC_TRANSFER_INTERFACE_NEW,
|
OBC_TRANSFER_INTERFACE_NEW,
|
||||||
"Complete",
|
"Complete",
|
||||||
GDBusCXX::SignalFilter::SIGNAL_FILTER_PATH_PREFIX)));
|
GDBusCXX::SignalFilter::SIGNAL_FILTER_PATH_PREFIX)));
|
||||||
m_completeSignal->activate(boost::bind(&PbapSession::completeCb, m_self, _1));
|
m_completeSignal->activate([self=weak_from_this()] (const GDBusCXX::Path_t &path) {
|
||||||
|
auto lock = self.lock();
|
||||||
|
SE_LOG_DEBUG(NULL, "obexd transfer %s completed", path.c_str());
|
||||||
|
if (lock) {
|
||||||
|
lock->m_transfers[path] = Completion::now();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// same for error
|
// same for error
|
||||||
m_errorSignal.reset(new GDBusCXX::SignalWatch3<GDBusCXX::Path_t, std::string, std::string>
|
m_errorSignal.reset(new GDBusCXX::SignalWatch<GDBusCXX::Path_t, std::string, std::string>
|
||||||
(GDBusCXX::SignalFilter(m_client->getConnection(),
|
(GDBusCXX::SignalFilter(m_client->getConnection(),
|
||||||
session,
|
session,
|
||||||
OBC_TRANSFER_INTERFACE_NEW,
|
OBC_TRANSFER_INTERFACE_NEW,
|
||||||
"Error",
|
"Error",
|
||||||
GDBusCXX::SignalFilter::SIGNAL_FILTER_PATH_PREFIX)));
|
GDBusCXX::SignalFilter::SIGNAL_FILTER_PATH_PREFIX)));
|
||||||
m_errorSignal->activate(boost::bind(&PbapSession::errorCb, m_self, _1, _2, _3));
|
m_errorSignal->activate([self=weak_from_this()] (const GDBusCXX::Path_t &path, const std::string &error, const std::string &msg) {
|
||||||
|
auto lock = self.lock();
|
||||||
|
SE_LOG_DEBUG(NULL, "obexd transfer %s failed: %s %s",
|
||||||
|
path.c_str(), error.c_str(), msg.c_str());
|
||||||
|
if (lock) {
|
||||||
|
Completion &completion = lock->m_transfers[path];
|
||||||
|
completion.m_transferComplete = Timespec::monotonic();
|
||||||
|
completion.m_transferErrorCode = error;
|
||||||
|
completion.m_transferErrorMsg = msg;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// and property changes
|
// and property changes
|
||||||
m_propertyChangedSignal.reset(new PropertyChangedSignal_t(GDBusCXX::SignalFilter(m_client->getConnection(),
|
m_propertyChangedSignal.reset(new PropertyChangedSignal_t(GDBusCXX::SignalFilter(m_client->getConnection(),
|
||||||
|
@ -633,7 +626,12 @@ void PbapSession::initSession(const std::string &address, const std::string &for
|
||||||
OBC_TRANSFER_INTERFACE_NEW,
|
OBC_TRANSFER_INTERFACE_NEW,
|
||||||
"PropertyChanged",
|
"PropertyChanged",
|
||||||
GDBusCXX::SignalFilter::SIGNAL_FILTER_PATH_PREFIX)));
|
GDBusCXX::SignalFilter::SIGNAL_FILTER_PATH_PREFIX)));
|
||||||
m_propertyChangedSignal->activate(boost::bind(&PbapSession::propertyChangedCb, m_self, _1, _2, _3));
|
m_propertyChangedSignal->activate([self=weak_from_this()] (const GDBusCXX::Path_t &path, const std::string &interface , const boost::variant<int64_t> &value) {
|
||||||
|
auto lock = self.lock();
|
||||||
|
if (lock) {
|
||||||
|
lock->propertyChangedCb(path, interface, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// obexd < 0.47
|
// obexd < 0.47
|
||||||
|
@ -647,7 +645,7 @@ void PbapSession::initSession(const std::string &address, const std::string &for
|
||||||
SE_LOG_DEBUG(NULL, "PBAP session created: %s", m_session->getPath());
|
SE_LOG_DEBUG(NULL, "PBAP session created: %s", m_session->getPath());
|
||||||
|
|
||||||
// get filter list so that we can continue validating our format specifier
|
// get filter list so that we can continue validating our format specifier
|
||||||
m_filterFields = GDBusCXX::DBusClientCall1< Properties >(*m_session, "ListFilterFields")();
|
m_filterFields = GDBusCXX::DBusClientCall< Properties >(*m_session, "ListFilterFields")();
|
||||||
SE_LOG_DEBUG(NULL, "supported PBAP filter fields:\n %s",
|
SE_LOG_DEBUG(NULL, "supported PBAP filter fields:\n %s",
|
||||||
boost::join(m_filterFields, "\n ").c_str());
|
boost::join(m_filterFields, "\n ").c_str());
|
||||||
|
|
||||||
|
@ -658,15 +656,15 @@ void PbapSession::initSession(const std::string &address, const std::string &for
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate parameters and update filter
|
// validate parameters and update filter
|
||||||
BOOST_FOREACH (const std::string &prop, keywords) {
|
for (const std::string &prop: keywords) {
|
||||||
if (prop.empty()) {
|
if (prop.empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Properties::const_iterator entry =
|
auto entry =
|
||||||
std::find_if(m_filterFields.begin(),
|
std::find_if(m_filterFields.begin(),
|
||||||
m_filterFields.end(),
|
m_filterFields.end(),
|
||||||
boost::bind(&boost::iequals<std::string,std::string>, _1, prop, std::locale()));
|
[&prop] (const std::string &other) { return boost::iequals(other, prop, std::locale()); });
|
||||||
|
|
||||||
if (entry == m_filterFields.end()) {
|
if (entry == m_filterFields.end()) {
|
||||||
m_parent.throwError(SE_HERE, StringPrintf("invalid property name in PBAP vCard format specification (databaseFormat): %s",
|
m_parent.throwError(SE_HERE, StringPrintf("invalid property name in PBAP vCard format specification (databaseFormat): %s",
|
||||||
|
@ -680,14 +678,14 @@ void PbapSession::initSession(const std::string &address, const std::string &for
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GDBusCXX::DBusClientCall0(*m_session, "Select")(std::string("int"), std::string("PB"));
|
GDBusCXX::DBusClientCall<>(*m_session, "Select")(std::string("int"), std::string("PB"));
|
||||||
m_filter5["Format"] = version == "2.1" ? "vcard21" : "vcard30";
|
m_filter5["Format"] = version == "2.1" ? "vcard21" : "vcard30";
|
||||||
m_filter5["Fields"] = filter;
|
m_filter5["Fields"] = filter;
|
||||||
|
|
||||||
SE_LOG_DEBUG(NULL, "PBAP session initialized");
|
SE_LOG_DEBUG(NULL, "PBAP session initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<PullAll> PbapSession::startPullAll(const PullParams &pullParams)
|
std::shared_ptr<PullAll> PbapSession::startPullAll(const PullParams &pullParams)
|
||||||
{
|
{
|
||||||
resetTransfer();
|
resetTransfer();
|
||||||
blockOnFreeze();
|
blockOnFreeze();
|
||||||
|
@ -717,7 +715,7 @@ boost::shared_ptr<PullAll> PbapSession::startPullAll(const PullParams &pullParam
|
||||||
if (filter.empty()) {
|
if (filter.empty()) {
|
||||||
filter = supportedProperties();
|
filter = supportedProperties();
|
||||||
}
|
}
|
||||||
for (Properties::iterator it = filter.begin();
|
for (auto it = filter.begin();
|
||||||
it != filter.end();
|
it != filter.end();
|
||||||
++it) {
|
++it) {
|
||||||
if (*it == "PHOTO") {
|
if (*it == "PHOTO") {
|
||||||
|
@ -734,8 +732,8 @@ boost::shared_ptr<PullAll> PbapSession::startPullAll(const PullParams &pullParam
|
||||||
if (m_obexAPI == OBEXD_OLD ||
|
if (m_obexAPI == OBEXD_OLD ||
|
||||||
m_obexAPI == OBEXD_NEW) {
|
m_obexAPI == OBEXD_NEW) {
|
||||||
try {
|
try {
|
||||||
GDBusCXX::DBusClientCall0(*m_session, "SetFilter")(filter);
|
GDBusCXX::DBusClientCall<>(*m_session, "SetFilter")(filter);
|
||||||
GDBusCXX::DBusClientCall0(*m_session, "SetFormat")(format);
|
GDBusCXX::DBusClientCall<>(*m_session, "SetFormat")(format);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// Ignore failure, can happen with 0.48. Instead send filter together
|
// Ignore failure, can happen with 0.48. Instead send filter together
|
||||||
// with PullAll method call.
|
// with PullAll method call.
|
||||||
|
@ -744,7 +742,7 @@ boost::shared_ptr<PullAll> PbapSession::startPullAll(const PullParams &pullParam
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<PullAll> state(new PullAll);
|
auto state = std::make_shared<PullAll>();
|
||||||
state->m_pullParams = pullParams;
|
state->m_pullParams = pullParams;
|
||||||
state->m_contentStartIndex = 0;
|
state->m_contentStartIndex = 0;
|
||||||
state->m_currentContact = 0;
|
state->m_currentContact = 0;
|
||||||
|
@ -759,7 +757,7 @@ boost::shared_ptr<PullAll> PbapSession::startPullAll(const PullParams &pullParam
|
||||||
// Beware, this will lead to a "Complete" signal in obexd
|
// Beware, this will lead to a "Complete" signal in obexd
|
||||||
// 0.47. We need to be careful with looking at the right
|
// 0.47. We need to be careful with looking at the right
|
||||||
// transfer to determine whether PullAll completed.
|
// transfer to determine whether PullAll completed.
|
||||||
state->m_numContacts = GDBusCXX::DBusClientCall1<uint16_t>(*m_session, "GetSize")();
|
state->m_numContacts = GDBusCXX::DBusClientCall<uint16_t>(*m_session, "GetSize")();
|
||||||
SE_LOG_DEBUG(NULL, "Expecting %d contacts.", state->m_numContacts);
|
SE_LOG_DEBUG(NULL, "Expecting %d contacts.", state->m_numContacts);
|
||||||
|
|
||||||
state->m_tmpFile.create(TmpFile::FILE);
|
state->m_tmpFile.create(TmpFile::FILE);
|
||||||
|
@ -791,12 +789,12 @@ boost::shared_ptr<PullAll> PbapSession::startPullAll(const PullParams &pullParam
|
||||||
Bluez5PullAllResult tuple =
|
Bluez5PullAllResult tuple =
|
||||||
pullAllWithFiltersFallback ?
|
pullAllWithFiltersFallback ?
|
||||||
// 0.48
|
// 0.48
|
||||||
GDBusCXX::DBusClientCall1<std::pair<GDBusCXX::DBusObject_t, Params> >(*m_session, "PullAll")(state->m_tmpFile.filename(), currentFilter) :
|
GDBusCXX::DBusClientCall<std::pair<GDBusCXX::DBusObject_t, Params> >(*m_session, "PullAll")(state->m_tmpFile.filename(), currentFilter) :
|
||||||
m_obexAPI == OBEXD_NEW ?
|
m_obexAPI == OBEXD_NEW ?
|
||||||
// 0.47
|
// 0.47
|
||||||
GDBusCXX::DBusClientCall1<std::pair<GDBusCXX::DBusObject_t, Params> >(*m_session, "PullAll")(state->m_tmpFile.filename()) :
|
GDBusCXX::DBusClientCall<std::pair<GDBusCXX::DBusObject_t, Params> >(*m_session, "PullAll")(state->m_tmpFile.filename()) :
|
||||||
// 5.x
|
// 5.x
|
||||||
GDBusCXX::DBusClientCall2<GDBusCXX::DBusObject_t, Params>(*m_session, "PullAll")(state->m_tmpFile.filename(), currentFilter);
|
GDBusCXX::DBusClientCall<GDBusCXX::DBusObject_t, Params>(*m_session, "PullAll")(state->m_tmpFile.filename(), currentFilter);
|
||||||
const GDBusCXX::DBusObject_t &transfer = tuple.first;
|
const GDBusCXX::DBusObject_t &transfer = tuple.first;
|
||||||
const Params &properties = tuple.second;
|
const Params &properties = tuple.second;
|
||||||
m_currentTransfer = transfer;
|
m_currentTransfer = transfer;
|
||||||
|
@ -812,7 +810,7 @@ boost::shared_ptr<PullAll> PbapSession::startPullAll(const PullParams &pullParam
|
||||||
// and the Synthesis engine will ignore the ID (src/sysync/binfileimplds.cpp:
|
// and the Synthesis engine will ignore the ID (src/sysync/binfileimplds.cpp:
|
||||||
// "Record does not exist any more in database%s -> ignore").
|
// "Record does not exist any more in database%s -> ignore").
|
||||||
state->m_tmpFileOffset = 0;
|
state->m_tmpFileOffset = 0;
|
||||||
state->m_session = m_self.lock();
|
state->m_session = shared_from_this();
|
||||||
state->m_filter = currentFilter;
|
state->m_filter = currentFilter;
|
||||||
} else {
|
} else {
|
||||||
// < 0.47
|
// < 0.47
|
||||||
|
@ -823,28 +821,66 @@ boost::shared_ptr<PullAll> PbapSession::startPullAll(const PullParams &pullParam
|
||||||
// of obex-client < 0.47. Not sure what we should do about
|
// of obex-client < 0.47. Not sure what we should do about
|
||||||
// this: disable incremental sync for old obex-client? Reject
|
// this: disable incremental sync for old obex-client? Reject
|
||||||
// it? Catch the error and add a better exlanation?
|
// it? Catch the error and add a better exlanation?
|
||||||
GDBusCXX::DBusClientCall1<std::string> pullall(*m_session, "PullAll");
|
GDBusCXX::DBusClientCall<std::string> pullall(*m_session, "PullAll");
|
||||||
state->m_buffer = pullall();
|
state->m_buffer = pullall();
|
||||||
state->addVCards(0, state->m_buffer);
|
state->addVCards(0, state->m_buffer, true);
|
||||||
state->m_numContacts = state->m_content.size();
|
state->m_numContacts = state->m_content.size();
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *PullAll::addVCards(int startIndex, const pcrecpp::StringPiece &vcards)
|
const char *findLine(const StringPiece &hay, const StringPiece &needle, bool eof)
|
||||||
{
|
{
|
||||||
pcrecpp::StringPiece vcarddata;
|
const char *current = hay.begin();
|
||||||
pcrecpp::StringPiece tmp = vcards;
|
const char *end = hay.end();
|
||||||
int count = startIndex;
|
size_t size = needle.size();
|
||||||
pcrecpp::RE re("[\\r\\n]*(^BEGIN:VCARD.*?^END:VCARD)",
|
while (current < end) {
|
||||||
pcrecpp::RE_Options().set_dotall(true).set_multiline(true));
|
// Skip line break(s).
|
||||||
while (re.Consume(&tmp, &vcarddata)) {
|
while (current < end && (*current == '\n' || *current == '\r')) {
|
||||||
m_content[count] = vcarddata;
|
current++;
|
||||||
++count;
|
}
|
||||||
|
const char *next = current + size;
|
||||||
|
if (next <= end &&
|
||||||
|
!memcmp(current, needle.begin(), size) &&
|
||||||
|
((eof && next == end) ||
|
||||||
|
(next + 1 < end && (*next == '\n' || *next == '\r')))) {
|
||||||
|
// Found a matching line.
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
// Skip line.
|
||||||
|
while (current < end && *current != '\n' && *current != '\r') {
|
||||||
|
current++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *PullAll::addVCards(int startIndex, const StringPiece &vcards, bool eof)
|
||||||
|
{
|
||||||
|
const char *current = vcards.begin();
|
||||||
|
const char *end = vcards.end();
|
||||||
|
const static StringPiece BEGIN_VCARD("BEGIN:VCARD");
|
||||||
|
const static StringPiece END_VCARD("END:VCARD");
|
||||||
|
int count = startIndex;
|
||||||
|
while (true) {
|
||||||
|
StringPiece remaining(current, end - current);
|
||||||
|
const char *begin_vcard = findLine(remaining, BEGIN_VCARD, eof);
|
||||||
|
if (begin_vcard) {
|
||||||
|
const char *end_vcard = findLine(StringPiece(remaining), END_VCARD, eof);
|
||||||
|
if (end_vcard) {
|
||||||
|
const char *next = end_vcard + END_VCARD.size();
|
||||||
|
StringPiece vcarddata(begin_vcard, next - begin_vcard);
|
||||||
|
m_content[count] = vcarddata;
|
||||||
|
++count;
|
||||||
|
current = next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No further vcard found, try again when we have more data.
|
||||||
|
break;
|
||||||
|
}
|
||||||
SE_LOG_DEBUG(NULL, "PBAP content parsed: %d contacts starting at ID %d", count - startIndex, startIndex);
|
SE_LOG_DEBUG(NULL, "PBAP content parsed: %d contacts starting at ID %d", count - startIndex, startIndex);
|
||||||
return tmp.data();
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PbapSession::continuePullAll(PullAll &state)
|
void PbapSession::continuePullAll(PullAll &state)
|
||||||
|
@ -855,9 +891,9 @@ void PbapSession::continuePullAll(PullAll &state)
|
||||||
|
|
||||||
Bluez5PullAllResult tuple =
|
Bluez5PullAllResult tuple =
|
||||||
m_obexAPI == BLUEZ5 ?
|
m_obexAPI == BLUEZ5 ?
|
||||||
GDBusCXX::DBusClientCall2<GDBusCXX::DBusObject_t, Params>(*m_session, "PullAll")(state.m_tmpFile.filename(), state.m_filter) :
|
GDBusCXX::DBusClientCall<GDBusCXX::DBusObject_t, Params>(*m_session, "PullAll")(state.m_tmpFile.filename(), state.m_filter) :
|
||||||
// must be 0.48
|
// must be 0.48
|
||||||
GDBusCXX::DBusClientCall1<std::pair<GDBusCXX::DBusObject_t, Params> >(*m_session, "PullAll")(state.m_tmpFile.filename(), state.m_filter);
|
GDBusCXX::DBusClientCall<std::pair<GDBusCXX::DBusObject_t, Params> >(*m_session, "PullAll")(state.m_tmpFile.filename(), state.m_filter);
|
||||||
|
|
||||||
const GDBusCXX::DBusObject_t &transfer = tuple.first;
|
const GDBusCXX::DBusObject_t &transfer = tuple.first;
|
||||||
const Params &properties = tuple.second;
|
const Params &properties = tuple.second;
|
||||||
|
@ -871,7 +907,7 @@ void PbapSession::continuePullAll(PullAll &state)
|
||||||
|
|
||||||
void PbapSession::checkForError()
|
void PbapSession::checkForError()
|
||||||
{
|
{
|
||||||
Transfers::const_iterator it = m_transfers.find(m_currentTransfer);
|
auto it = m_transfers.find(m_currentTransfer);
|
||||||
if (it != m_transfers.end()) {
|
if (it != m_transfers.end()) {
|
||||||
if (!it->second.m_transferErrorCode.empty()) {
|
if (!it->second.m_transferErrorCode.empty()) {
|
||||||
m_parent.throwError(SE_HERE, StringPrintf("%s: %s",
|
m_parent.throwError(SE_HERE, StringPrintf("%s: %s",
|
||||||
|
@ -884,7 +920,7 @@ void PbapSession::checkForError()
|
||||||
Timespec PbapSession::transferComplete() const
|
Timespec PbapSession::transferComplete() const
|
||||||
{
|
{
|
||||||
Timespec res;
|
Timespec res;
|
||||||
Transfers::const_iterator it = m_transfers.find(m_currentTransfer);
|
auto it = m_transfers.find(m_currentTransfer);
|
||||||
if (it != m_transfers.end()) {
|
if (it != m_transfers.end()) {
|
||||||
res = it->second.m_transferComplete;
|
res = it->second.m_transferComplete;
|
||||||
}
|
}
|
||||||
|
@ -906,7 +942,7 @@ std::string PullAll::getNextID()
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PullAll::getContact(const char *id, pcrecpp::StringPiece &vcard)
|
bool PullAll::getContact(const char *id, StringPiece &vcard)
|
||||||
{
|
{
|
||||||
int contactNumber = atoi(id);
|
int contactNumber = atoi(id);
|
||||||
SE_LOG_DEBUG(NULL, "get PBAP contact ID %s", id);
|
SE_LOG_DEBUG(NULL, "get PBAP contact ID %s", id);
|
||||||
|
@ -932,7 +968,7 @@ bool PullAll::getContact(const char *id, pcrecpp::StringPiece &vcard)
|
||||||
// now).
|
// now).
|
||||||
while (!m_session->transferComplete() && m_tmpFile.moreData() < 128 * 1024) {
|
while (!m_session->transferComplete() && m_tmpFile.moreData() < 128 * 1024) {
|
||||||
s.checkForNormal();
|
s.checkForNormal();
|
||||||
g_main_context_iteration(NULL, true);
|
g_main_context_iteration(nullptr, true);
|
||||||
}
|
}
|
||||||
m_session->checkForError();
|
m_session->checkForError();
|
||||||
|
|
||||||
|
@ -940,13 +976,13 @@ bool PullAll::getContact(const char *id, pcrecpp::StringPiece &vcard)
|
||||||
if (m_tmpFile.moreData()) {
|
if (m_tmpFile.moreData()) {
|
||||||
// Remap. This shifts all addresses already stored in
|
// Remap. This shifts all addresses already stored in
|
||||||
// m_content, so beware and update those.
|
// m_content, so beware and update those.
|
||||||
pcrecpp::StringPiece oldMem = m_tmpFile.stringPiece();
|
StringPiece oldMem = m_tmpFile.stringPiece();
|
||||||
m_tmpFile.unmap();
|
m_tmpFile.unmap();
|
||||||
m_tmpFile.map();
|
m_tmpFile.map();
|
||||||
pcrecpp::StringPiece newMem = m_tmpFile.stringPiece();
|
StringPiece newMem = m_tmpFile.stringPiece();
|
||||||
ssize_t delta = newMem.data() - oldMem.data();
|
ssize_t delta = newMem.data() - oldMem.data();
|
||||||
BOOST_FOREACH (Content::value_type &entry, m_content) {
|
for (auto &entry: m_content) {
|
||||||
pcrecpp::StringPiece &vcard = entry.second;
|
StringPiece &vcard = entry.second;
|
||||||
vcard.set(vcard.data() + delta, vcard.size());
|
vcard.set(vcard.data() + delta, vcard.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -955,15 +991,15 @@ bool PullAll::getContact(const char *id, pcrecpp::StringPiece &vcard)
|
||||||
m_tmpFile.remove();
|
m_tmpFile.remove();
|
||||||
|
|
||||||
// Continue parsing where we stopped before.
|
// Continue parsing where we stopped before.
|
||||||
pcrecpp::StringPiece next(newMem.data() + m_tmpFileOffset,
|
StringPiece next(newMem.data() + m_tmpFileOffset,
|
||||||
newMem.size() - m_tmpFileOffset);
|
newMem.size() - m_tmpFileOffset);
|
||||||
const char *end = addVCards(m_contentStartIndex + m_content.size(), next);
|
const char *end = addVCards(m_contentStartIndex + m_content.size(), next, completed);
|
||||||
size_t newTmpFileOffset = end - newMem.data();
|
size_t newTmpFileOffset = end - newMem.data();
|
||||||
SE_LOG_DEBUG(NULL, "PBAP content parsed: %ld out of %d (total), %d out of %d (last update)",
|
SE_LOG_DEBUG(NULL, "PBAP content parsed: %ld out of %ld (total), %d out of %ld (last update)",
|
||||||
(long)newTmpFileOffset,
|
(long)newTmpFileOffset,
|
||||||
newMem.size(),
|
(long)newMem.size(),
|
||||||
(int)(end - next.data()),
|
(int)(end - next.data()),
|
||||||
next.size());
|
(long)next.size());
|
||||||
m_tmpFileOffset = newTmpFileOffset;
|
m_tmpFileOffset = newTmpFileOffset;
|
||||||
|
|
||||||
if (completed) {
|
if (completed) {
|
||||||
|
@ -1039,7 +1075,7 @@ bool PullAll::getContact(const char *id, pcrecpp::StringPiece &vcard)
|
||||||
|
|
||||||
void PbapSession::shutdown(void)
|
void PbapSession::shutdown(void)
|
||||||
{
|
{
|
||||||
GDBusCXX::DBusClientCall0 removeSession(*m_client, "RemoveSession");
|
GDBusCXX::DBusClientCall<> removeSession(*m_client, "RemoveSession");
|
||||||
|
|
||||||
// always clear pointer, even if method call fails
|
// always clear pointer, even if method call fails
|
||||||
GDBusCXX::DBusObject_t path(m_session->getPath());
|
GDBusCXX::DBusObject_t path(m_session->getPath());
|
||||||
|
@ -1075,9 +1111,9 @@ void PbapSession::setFreeze(bool freeze)
|
||||||
true);
|
true);
|
||||||
try {
|
try {
|
||||||
if (freeze) {
|
if (freeze) {
|
||||||
GDBusCXX::DBusClientCall0(transfer, "Suspend")();
|
GDBusCXX::DBusClientCall<>(transfer, "Suspend")();
|
||||||
} else {
|
} else {
|
||||||
GDBusCXX::DBusClientCall0(transfer, "Resume")();
|
GDBusCXX::DBusClientCall<>(transfer, "Resume")();
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
std::string explanation;
|
std::string explanation;
|
||||||
|
@ -1101,7 +1137,7 @@ void PbapSession::setFreeze(bool freeze)
|
||||||
SE_LOG_DEBUG(NULL, "must retry Suspend(), got error at the moment: %s", explanation.c_str());
|
SE_LOG_DEBUG(NULL, "must retry Suspend(), got error at the moment: %s", explanation.c_str());
|
||||||
} else {
|
} else {
|
||||||
// Have to abort.
|
// Have to abort.
|
||||||
GDBusCXX::DBusClientCall0(transfer, "Cancel")();
|
GDBusCXX::DBusClientCall<>(transfer, "Cancel")();
|
||||||
|
|
||||||
// Bluez does not change the transfer status when cancelling it,
|
// Bluez does not change the transfer status when cancelling it,
|
||||||
// so our propChangedCb() doesn't get called. We need to record
|
// so our propChangedCb() doesn't get called. We need to record
|
||||||
|
@ -1127,7 +1163,7 @@ void PbapSession::blockOnFreeze()
|
||||||
SuspendFlags &s = SuspendFlags::getSuspendFlags();
|
SuspendFlags &s = SuspendFlags::getSuspendFlags();
|
||||||
while (m_frozen) {
|
while (m_frozen) {
|
||||||
s.checkForNormal();
|
s.checkForNormal();
|
||||||
g_main_context_iteration(NULL, true);
|
g_main_context_iteration(nullptr, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1135,12 +1171,17 @@ PbapSyncSource::PbapSyncSource(const SyncSourceParams ¶ms) :
|
||||||
SyncSource(params)
|
SyncSource(params)
|
||||||
{
|
{
|
||||||
SyncSourceSession::init(m_operations);
|
SyncSourceSession::init(m_operations);
|
||||||
m_operations.m_readNextItem = boost::bind(&PbapSyncSource::readNextItem, this, _1, _2, _3);
|
m_operations.m_readNextItem = [this] (sysync::ItemID aID,
|
||||||
m_operations.m_readItemAsKey = boost::bind(&PbapSyncSource::readItemAsKey,
|
sysync::sInt32 *aStatus,
|
||||||
this, _1, _2);
|
bool aFirst) {
|
||||||
m_session = PbapSession::create(*this);
|
return readNextItem(aID, aStatus, aFirst);
|
||||||
|
};
|
||||||
|
m_operations.m_readItemAsKey = [this] (sysync::cItemID aID, sysync::KeyH aItemKey) {
|
||||||
|
return readItemAsKey(aID, aItemKey);
|
||||||
|
};
|
||||||
|
m_session = make_weak_shared::make<PbapSession>(*this);
|
||||||
const char *PBAPSyncMode = getenv("SYNCEVOLUTION_PBAP_SYNC");
|
const char *PBAPSyncMode = getenv("SYNCEVOLUTION_PBAP_SYNC");
|
||||||
m_PBAPSyncMode = !PBAPSyncMode ? PBAP_SYNC_NORMAL :
|
m_PBAPSyncMode = !PBAPSyncMode ? PBAP_SYNC_INCREMENTAL :
|
||||||
boost::iequals(PBAPSyncMode, "incremental") ? PBAP_SYNC_INCREMENTAL :
|
boost::iequals(PBAPSyncMode, "incremental") ? PBAP_SYNC_INCREMENTAL :
|
||||||
boost::iequals(PBAPSyncMode, "text") ? PBAP_SYNC_TEXT :
|
boost::iequals(PBAPSyncMode, "text") ? PBAP_SYNC_TEXT :
|
||||||
boost::iequals(PBAPSyncMode, "all") ? PBAP_SYNC_NORMAL :
|
boost::iequals(PBAPSyncMode, "all") ? PBAP_SYNC_NORMAL :
|
||||||
|
@ -1273,13 +1314,13 @@ sysync::TSyError PbapSyncSource::readNextItem(sysync::ItemID aID,
|
||||||
PULL_AS_CONFIGURED;
|
PULL_AS_CONFIGURED;
|
||||||
|
|
||||||
const char *env;
|
const char *env;
|
||||||
if ((env = getenv("SYNCEVOLUTION_PBAP_CHUNK_TRANSFER_TIME")) != NULL) {
|
if ((env = getenv("SYNCEVOLUTION_PBAP_CHUNK_TRANSFER_TIME")) != nullptr) {
|
||||||
params.m_timePerChunk = atof(env);
|
params.m_timePerChunk = atof(env);
|
||||||
} else {
|
} else {
|
||||||
params.m_timePerChunk = 30;
|
params.m_timePerChunk = 30;
|
||||||
}
|
}
|
||||||
static const double LAMBDA_DEF = 0.1;
|
static const double LAMBDA_DEF = 0.1;
|
||||||
if ((env = getenv("SYNCEVOLUTION_PBAP_CHUNK_TIME_LAMBDA")) != NULL) {
|
if ((env = getenv("SYNCEVOLUTION_PBAP_CHUNK_TIME_LAMBDA")) != nullptr) {
|
||||||
params.m_timeLambda = atof(env);
|
params.m_timeLambda = atof(env);
|
||||||
} else {
|
} else {
|
||||||
params.m_timeLambda = LAMBDA_DEF;
|
params.m_timeLambda = LAMBDA_DEF;
|
||||||
|
@ -1288,13 +1329,13 @@ sysync::TSyError PbapSyncSource::readNextItem(sysync::ItemID aID,
|
||||||
params.m_timeLambda > 1) {
|
params.m_timeLambda > 1) {
|
||||||
params.m_timeLambda = LAMBDA_DEF;
|
params.m_timeLambda = LAMBDA_DEF;
|
||||||
}
|
}
|
||||||
if ((env = getenv("SYNCEVOLUTION_PBAP_CHUNK_MAX_COUNT_PHOTO")) != NULL) {
|
if ((env = getenv("SYNCEVOLUTION_PBAP_CHUNK_MAX_COUNT_PHOTO")) != nullptr) {
|
||||||
params.m_startMaxCount[true] = atoi(env);
|
params.m_startMaxCount[true] = atoi(env);
|
||||||
}
|
}
|
||||||
if ((env = getenv("SYNCEVOLUTION_PBAP_CHUNK_MAX_COUNT_NO_PHOTO")) != NULL) {
|
if ((env = getenv("SYNCEVOLUTION_PBAP_CHUNK_MAX_COUNT_NO_PHOTO")) != nullptr) {
|
||||||
params.m_startMaxCount[false] = atoi(env);
|
params.m_startMaxCount[false] = atoi(env);
|
||||||
}
|
}
|
||||||
if ((env = getenv("SYNCEVOLUTION_PBAP_CHUNK_OFFSET")) != NULL) {
|
if ((env = getenv("SYNCEVOLUTION_PBAP_CHUNK_OFFSET")) != nullptr) {
|
||||||
params.m_startOffset = atoi(env);
|
params.m_startOffset = atoi(env);
|
||||||
} else {
|
} else {
|
||||||
unsigned int seed = (unsigned int)Timespec::system().seconds();
|
unsigned int seed = (unsigned int)Timespec::system().seconds();
|
||||||
|
@ -1319,7 +1360,7 @@ sysync::TSyError PbapSyncSource::readNextItem(sysync::ItemID aID,
|
||||||
} else {
|
} else {
|
||||||
*aStatus = sysync::ReadNextItem_Unchanged;
|
*aStatus = sysync::ReadNextItem_Unchanged;
|
||||||
aID->item = StrAlloc(id.c_str());
|
aID->item = StrAlloc(id.c_str());
|
||||||
aID->parent = NULL;
|
aID->parent = nullptr;
|
||||||
m_hadContacts = true;
|
m_hadContacts = true;
|
||||||
}
|
}
|
||||||
return sysync::LOCERR_OK;
|
return sysync::LOCERR_OK;
|
||||||
|
@ -1330,7 +1371,7 @@ sysync::TSyError PbapSyncSource::readItemAsKey(sysync::cItemID aID, sysync::KeyH
|
||||||
if (!m_pullAll) {
|
if (!m_pullAll) {
|
||||||
throwError(SE_HERE, "logic error: readItemAsKey() without preceeding readNextItem()");
|
throwError(SE_HERE, "logic error: readItemAsKey() without preceeding readNextItem()");
|
||||||
}
|
}
|
||||||
pcrecpp::StringPiece vcard;
|
StringPiece vcard;
|
||||||
if (m_pullAll->getContact(aID->item, vcard)) {
|
if (m_pullAll->getContact(aID->item, vcard)) {
|
||||||
return getSynthesisAPI()->setValue(aItemKey, "itemdata", vcard.data(), vcard.size());
|
return getSynthesisAPI()->setValue(aItemKey, "itemdata", vcard.data(), vcard.size());
|
||||||
} else {
|
} else {
|
||||||
|
@ -1349,7 +1390,7 @@ void PbapSyncSource::readItemRaw(const std::string &luid, std::string &item)
|
||||||
if (!m_pullAll) {
|
if (!m_pullAll) {
|
||||||
throwError(SE_HERE, "logic error: readItemRaw() without preceeding readNextItem()");
|
throwError(SE_HERE, "logic error: readItemRaw() without preceeding readNextItem()");
|
||||||
}
|
}
|
||||||
pcrecpp::StringPiece vcard;
|
StringPiece vcard;
|
||||||
if (m_pullAll->getContact(luid.c_str(), vcard)) {
|
if (m_pullAll->getContact(luid.c_str(), vcard)) {
|
||||||
item.assign(vcard.data(), vcard.size());
|
item.assign(vcard.data(), vcard.size());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -28,8 +28,6 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
#include <pcrecpp.h>
|
|
||||||
|
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
#include <syncevo/TmpFile.h>
|
#include <syncevo/TmpFile.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
@ -65,8 +63,8 @@ class PbapSyncSource : virtual public SyncSource, virtual public SyncSourceSessi
|
||||||
virtual void readItemRaw(const std::string &luid, std::string &item);
|
virtual void readItemRaw(const std::string &luid, std::string &item);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::shared_ptr<PbapSession> m_session;
|
std::shared_ptr<PbapSession> m_session;
|
||||||
boost::shared_ptr<PullAll> m_pullAll;
|
std::shared_ptr<PullAll> m_pullAll;
|
||||||
enum PBAPSyncMode {
|
enum PBAPSyncMode {
|
||||||
PBAP_SYNC_NORMAL, ///< Read contact data according to filter.
|
PBAP_SYNC_NORMAL, ///< Read contact data according to filter.
|
||||||
PBAP_SYNC_TEXT, ///< Sync without reading photo data from phone and keeping local photos instead.
|
PBAP_SYNC_TEXT, ///< Sync without reading photo data from phone and keeping local photos instead.
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
|
||||||
static SyncSource *createSource(const SyncSourceParams ¶ms)
|
static std::unique_ptr<SyncSource> createSource(const SyncSourceParams ¶ms)
|
||||||
{
|
{
|
||||||
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
||||||
// The string returned by getSourceType() is always the one
|
// The string returned by getSourceType() is always the one
|
||||||
|
@ -35,16 +35,16 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
#ifndef ENABLE_PBAP
|
#ifndef ENABLE_PBAP
|
||||||
// tell SyncEvolution if the user wanted to use a disabled sync source,
|
// tell SyncEvolution if the user wanted to use a disabled sync source,
|
||||||
// otherwise let it continue searching
|
// otherwise let it continue searching
|
||||||
return isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
|
return isMe ? RegisterSyncSource::InactiveSource(params) : nullptr;
|
||||||
#else
|
#else
|
||||||
// Also recognize one of the standard types?
|
// Also recognize one of the standard types?
|
||||||
// Not in the PbapSyncSource!
|
// Not in the PbapSyncSource!
|
||||||
bool maybeMe = false /* sourceType.m_backend == "addressbook" */;
|
bool maybeMe = false /* sourceType.m_backend == "addressbook" */;
|
||||||
|
|
||||||
if (isMe || maybeMe) {
|
if (isMe || maybeMe) {
|
||||||
return new PbapSyncSource(params);
|
return std::make_unique<PbapSyncSource>(params);
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ src_backends_pbap_src = \
|
||||||
src/backends/pbap/PbapSyncSource.cpp
|
src/backends/pbap/PbapSyncSource.cpp
|
||||||
|
|
||||||
src_backends_pbap_syncpbap_la_SOURCES = $(src_backends_pbap_src)
|
src_backends_pbap_syncpbap_la_SOURCES = $(src_backends_pbap_src)
|
||||||
src_backends_pbap_syncpbap_la_LIBADD = $(PBAP_LIBS) $(PCRECPP_LIBS) $(SYNCEVOLUTION_LIBS) $(DBUS_LIBS) $(gdbus_build_dir)/libgdbussyncevo.la
|
src_backends_pbap_syncpbap_la_LIBADD = $(PBAP_LIBS) $(SYNCEVOLUTION_LIBS) $(DBUS_LIBS) $(gdbus_build_dir)/libgdbussyncevo.la
|
||||||
src_backends_pbap_syncpbap_la_LDFLAGS = -module -avoid-version $(DBUS_LIBS)
|
src_backends_pbap_syncpbap_la_LDFLAGS = -module -avoid-version $(DBUS_LIBS)
|
||||||
src_backends_pbap_syncpbap_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) $(SYNCEVO_WFLAGS) $(DBUS_CFLAGS)
|
src_backends_pbap_syncpbap_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) $(SYNCEVO_WFLAGS) $(DBUS_CFLAGS)
|
||||||
src_backends_pbap_syncpbap_la_CPPFLAGS = $(SYNCEVOLUTION_CFLAGS) -I$(gdbus_dir) -I$(top_srcdir)/test $(BACKEND_CPPFLAGS)
|
src_backends_pbap_syncpbap_la_CPPFLAGS = $(SYNCEVOLUTION_CFLAGS) -I$(gdbus_dir) -I$(top_srcdir)/test $(BACKEND_CPPFLAGS)
|
||||||
|
|
|
@ -154,7 +154,7 @@ public:
|
||||||
QStringList content;
|
QStringList content;
|
||||||
content << detail.definitionName(); // <detail>
|
content << detail.definitionName(); // <detail>
|
||||||
QVariantMap fields = detail.variantValues();
|
QVariantMap fields = detail.variantValues();
|
||||||
for (QVariantMap::const_iterator entry = fields.begin();
|
for (auto entry = fields.begin();
|
||||||
entry != fields.end();
|
entry != fields.end();
|
||||||
++entry) {
|
++entry) {
|
||||||
const QString &fieldName = entry.key();
|
const QString &fieldName = entry.key();
|
||||||
|
@ -198,7 +198,7 @@ public:
|
||||||
#else
|
#else
|
||||||
StringEscape escape('|', "^");
|
StringEscape escape('|', "^");
|
||||||
std::list<std::string> strings;
|
std::list<std::string> strings;
|
||||||
BOOST_FOREACH(const QString &str, content) {
|
for (const QString &str: content) {
|
||||||
strings.push_back(escape.escape(string(str.toUtf8().constData())));
|
strings.push_back(escape.escape(string(str.toUtf8().constData())));
|
||||||
}
|
}
|
||||||
prop.setValue(QVariant(QString::fromUtf8(boost::join(strings, "^").c_str())));
|
prop.setValue(QVariant(QString::fromUtf8(boost::join(strings, "^").c_str())));
|
||||||
|
@ -237,7 +237,7 @@ public:
|
||||||
// detail name available?
|
// detail name available?
|
||||||
if (content.size() > 0) {
|
if (content.size() > 0) {
|
||||||
const QString &detailName = content[0];
|
const QString &detailName = content[0];
|
||||||
QMap<QString, QContactDetailDefinition>::const_iterator it = m_details.constFind(detailName);
|
auto it = m_details.constFind(detailName);
|
||||||
// detail still exists?
|
// detail still exists?
|
||||||
if (it != m_details.constEnd()) {
|
if (it != m_details.constEnd()) {
|
||||||
const QContactDetailDefinition &definition = *it;
|
const QContactDetailDefinition &definition = *it;
|
||||||
|
@ -273,9 +273,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip fields which are (no longer) valid, have wrong type or wrong value
|
// skip fields which are (no longer) valid, have wrong type or wrong value
|
||||||
QMap<QString, QContactDetailFieldDefinition> fields = definition.fields();
|
auto fields = definition.fields();
|
||||||
QMap<QString, QContactDetailFieldDefinition>::const_iterator it2 =
|
auto it2 = fields.constFind(fieldName);
|
||||||
fields.constFind(fieldName);
|
|
||||||
if (it2 != fields.constEnd()) {
|
if (it2 != fields.constEnd()) {
|
||||||
if (it2->dataType() == value.type()) {
|
if (it2->dataType() == value.type()) {
|
||||||
QVariantList allowed = it2->allowableValues();
|
QVariantList allowed = it2->allowableValues();
|
||||||
|
@ -376,7 +375,7 @@ public:
|
||||||
QtContactsSource::QtContactsSource(const SyncSourceParams ¶ms) :
|
QtContactsSource::QtContactsSource(const SyncSourceParams ¶ms) :
|
||||||
TrackingSyncSource(params)
|
TrackingSyncSource(params)
|
||||||
{
|
{
|
||||||
m_data = NULL;
|
m_data = nullptr;
|
||||||
SyncSourceLogging::init(InitList<std::string>("N_FIRST") + "N_MIDDLE" + "N_LAST",
|
SyncSourceLogging::init(InitList<std::string>("N_FIRST") + "N_MIDDLE" + "N_LAST",
|
||||||
" ",
|
" ",
|
||||||
m_operations);
|
m_operations);
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
|
||||||
static SyncSource *createSource(const SyncSourceParams ¶ms)
|
static std::unique_ptr<SyncSource> createSource(const SyncSourceParams ¶ms)
|
||||||
{
|
{
|
||||||
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
|
||||||
bool isMe = sourceType.m_backend == "QtContacts";
|
bool isMe = sourceType.m_backend == "QtContacts";
|
||||||
|
@ -44,10 +44,10 @@ static SyncSource *createSource(const SyncSourceParams ¶ms)
|
||||||
#ifdef ENABLE_QTCONTACTS
|
#ifdef ENABLE_QTCONTACTS
|
||||||
true ? new QtContactsSource(params) :
|
true ? new QtContactsSource(params) :
|
||||||
#endif
|
#endif
|
||||||
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
|
isMe ? RegisterSyncSource::InactiveSource(params) : nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterSyncSource registerMe("QtContacts",
|
static RegisterSyncSource registerMe("QtContacts",
|
||||||
|
@ -76,9 +76,9 @@ class QtContactsSourceUnitTest : public CppUnit::TestFixture {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void testInstantiate() {
|
void testInstantiate() {
|
||||||
boost::shared_ptr<SyncSource> source;
|
std::unique_ptr<SyncSource> source;
|
||||||
source.reset(SyncSource::createTestingSource("qtcontacts", "qtcontacts:text/vcard:3.0", true));
|
source = SyncSource::createTestingSource("qtcontacts", "qtcontacts:text/vcard:3.0", true);
|
||||||
source.reset(SyncSource::createTestingSource("qtcontacts", "QtContacts", true));
|
source = SyncSource::createTestingSource("qtcontacts", "QtContacts", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testHandler() {
|
void testHandler() {
|
||||||
|
|
|
@ -38,9 +38,8 @@
|
||||||
|
|
||||||
#include <syncevo/GLibSupport.h>
|
#include <syncevo/GLibSupport.h>
|
||||||
#include <syncevo/GVariantSupport.h>
|
#include <syncevo/GVariantSupport.h>
|
||||||
#include <pcrecpp.h>
|
|
||||||
|
|
||||||
#include <boost/lambda/core.hpp>
|
#include <regex>
|
||||||
|
|
||||||
SE_GOBJECT_TYPE(SignonAuthService)
|
SE_GOBJECT_TYPE(SignonAuthService)
|
||||||
SE_GOBJECT_TYPE(SignonAuthSession)
|
SE_GOBJECT_TYPE(SignonAuthSession)
|
||||||
|
@ -111,8 +110,8 @@ public:
|
||||||
SE_THROW("Username or password missing");
|
SE_THROW("Username or password missing");
|
||||||
}
|
}
|
||||||
Credentials credentials;
|
Credentials credentials;
|
||||||
credentials.m_username = g_variant_get_string(usernameVar, NULL);
|
credentials.m_username = g_variant_get_string(usernameVar, nullptr);
|
||||||
credentials.m_password = g_variant_get_string(passwordVar, NULL);
|
credentials.m_password = g_variant_get_string(passwordVar, nullptr);
|
||||||
if (credentials.m_password.empty()) {
|
if (credentials.m_password.empty()) {
|
||||||
SE_THROW("Got an empty password");
|
SE_THROW("Got an empty password");
|
||||||
} else if (m_invalidateCache &&
|
} else if (m_invalidateCache &&
|
||||||
|
@ -145,7 +144,7 @@ public:
|
||||||
if (!tokenVar) {
|
if (!tokenVar) {
|
||||||
SE_THROW("no AccessToken in OAuth2 response");
|
SE_THROW("no AccessToken in OAuth2 response");
|
||||||
}
|
}
|
||||||
std::string newToken = g_variant_get_string(tokenVar, NULL);
|
std::string newToken = g_variant_get_string(tokenVar, nullptr);
|
||||||
if (newToken.empty()) {
|
if (newToken.empty()) {
|
||||||
SE_THROW("AccessToken did not contain a string value");
|
SE_THROW("AccessToken did not contain a string value");
|
||||||
} else if (m_invalidateCache && newToken == m_accessToken) {
|
} else if (m_invalidateCache && newToken == m_accessToken) {
|
||||||
|
@ -175,8 +174,8 @@ private:
|
||||||
|
|
||||||
#define signon_auth_session_process_async_finish signon_auth_session_process_finish
|
#define signon_auth_session_process_async_finish signon_auth_session_process_finish
|
||||||
SYNCEVO_GLIB_CALL_SYNC(resultData, gerror, signon_auth_session_process_async,
|
SYNCEVO_GLIB_CALL_SYNC(resultData, gerror, signon_auth_session_process_async,
|
||||||
m_authSession, sessionData, mechanism, NULL);
|
m_authSession, sessionData, mechanism, nullptr);
|
||||||
buffer.reset(resultData ? g_variant_print(resultData, true) : NULL);
|
buffer.reset(resultData ? g_variant_print(resultData, true) : nullptr);
|
||||||
SE_LOG_DEBUG(NULL, "authentication result: %s, %s",
|
SE_LOG_DEBUG(NULL, "authentication result: %s, %s",
|
||||||
buffer.get() ? buffer.get() : "<<null>>",
|
buffer.get() ? buffer.get() : "<<null>>",
|
||||||
gerror ? gerror->message : "???");
|
gerror ? gerror->message : "???");
|
||||||
|
@ -210,21 +209,22 @@ static void StoreIdentityCB(SignonIdentity *self,
|
||||||
data->m_gerror = error;
|
data->m_gerror = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<AuthProvider> createSignonAuthProvider(const InitStateString &username,
|
std::shared_ptr<AuthProvider> createSignonAuthProvider(const InitStateString &username,
|
||||||
const InitStateString &password)
|
const InitStateString &password)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<AuthProvider> provider;
|
std::shared_ptr<AuthProvider> provider;
|
||||||
|
|
||||||
// Split username into <account ID> and <service name>.
|
// Split username into <account ID> and <service name>.
|
||||||
// Be flexible and allow leading/trailing white space.
|
// Be flexible and allow leading/trailing white space.
|
||||||
// Comma is optional.
|
// Comma is optional.
|
||||||
static const pcrecpp::RE re("^\\s*(\\d+)\\s*,?\\s*(.*)\\s*$");
|
static const std::regex re(R"del(\s*(\d+)\s*,?\s*(.*)\s*)del");
|
||||||
AgAccountId accountID;
|
std::smatch match;
|
||||||
std::string serviceName;
|
if (!std::regex_match(username, match, re)) {
|
||||||
if (!re.FullMatch(username, &accountID, &serviceName)) {
|
|
||||||
SE_THROW(StringPrintf("username must have the format " SE_SIGNON_PROVIDER_ID ":<account ID>,<service name>: %s",
|
SE_THROW(StringPrintf("username must have the format " SE_SIGNON_PROVIDER_ID ":<account ID>,<service name>: %s",
|
||||||
username.c_str()));
|
username.c_str()));
|
||||||
}
|
}
|
||||||
|
AgAccountId accountID = std::stol(match[1].str());
|
||||||
|
std::string serviceName = match[2].str();
|
||||||
SE_LOG_DEBUG(NULL, "looking up account ID %d and service '%s'",
|
SE_LOG_DEBUG(NULL, "looking up account ID %d and service '%s'",
|
||||||
accountID,
|
accountID,
|
||||||
serviceName.c_str());
|
serviceName.c_str());
|
||||||
|
@ -243,10 +243,10 @@ boost::shared_ptr<AuthProvider> createSignonAuthProvider(const InitStateString &
|
||||||
}
|
}
|
||||||
AgAccountServiceCXX accountService;
|
AgAccountServiceCXX accountService;
|
||||||
if (serviceName.empty()) {
|
if (serviceName.empty()) {
|
||||||
accountService = AgAccountServiceCXX::steal(ag_account_service_new(account, NULL));
|
accountService = AgAccountServiceCXX::steal(ag_account_service_new(account, nullptr));
|
||||||
} else {
|
} else {
|
||||||
ServiceListCXX services(ag_account_list_enabled_services(account));
|
ServiceListCXX services(ag_account_list_enabled_services(account));
|
||||||
BOOST_FOREACH (AgService *service, services) {
|
for (AgService *service: services) {
|
||||||
const char *name = ag_service_get_name(service);
|
const char *name = ag_service_get_name(service);
|
||||||
SE_LOG_DEBUG(NULL, "enabled service: %s", name);
|
SE_LOG_DEBUG(NULL, "enabled service: %s", name);
|
||||||
if (serviceName == name) {
|
if (serviceName == name) {
|
||||||
|
|
|
@ -49,9 +49,9 @@ else
|
||||||
noinst_LTLIBRARIES += $(src_backends_signon_libs)
|
noinst_LTLIBRARIES += $(src_backends_signon_libs)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
src_backends_signon_common_libadd = $(SYNCEVOLUTION_LIBS)
|
src_backends_signon_common_libadd = $(SYNCEVOLUTION_LIBS) $(PCRECPP_LIBS)
|
||||||
src_backends_signon_common_ldflags = -module -avoid-version
|
src_backends_signon_common_ldflags = -module -avoid-version
|
||||||
src_backends_signon_common_cxxflags = $(SYNCEVOLUTION_CFLAGS)
|
src_backends_signon_common_cxxflags = $(SYNCEVOLUTION_CFLAGS) $(PCRECPP_CFLAGS)
|
||||||
src_backends_signon_common_cppflags = -DUSE_SIGNON -I$(top_srcdir)/test $(BACKEND_CPPFLAGS)
|
src_backends_signon_common_cppflags = -DUSE_SIGNON -I$(top_srcdir)/test $(BACKEND_CPPFLAGS)
|
||||||
src_backends_signon_common_dependencies = src/syncevo/libsyncevolution.la
|
src_backends_signon_common_dependencies = src/syncevo/libsyncevolution.la
|
||||||
|
|
||||||
|
|
|
@ -32,9 +32,6 @@
|
||||||
|
|
||||||
#include <syncevo/GLibSupport.h>
|
#include <syncevo/GLibSupport.h>
|
||||||
#include <syncevo/GVariantSupport.h>
|
#include <syncevo/GVariantSupport.h>
|
||||||
#include <pcrecpp.h>
|
|
||||||
|
|
||||||
#include <boost/lambda/core.hpp>
|
|
||||||
|
|
||||||
SE_GOBJECT_TYPE(SignonAuthService)
|
SE_GOBJECT_TYPE(SignonAuthService)
|
||||||
SE_GOBJECT_TYPE(SignonAuthSession)
|
SE_GOBJECT_TYPE(SignonAuthSession)
|
||||||
|
@ -94,8 +91,8 @@ public:
|
||||||
|
|
||||||
#define signon_auth_session_process_async_finish signon_auth_session_process_finish
|
#define signon_auth_session_process_async_finish signon_auth_session_process_finish
|
||||||
SYNCEVO_GLIB_CALL_SYNC(resultDataVar, gerror, signon_auth_session_process_async,
|
SYNCEVO_GLIB_CALL_SYNC(resultDataVar, gerror, signon_auth_session_process_async,
|
||||||
m_authSession, sessionDataVar, m_mechanism.c_str(), NULL);
|
m_authSession, sessionDataVar, m_mechanism.c_str(), nullptr);
|
||||||
buffer.reset(resultDataVar ? g_variant_print(resultDataVar, true) : NULL);
|
buffer.reset(resultDataVar ? g_variant_print(resultDataVar, true) : nullptr);
|
||||||
SE_LOG_DEBUG(NULL, "OAuth2 token result: %s, %s",
|
SE_LOG_DEBUG(NULL, "OAuth2 token result: %s, %s",
|
||||||
buffer.get() ? buffer.get() : "<<null>>",
|
buffer.get() ? buffer.get() : "<<null>>",
|
||||||
gerror ? gerror->message : "???");
|
gerror ? gerror->message : "???");
|
||||||
|
@ -109,7 +106,7 @@ public:
|
||||||
if (!tokenVar) {
|
if (!tokenVar) {
|
||||||
SE_THROW("no AccessToken in OAuth2 response");
|
SE_THROW("no AccessToken in OAuth2 response");
|
||||||
}
|
}
|
||||||
std::string newToken = g_variant_get_string(tokenVar, NULL);
|
std::string newToken = g_variant_get_string(tokenVar, nullptr);
|
||||||
if (newToken.empty()) {
|
if (newToken.empty()) {
|
||||||
SE_THROW("AccessToken did not contain a string value");
|
SE_THROW("AccessToken did not contain a string value");
|
||||||
} else if (m_invalidateCache && newToken == m_accessToken) {
|
} else if (m_invalidateCache && newToken == m_accessToken) {
|
||||||
|
@ -124,15 +121,15 @@ public:
|
||||||
virtual std::string getUsername() const { return ""; }
|
virtual std::string getUsername() const { return ""; }
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::shared_ptr<AuthProvider> createSignonAuthProvider(const InitStateString &username,
|
std::shared_ptr<AuthProvider> createSignonAuthProvider(const InitStateString &username,
|
||||||
const InitStateString &password)
|
const InitStateString &password)
|
||||||
{
|
{
|
||||||
// Expected content of parameter GVariant.
|
// Expected content of parameter GVariant.
|
||||||
boost::shared_ptr<GVariantType> hashtype(g_variant_type_new("a{sv}"), g_variant_type_free);
|
std::shared_ptr<GVariantType> hashtype(g_variant_type_new("a{sv}"), g_variant_type_free);
|
||||||
|
|
||||||
// 'username' is the part after signon: which we can parse directly.
|
// 'username' is the part after signon: which we can parse directly.
|
||||||
GErrorCXX gerror;
|
GErrorCXX gerror;
|
||||||
GVariantCXX parametersVar(g_variant_parse(hashtype.get(), username.c_str(), NULL, NULL, gerror),
|
GVariantCXX parametersVar(g_variant_parse(hashtype.get(), username.c_str(), nullptr, nullptr, gerror),
|
||||||
TRANSFER_REF);
|
TRANSFER_REF);
|
||||||
if (!parametersVar) {
|
if (!parametersVar) {
|
||||||
gerror.throwError(SE_HERE, "parsing 'signon:' username");
|
gerror.throwError(SE_HERE, "parsing 'signon:' username");
|
||||||
|
@ -157,14 +154,14 @@ boost::shared_ptr<AuthProvider> createSignonAuthProvider(const InitStateString &
|
||||||
!g_variant_type_equal(G_VARIANT_TYPE_STRING, g_variant_get_type(value))) {
|
!g_variant_type_equal(G_VARIANT_TYPE_STRING, g_variant_get_type(value))) {
|
||||||
SE_THROW("need 'method: <string>' in 'signon:' parameters");
|
SE_THROW("need 'method: <string>' in 'signon:' parameters");
|
||||||
}
|
}
|
||||||
method = g_variant_get_string(value, NULL);
|
method = g_variant_get_string(value, nullptr);
|
||||||
|
|
||||||
value = (GVariant *)g_hash_table_lookup(parameters, "mechanism");
|
value = (GVariant *)g_hash_table_lookup(parameters, "mechanism");
|
||||||
if (!value ||
|
if (!value ||
|
||||||
!g_variant_type_equal(G_VARIANT_TYPE_STRING, g_variant_get_type(value))) {
|
!g_variant_type_equal(G_VARIANT_TYPE_STRING, g_variant_get_type(value))) {
|
||||||
SE_THROW("need 'mechanism: <string>' in 'signon:' parameters");
|
SE_THROW("need 'mechanism: <string>' in 'signon:' parameters");
|
||||||
}
|
}
|
||||||
mechanism = g_variant_get_string(value, NULL);
|
mechanism = g_variant_get_string(value, nullptr);
|
||||||
|
|
||||||
value = (GVariant *)g_hash_table_lookup(parameters, "session");
|
value = (GVariant *)g_hash_table_lookup(parameters, "session");
|
||||||
if (!value ||
|
if (!value ||
|
||||||
|
@ -179,7 +176,7 @@ boost::shared_ptr<AuthProvider> createSignonAuthProvider(const InitStateString &
|
||||||
SE_LOG_DEBUG(NULL, "using signond identity %d", signonID);
|
SE_LOG_DEBUG(NULL, "using signond identity %d", signonID);
|
||||||
SignonAuthSessionCXX authSession(signon_identity_create_session(identity, method, gerror), TRANSFER_REF);
|
SignonAuthSessionCXX authSession(signon_identity_create_session(identity, method, gerror), TRANSFER_REF);
|
||||||
|
|
||||||
boost::shared_ptr<AuthProvider> provider(new SignonAuthProvider(authSession, sessionData, mechanism));
|
auto provider = std::make_shared<SignonAuthProvider>(authSession, sessionData, mechanism);
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
#include <syncevo/util.h>
|
#include <syncevo/util.h>
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <memory>
|
||||||
|
|
||||||
#include <syncevo/declarations.h>
|
#include <syncevo/declarations.h>
|
||||||
SE_BEGIN_CXX
|
SE_BEGIN_CXX
|
||||||
|
@ -35,7 +35,7 @@ SE_BEGIN_CXX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class AuthProvider;
|
class AuthProvider;
|
||||||
boost::shared_ptr<AuthProvider> createSignonAuthProvider(const InitStateString &username,
|
std::shared_ptr<AuthProvider> createSignonAuthProvider(const InitStateString &username,
|
||||||
const InitStateString &password);
|
const InitStateString &password);
|
||||||
|
|
||||||
SE_END_CXX
|
SE_END_CXX
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue