removed all references to Funambol header files and definitions
This commit is contained in:
parent
d801974f74
commit
43f2c5fec5
32 changed files with 502 additions and 2118 deletions
11
HACKING
11
HACKING
|
@ -58,18 +58,15 @@ Funambol client library or non-default sources - see the "funambol"
|
|||
configure options for details.
|
||||
|
||||
For doing development work the recommended configure line is:
|
||||
configure SYNCEVOLUTION_CXXFLAGS="-Wall -Werror -Wno-unknown-pragmas" \
|
||||
configure CXXFLAGS="-Wall -Werror -Wno-unknown-pragmas" \
|
||||
--enable-unit-tests \
|
||||
--enable-libcurl
|
||||
|
||||
Enabling libcurl explicitly ensures that it gets built even when not
|
||||
the default.
|
||||
|
||||
In contrast to CXXFLAGS, SYNCEVOLUTION_CXXFLAGS adds these flags only
|
||||
to the compilation of source files from the SyncEvolution source code
|
||||
repository, but not the client library. -Wno-unknown-pragmas is
|
||||
required to avoid warnings triggered by '#pragma }', a trick to
|
||||
preserve indention after 'extern "C" {' in
|
||||
-Wno-unknown-pragmas is required to avoid warnings triggered by
|
||||
'#pragma }', a trick to preserve indention after 'extern "C" {' in
|
||||
/usr/include/evolution-data-server-1.12/libical/
|
||||
|
||||
Working with the Code
|
||||
|
@ -220,7 +217,7 @@ Compiling for Mac OS X
|
|||
Configuring for development:
|
||||
<path>/configure --with-funambol-src=<path> \
|
||||
--enable-addressbook \
|
||||
SYNCEVOLUTION_CXXFLAGS="-Wall -Werror -Wno-unknown-pragmas" \
|
||||
CXXFLAGS="-Wall -Werror -Wno-unknown-pragmas" \
|
||||
LDFLAGS="-framework Addressbook -framework CoreServices" \
|
||||
CXXFLAGS=-g \
|
||||
CFLAGS=-g
|
||||
|
|
260
configure-pre.in
260
configure-pre.in
|
@ -32,36 +32,36 @@ else
|
|||
FUNAMBOLSRC_DEF="FUNAMBOLSRC_REPO"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(funambol-src,
|
||||
AS_HELP_STRING([--with-funambol-src=<base directory|svn URL|git URL>],
|
||||
[Specifies location of the Funambol 'client-api/native' source code.
|
||||
Use this instead of --with-funambol when the client library is to
|
||||
be compiled as part of the SyncEvolution compilation. In release
|
||||
versions of SyncEvolution, a copy of the client library is bundled
|
||||
under 'src/client-api' and compiled unless something else is
|
||||
specified. --with-funambol-src can be given a path to sources
|
||||
checked out already, a Subversion repository URL or a git repository
|
||||
URL. When given a repository URL, then the configure script
|
||||
will checkout the sources into 'src/client-api-copy' or
|
||||
update that working copy if the directory already exists.
|
||||
Default: bundled source in src/client-api (in released SyncEvolution sources),
|
||||
FUNAMBOLSRC_REPO otherwise.]),
|
||||
[FUNAMBOLSRC="$withval"], [FUNAMBOLSRC="$FUNAMBOLSRC_DEF"; REVISION="FUNAMBOLSRC_REVISION"])
|
||||
dnl AC_ARG_WITH(funambol-src,
|
||||
dnl AS_HELP_STRING([--with-funambol-src=<base directory|svn URL|git URL>],
|
||||
dnl [Specifies location of the Funambol 'client-api/native' source code.
|
||||
dnl Use this instead of --with-funambol when the client library is to
|
||||
dnl be compiled as part of the SyncEvolution compilation. In release
|
||||
dnl versions of SyncEvolution, a copy of the client library is bundled
|
||||
dnl under 'src/client-api' and compiled unless something else is
|
||||
dnl specified. --with-funambol-src can be given a path to sources
|
||||
dnl checked out already, a Subversion repository URL or a git repository
|
||||
dnl URL. When given a repository URL, then the configure script
|
||||
dnl will checkout the sources into 'src/client-api-copy' or
|
||||
dnl update that working copy if the directory already exists.
|
||||
dnl Default: bundled source in src/client-api (in released SyncEvolution sources),
|
||||
dnl FUNAMBOLSRC_REPO otherwise.]),
|
||||
dnl [FUNAMBOLSRC="$withval"], [FUNAMBOLSRC="$FUNAMBOLSRC_DEF"; REVISION="FUNAMBOLSRC_REVISION"])
|
||||
|
||||
AC_ARG_WITH(sync4j-src,
|
||||
AS_HELP_STRING([--with-sync4j-src=<base directory>],
|
||||
[alias for --with-funambol-src]),
|
||||
[FUNAMBOLSRC="$withval"])
|
||||
dnl AC_ARG_WITH(sync4j-src,
|
||||
dnl AS_HELP_STRING([--with-sync4j-src=<base directory>],
|
||||
dnl [alias for --with-funambol-src]),
|
||||
dnl [FUNAMBOLSRC="$withval"])
|
||||
|
||||
AC_ARG_WITH(funambol-username,
|
||||
AS_HELP_STRING([--with-funambol-username=<svn username>],
|
||||
[username to use when checking out --with-funambol-src sources from Subversion, default 'guest']),
|
||||
[USERNAME="$withval"], [USERNAME="guest"])
|
||||
dnl AC_ARG_WITH(funambol-username,
|
||||
dnl AS_HELP_STRING([--with-funambol-username=<svn username>],
|
||||
dnl [username to use when checking out --with-funambol-src sources from Subversion, default 'guest']),
|
||||
dnl [USERNAME="$withval"], [USERNAME="guest"])
|
||||
|
||||
AC_ARG_WITH(funambol-revision,
|
||||
AS_HELP_STRING([--with-funambol-revision=<git tag/branch/hash or Subversion revision>],
|
||||
[Identifies which source revision to use from --with-funambol-src repository, empty string stands for latest. Default for default --funambol-src: FUNAMBOLSRC_REVISION]),
|
||||
[REVISION="$withval"])
|
||||
dnl AC_ARG_WITH(funambol-revision,
|
||||
dnl AS_HELP_STRING([--with-funambol-revision=<git tag/branch/hash or Subversion revision>],
|
||||
dnl [Identifies which source revision to use from --with-funambol-src repository, empty string stands for latest. Default for default --funambol-src: FUNAMBOLSRC_REVISION]),
|
||||
dnl [REVISION="$withval"])
|
||||
|
||||
AC_ARG_ENABLE(shared,
|
||||
AS_HELP_STRING([--enable-shared],
|
||||
|
@ -136,7 +136,7 @@ AC_SUBST(CORE_LDADD_DEP)
|
|||
# preserve src/client-api by default,
|
||||
# always
|
||||
CLEAN_CLIENT_SRC=
|
||||
FUNAMBOL_LIB=$PWD/src/build-client-api/src/libfunambol.la
|
||||
dnl FUNAMBOL_LIB=$PWD/src/build-client-api/src/libfunambol.la
|
||||
|
||||
AC_SUBST(CLEAN_CLIENT_SRC)
|
||||
|
||||
|
@ -216,115 +216,117 @@ AC_SUBST(TRANSPORT_LIBS)
|
|||
AC_SUBST(TRANSPORT_CFLAGS)
|
||||
|
||||
|
||||
# absolute patch to source of Funambol client library
|
||||
CLIENT_API_SRC=no-client-api-source
|
||||
AC_SUBST(CLIENT_API_SRC)
|
||||
if test ! "$FUNAMBOL"; then
|
||||
if test "$FUNAMBOLSRC"; then
|
||||
# default: checkout a copy of the sources, remove it during maintainer-clean and distclean
|
||||
CLEAN_CLIENT_SRC=client-api-copy
|
||||
CLIENT_API_SRC=$PWD/src/client-api-copy
|
||||
dnl # absolute patch to source of Funambol client library
|
||||
dnl CLIENT_API_SRC=no-client-api-source
|
||||
dnl AC_SUBST(CLIENT_API_SRC)
|
||||
dnl if test ! "$FUNAMBOL"; then
|
||||
dnl if test "$FUNAMBOLSRC"; then
|
||||
dnl # default: checkout a copy of the sources, remove it during maintainer-clean and distclean
|
||||
dnl CLEAN_CLIENT_SRC=client-api-copy
|
||||
dnl CLIENT_API_SRC=$PWD/src/client-api-copy
|
||||
|
||||
AC_MSG_NOTICE( [updating the content of $CLIENT_API_SRC from $FUNAMBOLSRC] )
|
||||
case "$FUNAMBOLSRC" in
|
||||
*://*) protocol="`echo $FUNAMBOLSRC | sed -e 's;://.*;;'`";;
|
||||
*) protocol="file";;
|
||||
esac
|
||||
dnl AC_MSG_NOTICE( [updating the content of $CLIENT_API_SRC from $FUNAMBOLSRC] )
|
||||
dnl case "$FUNAMBOLSRC" in
|
||||
dnl *://*) protocol="`echo $FUNAMBOLSRC | sed -e 's;://.*;;'`";;
|
||||
dnl *) protocol="file";;
|
||||
dnl esac
|
||||
|
||||
mkdir -p src
|
||||
case $protocol in
|
||||
file)
|
||||
# use existing copy of the sources
|
||||
CLEAN_CLIENT_SRC=
|
||||
case "$FUNAMBOLSRC" in
|
||||
/*) CLIENT_API_SRC="$FUNAMBOLSRC";;
|
||||
*) CLIENT_API_SRC="$PWD/$FUNAMBOLSRC";;
|
||||
esac
|
||||
;;
|
||||
*svn*|*http*)
|
||||
FUNAMBOLSRCREV="$FUNAMBOLSRC"
|
||||
if test "$REVISION"; then
|
||||
revarg="-r $REVISION "
|
||||
if `echo $FUNAMBOLSRC | grep '@[0123456789]*'` >/dev/null; then
|
||||
:
|
||||
else
|
||||
FUNAMBOLSRCREV="$FUNAMBOLSRC@$REVISION"
|
||||
fi
|
||||
fi
|
||||
if test -d $CLIENT_API_SRC ; then
|
||||
( set -x; cd $CLIENT_API_SRC && svn --username=$USERNAME switch $revarg "$FUNAMBOLSRC" ) || AC_ERROR([updating from $FUNAMBOLSRC failed])
|
||||
else
|
||||
(set -x; svn --username=$USERNAME checkout $revarg "$FUNAMBOLSRCREV" $CLIENT_API_SRC ) || AC_ERROR([checking out $FUNAMBOLSRC failed])
|
||||
fi
|
||||
;;
|
||||
*git*)
|
||||
if test -d $CLIENT_API_SRC ; then
|
||||
( set -x; cd $CLIENT_API_SRC && git fetch "$FUNAMBOLSRC" ) || AC_ERROR([updating from $FUNAMBOLSRC failed])
|
||||
else
|
||||
( set -x; git clone "$FUNAMBOLSRC" $CLIENT_API_SRC ) || AC_ERROR([cloning $FUNAMBOLSRC failed])
|
||||
fi
|
||||
if test "$REVISION"; then
|
||||
# git 1.6 finds tags and branches without explicit prefix, 1.4.4.4 doesn't
|
||||
( set -x; cd $CLIENT_API_SRC &&
|
||||
(git checkout "$REVISION" ||
|
||||
git checkout "tags/$REVISION" ||
|
||||
git checkout "origin/$REVISION") ) || AC_ERROR([checking out $FUNAMBOLSRC failed])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
else
|
||||
# use existing copy of the sources; beware of
|
||||
# out-of-tree compilation
|
||||
case $srcdir in
|
||||
/*) CLIENT_API_SRC="$srcdir/src/client-api";;
|
||||
*) CLIENT_API_SRC="$PWD/$srcdir/src/client-api";;
|
||||
esac
|
||||
fi
|
||||
dnl mkdir -p src
|
||||
dnl case $protocol in
|
||||
dnl file)
|
||||
dnl # use existing copy of the sources
|
||||
dnl CLEAN_CLIENT_SRC=
|
||||
dnl case "$FUNAMBOLSRC" in
|
||||
dnl /*) CLIENT_API_SRC="$FUNAMBOLSRC";;
|
||||
dnl *) CLIENT_API_SRC="$PWD/$FUNAMBOLSRC";;
|
||||
dnl esac
|
||||
dnl ;;
|
||||
dnl *svn*|*http*)
|
||||
dnl FUNAMBOLSRCREV="$FUNAMBOLSRC"
|
||||
dnl if test "$REVISION"; then
|
||||
dnl revarg="-r $REVISION "
|
||||
dnl if `echo $FUNAMBOLSRC | grep '@[0123456789]*'` >/dev/null; then
|
||||
dnl :
|
||||
dnl else
|
||||
dnl FUNAMBOLSRCREV="$FUNAMBOLSRC@$REVISION"
|
||||
dnl fi
|
||||
dnl fi
|
||||
dnl if test -d $CLIENT_API_SRC ; then
|
||||
dnl ( set -x; cd $CLIENT_API_SRC && svn --username=$USERNAME switch $revarg "$FUNAMBOLSRC" ) || AC_ERROR([updating from $FUNAMBOLSRC failed])
|
||||
dnl else
|
||||
dnl (set -x; svn --username=$USERNAME checkout $revarg "$FUNAMBOLSRCREV" $CLIENT_API_SRC ) || AC_ERROR([checking out $FUNAMBOLSRC failed])
|
||||
dnl fi
|
||||
dnl ;;
|
||||
dnl *git*)
|
||||
dnl if test -d $CLIENT_API_SRC ; then
|
||||
dnl ( set -x; cd $CLIENT_API_SRC && git fetch "$FUNAMBOLSRC" ) || AC_ERROR([updating from $FUNAMBOLSRC failed])
|
||||
dnl else
|
||||
dnl ( set -x; git clone "$FUNAMBOLSRC" $CLIENT_API_SRC ) || AC_ERROR([cloning $FUNAMBOLSRC failed])
|
||||
dnl fi
|
||||
dnl if test "$REVISION"; then
|
||||
dnl # git 1.6 finds tags and branches without explicit prefix, 1.4.4.4 doesn't
|
||||
dnl ( set -x; cd $CLIENT_API_SRC &&
|
||||
dnl (git checkout "$REVISION" ||
|
||||
dnl git checkout "tags/$REVISION" ||
|
||||
dnl git checkout "origin/$REVISION") ) || AC_ERROR([checking out $FUNAMBOLSRC failed])
|
||||
dnl fi
|
||||
dnl ;;
|
||||
dnl esac
|
||||
dnl else
|
||||
dnl # use existing copy of the sources; beware of
|
||||
dnl # out-of-tree compilation
|
||||
dnl case $srcdir in
|
||||
dnl /*) CLIENT_API_SRC="$srcdir/src/client-api";;
|
||||
dnl *) CLIENT_API_SRC="$PWD/$srcdir/src/client-api";;
|
||||
dnl esac
|
||||
dnl fi
|
||||
|
||||
( cd $CLIENT_API_SRC/build/autotools && ( test -f configure || sh autogen.sh ) )
|
||||
dnl ( cd $CLIENT_API_SRC/build/autotools && ( test -f configure || sh autogen.sh ) )
|
||||
|
||||
if test -f $CLIENT_API_SRC/build/autotools/configure; then
|
||||
CLIENT_CONFIGURE="$CLIENT_API_SRC/build/autotools/configure"
|
||||
chmod u+x $CLIENT_API_SRC/build/autotools/configure $CLIENT_API_SRC/build/autotools/config.sub $CLIENT_API_SRC/build/autotools/config.guess
|
||||
dnl if test -f $CLIENT_API_SRC/build/autotools/configure; then
|
||||
dnl CLIENT_CONFIGURE="$CLIENT_API_SRC/build/autotools/configure"
|
||||
dnl chmod u+x $CLIENT_API_SRC/build/autotools/configure $CLIENT_API_SRC/build/autotools/config.sub $CLIENT_API_SRC/build/autotools/config.guess
|
||||
|
||||
# use local copy of the sources, with dependencies
|
||||
# to trigger building the client library
|
||||
FUNAMBOL_SUBDIR=$PWD/src/build-client-api
|
||||
FUNAMBOL_DEP=$PWD/src/build-client-api/src/libfunambol.la
|
||||
dnl # use local copy of the sources, with dependencies
|
||||
dnl # to trigger building the client library
|
||||
dnl FUNAMBOL_SUBDIR=$PWD/src/build-client-api
|
||||
dnl FUNAMBOL_DEP=$PWD/src/build-client-api/src/libfunambol.la
|
||||
|
||||
FUNAMBOL_CFLAGS="-I$FUNAMBOL_SUBDIR/include/posix -I$FUNAMBOL_SUBDIR/include/common -I$FUNAMBOL_SUBDIR/include -I$FUNAMBOL_SUBDIR/test"
|
||||
FUNAMBOL_LIBS="-L$FUNAMBOL_SUBDIR/src -lfunambol"
|
||||
dnl FUNAMBOL_CFLAGS="-I$FUNAMBOL_SUBDIR/include/posix -I$FUNAMBOL_SUBDIR/include/common -I$FUNAMBOL_SUBDIR/include -I$FUNAMBOL_SUBDIR/test"
|
||||
dnl FUNAMBOL_LIBS="-L$FUNAMBOL_SUBDIR/src -lfunambol"
|
||||
|
||||
AC_MSG_NOTICE( [configuring the client library] )
|
||||
# Passing some specific configure arguments to the client library's
|
||||
# configure makes sense (e.g., --enable-unit-tests) or is
|
||||
# required (--disable-dependency-tracking when compiling for
|
||||
# multiple architectures on Mac OS X).
|
||||
cxx_lib_args=`for i in --disable-dependency-tracking --enable-unit-tests; do
|
||||
if echo $ac_configure_args | grep -e $i >/dev/null; then
|
||||
echo $i;
|
||||
fi;
|
||||
done`
|
||||
if test "$enable_shared" == "yes"; then
|
||||
# Okay, this is a shortcut: strictly speaking we would have
|
||||
# to check with autoconf for the right flags...
|
||||
FUNAMBOL_LIB_SHARED_FLAGS="-DPIC -fPIC"
|
||||
fi
|
||||
if (set -x; mkdir -p $FUNAMBOL_SUBDIR && cd $FUNAMBOL_SUBDIR && $CLIENT_CONFIGURE $CLIENT_CONFIGURE_OPTIONS --build=$build_alias --host=$host_alias --target=$target_alias --disable-shared --with-transport-agent=curl CFLAGS="$CFLAGS $FUNAMBOL_LIB_SHARED_FLAGS" CXXFLAGS="$CXXFLAGS $FUNAMBOL_LIB_SHARED_FLAGS" $cxx_lib_args); then true; else
|
||||
AC_MSG_ERROR( [configuring client library failed] )
|
||||
fi
|
||||
else
|
||||
AC_MSG_ERROR( [either --with-funambol or --with-funambol-src have to be used] )
|
||||
fi
|
||||
else
|
||||
if test -f $FUNAMBOL/include/funambol/common/spds/SyncItem.h; then
|
||||
FUNAMBOL_CFLAGS="-I$FUNAMBOL/include/funambol/posix -I$FUNAMBOL/include/funambol/common -I$FUNAMBOL/include/funambol"
|
||||
FUNAMBOL_LIBS="-L$FUNAMBOL/lib -lfunambol"
|
||||
else
|
||||
AC_MSG_ERROR( [$FUNAMBOL does seem to be valid (e.g. include/funambol/spds/common/SyncItem.h is missing)] )
|
||||
fi
|
||||
fi
|
||||
dnl AC_MSG_NOTICE( [configuring the client library] )
|
||||
dnl # Passing some specific configure arguments to the client library's
|
||||
dnl # configure makes sense (e.g., --enable-unit-tests) or is
|
||||
dnl # required (--disable-dependency-tracking when compiling for
|
||||
dnl # multiple architectures on Mac OS X).
|
||||
dnl cxx_lib_args=`for i in --disable-dependency-tracking --enable-unit-tests; do
|
||||
dnl if echo $ac_configure_args | grep -e $i >/dev/null; then
|
||||
dnl echo $i;
|
||||
dnl fi;
|
||||
dnl done`
|
||||
dnl if test "$enable_shared" == "yes"; then
|
||||
dnl # Okay, this is a shortcut: strictly speaking we would have
|
||||
dnl # to check with autoconf for the right flags...
|
||||
dnl FUNAMBOL_LIB_SHARED_FLAGS="-DPIC -fPIC"
|
||||
dnl fi
|
||||
dnl if (set -x; mkdir -p $FUNAMBOL_SUBDIR && cd $FUNAMBOL_SUBDIR && $CLIENT_CONFIGURE $CLIENT_CONFIGURE_OPTIONS --build=$build_alias --host=$host_alias --target=$target_alias --disable-shared --with-transport-agent=curl CFLAGS="$CFLAGS $FUNAMBOL_LIB_SHARED_FLAGS" CXXFLAGS="$CXXFLAGS $FUNAMBOL_LIB_SHARED_FLAGS" $cxx_lib_args); then true; else
|
||||
dnl AC_MSG_ERROR( [configuring client library failed] )
|
||||
dnl fi
|
||||
dnl else
|
||||
dnl AC_MSG_ERROR( [either --with-funambol or --with-funambol-src have to be used] )
|
||||
dnl fi
|
||||
dnl else
|
||||
dnl if test -f $FUNAMBOL/include/funambol/common/spds/SyncItem.h; then
|
||||
dnl FUNAMBOL_CFLAGS="-I$FUNAMBOL/include/funambol/posix -I$FUNAMBOL/include/funambol/common -I$FUNAMBOL/include/funambol"
|
||||
dnl FUNAMBOL_LIBS="-L$FUNAMBOL/lib -lfunambol"
|
||||
dnl else
|
||||
dnl AC_MSG_ERROR( [$FUNAMBOL does seem to be valid (e.g. include/funambol/spds/common/SyncItem.h is missing)] )
|
||||
dnl fi
|
||||
dnl fi
|
||||
|
||||
dnl TODO: compile Synthesis library the same way Funambol was compiled/bundled before?
|
||||
dnl Makefiles are unchanged for that purpose.
|
||||
FUNAMBOL_CFLAGS="$FUNAMBOL_CFLAGS $SYNTHESIS_CFLAGS"
|
||||
|
||||
AC_SUBST(FUNAMBOL_CFLAGS)
|
||||
|
|
|
@ -118,12 +118,13 @@ distclean-local:
|
|||
# executed. The workaround is to explicitly set them as undefined on the
|
||||
# link line.
|
||||
client_test_SOURCES = client-test-app.cpp $(CORE_SOURCES)
|
||||
CLIENT_LIB_TEST_FILES = ClientTest.h ClientTest.cpp client-test-main.cpp \
|
||||
testcases/vcard21.vcf \
|
||||
testcases/vcard30.vcf \
|
||||
testcases/ical20.ics \
|
||||
testcases/imemo20.ics \
|
||||
testcases/itodo20.ics
|
||||
CLIENT_LIB_TEST_FILES =
|
||||
# ClientTest.h ClientTest.cpp client-test-main.cpp \
|
||||
# testcases/vcard21.vcf \
|
||||
# testcases/vcard30.vcf \
|
||||
# testcases/ical20.ics \
|
||||
# testcases/imemo20.ics \
|
||||
# testcases/itodo20.ics
|
||||
nodist_client_test_SOURCES = $(CLIENT_LIB_TEST_FILES)
|
||||
client_test_CPPFLAGS = -DHAVE_CONFIG_H -DENABLE_INTEGRATION_TESTS -DENABLE_UNIT_TESTS $(AM_CPPFLAGS)
|
||||
client_test_CXXFLAGS = `cppunit-config --cflags` $(SYNCEVOLUTION_CXXFLAGS)
|
||||
|
|
|
@ -229,24 +229,12 @@ SyncItem *EvolutionCalendarSource::createItem(const string &luid)
|
|||
ItemID id(luid);
|
||||
string icalstr = retrieveItemAsString(id);
|
||||
|
||||
auto_ptr<SyncItem> item(new SyncItem(luid.c_str()));
|
||||
cxxptr<SyncItem> item(new SyncItem(), "SyncItem");
|
||||
item->setKey(luid);
|
||||
item->setData(icalstr.c_str(), icalstr.size());
|
||||
item->setDataType("text/calendar");
|
||||
item->setModificationTime(0);
|
||||
|
||||
return item.release();
|
||||
}
|
||||
|
||||
void EvolutionCalendarSource::setItemStatusThrow(const char *key, int status)
|
||||
{
|
||||
switch (status) {
|
||||
case STC_CONFLICT_RESOLVED_WITH_SERVER_DATA:
|
||||
SE_LOG_ERROR(this, NULL, "item %.80s: conflict, will be replaced by server\n", key);
|
||||
break;
|
||||
}
|
||||
TrackingSyncSource::setItemStatusThrow(key, status);
|
||||
}
|
||||
|
||||
EvolutionCalendarSource::InsertItemResult EvolutionCalendarSource::insertItem(const string &luid, const SyncItem &item)
|
||||
{
|
||||
bool update = !luid.empty();
|
||||
|
@ -584,9 +572,8 @@ static string extractProp(const char *data, const char *keyword)
|
|||
void EvolutionCalendarSource::logItem(const SyncItem &item, const string &info, bool debug)
|
||||
{
|
||||
if (getLevel() >= (debug ? Logger::DEBUG : Logger::INFO)) {
|
||||
const char *keyptr = item.getKey();
|
||||
string key;
|
||||
if (!keyptr || !keyptr[0]) {
|
||||
string key = item.getKey();
|
||||
if (key.empty()) {
|
||||
// get UID from data via simple string search; doesn't have to be perfect
|
||||
const char *data = (const char *)item.getData();
|
||||
string uid = extractProp(data, "\nUID:");
|
||||
|
@ -596,8 +583,6 @@ void EvolutionCalendarSource::logItem(const SyncItem &item, const string &info,
|
|||
} else {
|
||||
key = ItemID::getLUID(uid, rid);
|
||||
}
|
||||
} else {
|
||||
key = keyptr;
|
||||
}
|
||||
SE_LOG(debug ? Logger::DEBUG : Logger::INFO, this, NULL, "%s: %s", key.c_str(), info.c_str());
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ class EvolutionCalendarSource : public TrackingSyncSource
|
|||
//
|
||||
virtual void listAllItems(RevisionMap_t &revisions);
|
||||
virtual InsertItemResult insertItem(const string &luid, const SyncItem &item);
|
||||
virtual void setItemStatusThrow(const char *key, int status);
|
||||
virtual void deleteItem(const string &luid);
|
||||
virtual void logItem(const string &luid, const string &info, bool debug = false);
|
||||
virtual void logItem(const SyncItem &item, const string &info, bool debug = false);
|
||||
|
|
|
@ -18,8 +18,6 @@ using namespace std;
|
|||
#include "SyncEvolutionUtil.h"
|
||||
|
||||
#include "Logging.h"
|
||||
#include "vocl/VConverter.h"
|
||||
using namespace vocl;
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
@ -331,27 +329,29 @@ void EvolutionContactSource::exportData(ostream &out)
|
|||
}
|
||||
}
|
||||
|
||||
SyncItem *EvolutionContactSource::createItem(const string &uid)
|
||||
SyncItem *EvolutionContactSource::createItem(const string &luid)
|
||||
{
|
||||
logItem( uid, "extracting from EV", true );
|
||||
logItem(luid, "extracting from EV", true);
|
||||
|
||||
EContact *contact;
|
||||
GError *gerror = NULL;
|
||||
if (! e_book_get_contact( m_addressbook,
|
||||
uid.c_str(),
|
||||
&contact,
|
||||
&gerror ) ) {
|
||||
throwError( string( "reading contact " ) + uid,
|
||||
gerror );
|
||||
if (!e_book_get_contact(m_addressbook,
|
||||
luid.c_str(),
|
||||
&contact,
|
||||
&gerror)) {
|
||||
throwError(string("reading contact ") + luid,
|
||||
gerror);
|
||||
}
|
||||
eptr<EContact, GObject> contactptr( contact, "contact" );
|
||||
eptr<char> vcardstr(e_vcard_to_string( &contactptr->parent,
|
||||
EVC_FORMAT_VCARD_30 ) );
|
||||
eptr<EContact, GObject> contactptr(contact, "contact");
|
||||
eptr<char> vcardstr(e_vcard_to_string(&contactptr->parent,
|
||||
EVC_FORMAT_VCARD_30));
|
||||
if (!vcardstr) {
|
||||
throwError(string("failure extracting contact from Evolution " ) + uid);
|
||||
throwError(string("failure extracting contact from Evolution " ) + luid);
|
||||
}
|
||||
SE_LOG_DEBUG(this, NULL, "%s", vcardstr.get());
|
||||
|
||||
#if 0
|
||||
// @TODO reimplement Evolution hacks via Synthesis datatype conversions
|
||||
std::auto_ptr<VObject> vobj(VConverter::parse(vcardstr));
|
||||
if (vobj.get() == 0) {
|
||||
throwError(string("failure parsing contact " ) + uid);
|
||||
|
@ -477,17 +477,20 @@ SyncItem *EvolutionContactSource::createItem(const string &uid)
|
|||
arrayptr<char> finalstr(vobj->toString(), "VOCL string");
|
||||
SE_LOG_DEBUG(this, NULL, "after conversion:");
|
||||
SE_LOG_DEBUG(this, NULL, "%s", (char *)finalstr);
|
||||
#endif
|
||||
|
||||
auto_ptr<SyncItem> item( new SyncItem( uid.c_str() ) );
|
||||
item->setData( (char *)finalstr, strlen(finalstr) );
|
||||
item->setDataType( getMimeType() );
|
||||
item->setModificationTime( 0 );
|
||||
|
||||
cxxptr<SyncItem> item(new SyncItem(), "SyncItem");
|
||||
item->setKey(luid);
|
||||
item->setData(vcardstr.get(), strlen(vcardstr.get()));
|
||||
return item.release();
|
||||
}
|
||||
|
||||
string EvolutionContactSource::preparseVCard(SyncItem& item)
|
||||
{
|
||||
return item.getData();
|
||||
|
||||
#if 0
|
||||
// @TODO Synthesis data conversion
|
||||
string data = (const char *)item.getData();
|
||||
// convert to 3.0 to get rid of quoted-printable encoded
|
||||
// non-ASCII chars, because Evolution does not support
|
||||
|
@ -672,52 +675,13 @@ string EvolutionContactSource::preparseVCard(SyncItem& item)
|
|||
SE_LOG_DEBUG(this, NULL, "after conversion to 3.0:");
|
||||
SE_LOG_DEBUG(this, NULL, "%s", data.c_str());
|
||||
return data;
|
||||
#endif
|
||||
}
|
||||
|
||||
void EvolutionContactSource::setItemStatusThrow(const char *key, int status)
|
||||
SyncMLStatus EvolutionContactSource::addItemThrow(SyncItem& item)
|
||||
{
|
||||
switch (status) {
|
||||
case STC_CONFLICT_RESOLVED_WITH_SERVER_DATA: {
|
||||
// make a copy before allowing the server to overwrite it
|
||||
|
||||
SE_LOG_ERROR(this, NULL, "contact %s: conflict, will be replaced by server contact - create copy", key);
|
||||
|
||||
EContact *contact;
|
||||
GError *gerror = NULL;
|
||||
if (! e_book_get_contact( m_addressbook,
|
||||
key,
|
||||
&contact,
|
||||
&gerror ) ) {
|
||||
SE_LOG_ERROR(this, NULL, "item %.80s: reading original for copy failed", key);
|
||||
break;
|
||||
}
|
||||
eptr<EContact, GObject> contactptr( contact, "contact" );
|
||||
EContact *copy = e_contact_duplicate(contact);
|
||||
eptr<EContact, GObject> contactcopyptr(copy);
|
||||
if(!copy ||
|
||||
! e_book_add_contact(m_addressbook,
|
||||
copy,
|
||||
&gerror)) {
|
||||
SE_LOG_ERROR(this, NULL, "item %.80s: making copy failed", key);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
EvolutionSyncSource::setItemStatusThrow(key, status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int EvolutionContactSource::addItemThrow(SyncItem& item)
|
||||
{
|
||||
int status = STC_OK;
|
||||
string data;
|
||||
if( strcmp(item.getDataType(), "raw" ) ) {
|
||||
data = preparseVCard(item);
|
||||
} else {
|
||||
data = (const char *)item.getData();
|
||||
}
|
||||
SyncMLStatus status = STATUS_OK;
|
||||
string data = item.getData();
|
||||
eptr<EContact, GObject> contact(e_contact_new_from_vcard(data.c_str()));
|
||||
if( contact ) {
|
||||
GError *gerror = NULL;
|
||||
|
@ -733,9 +697,9 @@ int EvolutionContactSource::addItemThrow(SyncItem& item)
|
|||
return status;
|
||||
}
|
||||
|
||||
int EvolutionContactSource::updateItemThrow(SyncItem& item)
|
||||
SyncMLStatus EvolutionContactSource::updateItemThrow(SyncItem& item)
|
||||
{
|
||||
int status = STC_OK;
|
||||
SyncMLStatus status = STATUS_OK;
|
||||
string data = preparseVCard(item);
|
||||
eptr<EContact, GObject> contact(e_contact_new_from_vcard(data.c_str()));
|
||||
if( contact ) {
|
||||
|
@ -750,7 +714,7 @@ int EvolutionContactSource::updateItemThrow(SyncItem& item)
|
|||
// and committing once more, but that did not solve the problem.
|
||||
//
|
||||
// TODO: test with current Evolution
|
||||
e_contact_set( contact, E_CONTACT_UID, (void *)item.getKey() );
|
||||
e_contact_set(contact, E_CONTACT_UID, (void *)item.getKey().c_str());
|
||||
if ( e_book_commit_contact(m_addressbook, contact, &gerror) ) {
|
||||
const char *uid = (const char *)e_contact_get_const(contact, E_CONTACT_UID);
|
||||
if (uid) {
|
||||
|
@ -783,15 +747,15 @@ int EvolutionContactSource::updateItemThrow(SyncItem& item)
|
|||
return status;
|
||||
}
|
||||
|
||||
int EvolutionContactSource::deleteItemThrow(SyncItem& item)
|
||||
SyncMLStatus EvolutionContactSource::deleteItemThrow(SyncItem& item)
|
||||
{
|
||||
int status = STC_OK;
|
||||
SyncMLStatus status = STATUS_OK;
|
||||
GError *gerror = NULL;
|
||||
if (!e_book_remove_contact( m_addressbook, item.getKey(), &gerror ) ) {
|
||||
if (!e_book_remove_contact(m_addressbook, item.getKey().c_str(), &gerror)) {
|
||||
if (gerror->domain == E_BOOK_ERROR &&
|
||||
gerror->code == E_BOOK_ERROR_CONTACT_NOT_FOUND) {
|
||||
SE_LOG_DEBUG(this, NULL, "%s: %s: request to delete non-existant contact ignored",
|
||||
getName(), item.getKey());
|
||||
getName(), item.getKey().c_str());
|
||||
g_clear_error(&gerror);
|
||||
} else {
|
||||
throwError( string( "deleting contact " ) + item.getKey(),
|
||||
|
@ -886,9 +850,7 @@ void EvolutionContactSource::logItem(const SyncItem &item, const string &info, b
|
|||
line += "<unnamed contact>";
|
||||
}
|
||||
|
||||
if (!item.getKey() ) {
|
||||
line += ", NULL UID (?!)";
|
||||
} else if (!strlen( item.getKey() )) {
|
||||
if (item.getKey().empty()) {
|
||||
line += ", empty UID";
|
||||
} else {
|
||||
line += ", ";
|
||||
|
@ -896,10 +858,10 @@ void EvolutionContactSource::logItem(const SyncItem &item, const string &info, b
|
|||
|
||||
EContact *contact;
|
||||
GError *gerror = NULL;
|
||||
if (e_book_get_contact( m_addressbook,
|
||||
item.getKey(),
|
||||
&contact,
|
||||
&gerror )) {
|
||||
if (e_book_get_contact(m_addressbook,
|
||||
item.getKey().c_str(),
|
||||
&contact,
|
||||
&gerror)) {
|
||||
eptr<EContact, GObject> contactptr( contact, "contact" );
|
||||
|
||||
line += ", EV ";
|
||||
|
|
|
@ -49,10 +49,9 @@ class EvolutionContactSource : public EvolutionSyncSource
|
|||
bool needPartial,
|
||||
bool deleteLocal);
|
||||
virtual void endSyncThrow();
|
||||
virtual void setItemStatusThrow(const char *key, int status);
|
||||
virtual int addItemThrow(SyncItem& item);
|
||||
virtual int updateItemThrow(SyncItem& item);
|
||||
virtual int deleteItemThrow(SyncItem& item);
|
||||
virtual SyncMLStatus addItemThrow(SyncItem& item);
|
||||
virtual SyncMLStatus updateItemThrow(SyncItem& item);
|
||||
virtual SyncMLStatus deleteItemThrow(SyncItem& item);
|
||||
virtual void logItem(const string &uid, const string &info, bool debug = false);
|
||||
virtual void logItem(const SyncItem &item, const string &info, bool debug = false);
|
||||
|
||||
|
|
|
@ -20,9 +20,8 @@ SyncItem *EvolutionMemoSource::createItem(const string &luid)
|
|||
|
||||
ItemID id(luid);
|
||||
eptr<icalcomponent> comp(retrieveItem(id));
|
||||
auto_ptr<SyncItem> item(new SyncItem(luid.c_str()));
|
||||
|
||||
item->setData("", 0);
|
||||
cxxptr<SyncItem> item(new SyncItem(), "SyncItem");
|
||||
item->setKey(luid);
|
||||
icalcomponent *cal = icalcomponent_get_first_component(comp, ICAL_VCALENDAR_COMPONENT);
|
||||
if (!cal) {
|
||||
cal = comp;
|
||||
|
@ -90,23 +89,20 @@ SyncItem *EvolutionMemoSource::createItem(const string &luid)
|
|||
item->setData(dostext, strlen(dostext));
|
||||
}
|
||||
}
|
||||
item->setDataType("text/plain");
|
||||
item->setModificationTime(0);
|
||||
|
||||
return item.release();
|
||||
}
|
||||
|
||||
EvolutionCalendarSource::InsertItemResult EvolutionMemoSource::insertItem(const string &luid, const SyncItem &item)
|
||||
{
|
||||
const char *type = item.getDataType();
|
||||
string type = item.getDataType();
|
||||
|
||||
// fall back to inserting iCalendar 2.0 if
|
||||
// real SyncML server has sent vCalendar 1.0 or iCalendar 2.0
|
||||
// or the test system inserts such an item
|
||||
if (!type[0] ||
|
||||
!strcasecmp(type, "raw") ||
|
||||
!strcasecmp(type, "text/x-vcalendar") ||
|
||||
!strcasecmp(type, "text/calendar")) {
|
||||
if (!strcasecmp(type.c_str(), "raw") ||
|
||||
!strcasecmp(type.c_str(), "text/x-vcalendar") ||
|
||||
!strcasecmp(type.c_str(), "text/calendar")) {
|
||||
return EvolutionCalendarSource::insertItem(luid, item);
|
||||
}
|
||||
|
||||
|
|
|
@ -151,12 +151,9 @@ SyncItem *FileSyncSource::createItem(const string &uid)
|
|||
}
|
||||
|
||||
string content = out.str();
|
||||
auto_ptr<SyncItem> item(new SyncItem(uid.c_str()));
|
||||
cxxptr<SyncItem> item(new SyncItem(), "SyncItem");
|
||||
item->setKey(uid);
|
||||
item->setData(content.c_str(), content.size());
|
||||
item->setDataType(getMimeType());
|
||||
// probably not even used by Funambol client library...
|
||||
item->setModificationTime(0);
|
||||
|
||||
return item.release();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ syncsqlite_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS)
|
|||
|
||||
# SQLiteContactSource does not support all fields from Funambol vCard 2.1
|
||||
# test cases: filter them out before testing
|
||||
../../testcases/sqlite_vcard21.vcf: $(FUNAMBOL_SUBDIR)/test/test/testcases/vcard21.vcf
|
||||
mkdir -p ${@D}
|
||||
perl -e '$$_ = join("", <>); s/^(ADR|TEL|EMAIL|PHOTO).*?(?=^\S)//msg; s/;X-EVOLUTION-UI-SLOT=\d+//g; print;' $< >$@
|
||||
all: ../../testcases/sqlite_vcard21.vcf
|
||||
#../../testcases/sqlite_vcard21.vcf: $(FUNAMBOL_SUBDIR)/test/test/testcases/vcard21.vcf
|
||||
# mkdir -p ${@D}
|
||||
# perl -e '$$_ = join("", <>); s/^(ADR|TEL|EMAIL|PHOTO).*?(?=^\S)//msg; s/;X-EVOLUTION-UI-SLOT=\d+//g; print;' $< >$@
|
||||
# all: ../../testcases/sqlite_vcard21.vcf
|
||||
|
|
|
@ -49,8 +49,13 @@ EvolutionSyncClient::EvolutionSyncClient(const string &server,
|
|||
m_quiet(false),
|
||||
m_engine(new sysync::TEngineModuleBridge())
|
||||
{
|
||||
// Use libsynthesis that we were linked against. The name
|
||||
// of a .so could be given here, too, to use that instead.
|
||||
// Use libsynthesis that we were linked against. The name of a
|
||||
// .so could be given here, too, to use that instead. This
|
||||
// instance of the engine is used outside of the sync session
|
||||
// itself. doSync() then creates another engine for the sync
|
||||
// itself. That is necessary because the engine shutdown depends
|
||||
// on the context of the sync (in particular instantiated sync
|
||||
// sources).
|
||||
sysync::TSyError err = m_engine->Connect("[]", 0,
|
||||
sysync::DBG_PLUGIN_NONE|
|
||||
sysync::DBG_PLUGIN_INT|
|
||||
|
@ -312,9 +317,7 @@ class SourceList : public vector<EvolutionSyncSource *> {
|
|||
LogDir m_logdir; /**< our logging directory */
|
||||
bool m_prepared; /**< remember whether syncPrepare() dumped databases successfully */
|
||||
bool m_doLogging; /**< true iff additional files are to be written during sync */
|
||||
SyncClient &m_client; /**< client which holds the sync report after a sync */
|
||||
bool m_reportTodo; /**< true if syncDone() shall print a final report */
|
||||
boost::scoped_array<SyncSource *> m_sourceArray; /** owns the array that is expected by SyncClient::sync() */
|
||||
const bool m_quiet; /**< avoid redundant printing to screen */
|
||||
string m_previousLogdir; /**< remember previous log dir before creating the new one */
|
||||
|
||||
|
@ -361,11 +364,10 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
SourceList(const string &server, bool doLogging, SyncClient &client, bool quiet) :
|
||||
SourceList(const string &server, bool doLogging, bool quiet) :
|
||||
m_logdir(server),
|
||||
m_prepared(false),
|
||||
m_doLogging(doLogging),
|
||||
m_client(client),
|
||||
m_reportTodo(true),
|
||||
m_quiet(quiet)
|
||||
{
|
||||
|
@ -502,8 +504,8 @@ public:
|
|||
for (EvolutionSyncSource::ItemLocation location = EvolutionSyncSource::ITEM_LOCAL;
|
||||
location <= EvolutionSyncSource::ITEM_REMOTE;
|
||||
location = EvolutionSyncSource::ItemLocation(int(location) + 1)) {
|
||||
for (EvolutionSyncSource::ItemState state = EvolutionSyncSource::ITEM_STATE_ADDED;
|
||||
state <= EvolutionSyncSource::ITEM_STATE_REMOVED;
|
||||
for (EvolutionSyncSource::ItemState state = EvolutionSyncSource::ITEM_ADDED;
|
||||
state <= EvolutionSyncSource::ITEM_REMOVED;
|
||||
state = EvolutionSyncSource::ItemState(int(state) + 1)) {
|
||||
cout << right << setw(number_width) <<
|
||||
source->getItemStat(location, state, EvolutionSyncSource::ITEM_REJECT);
|
||||
|
@ -515,24 +517,24 @@ public:
|
|||
}
|
||||
int total_conflicts =
|
||||
source->getItemStat(EvolutionSyncSource::ITEM_REMOTE,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
EvolutionSyncSource::ITEM_CONFLICT_SERVER_WON) +
|
||||
source->getItemStat(EvolutionSyncSource::ITEM_REMOTE,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
EvolutionSyncSource::ITEM_CONFLICT_CLIENT_WON) +
|
||||
source->getItemStat(EvolutionSyncSource::ITEM_REMOTE,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
EvolutionSyncSource::ITEM_CONFLICT_DUPLICATED);
|
||||
cout << right << setw(number_width + 1) << total_conflicts;
|
||||
cout << " |\n";
|
||||
|
||||
stringstream sent, received;
|
||||
sent << source->getItemStat(EvolutionSyncSource::ITEM_LOCAL,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
EvolutionSyncSource::ITEM_SENT_BYTES) / 1024 <<
|
||||
" KB sent by client";
|
||||
received << source->getItemStat(EvolutionSyncSource::ITEM_LOCAL,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
EvolutionSyncSource::ITEM_RECEIVED_BYTES) / 1024 <<
|
||||
" KB received";
|
||||
cout << "|" << left << setw(name_width) << "" << " |" <<
|
||||
|
@ -547,7 +549,7 @@ public:
|
|||
result = EvolutionSyncSource::ItemResult(int(result) + 1)) {
|
||||
int count;
|
||||
if ((count = source->getItemStat(EvolutionSyncSource::ITEM_REMOTE,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
result)) != 0 || true) {
|
||||
stringstream line;
|
||||
line << count << " " <<
|
||||
|
@ -562,7 +564,7 @@ public:
|
|||
}
|
||||
|
||||
int total_matched = source->getItemStat(EvolutionSyncSource::ITEM_REMOTE,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
EvolutionSyncSource::ITEM_MATCH);
|
||||
if (total_matched) {
|
||||
cout << "|" << left << setw(name_width) << "" << "| " << left <<
|
||||
|
@ -599,19 +601,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/** returns current sources as array as expected by SyncClient::sync(), memory owned by this class */
|
||||
SyncSource **getSourceArray() {
|
||||
m_sourceArray.reset(new SyncSource *[size() + 1]);
|
||||
|
||||
int index = 0;
|
||||
BOOST_FOREACH(EvolutionSyncSource *source, *this) {
|
||||
m_sourceArray[index] = source;
|
||||
index++;
|
||||
}
|
||||
m_sourceArray[index] = 0;
|
||||
return &m_sourceArray[0];
|
||||
}
|
||||
|
||||
/** returns names of active sources */
|
||||
set<string> getSources() {
|
||||
set<string> res;
|
||||
|
@ -783,15 +772,15 @@ void EvolutionSyncClient::displaySourceProgress(sysync::TEngineProgressEventType
|
|||
extra2=# updated,
|
||||
extra3=# deleted) */
|
||||
source.setItemStat(EvolutionSyncSource::ITEM_LOCAL,
|
||||
EvolutionSyncSource::ITEM_STATE_ADDED,
|
||||
EvolutionSyncSource::ITEM_ADDED,
|
||||
EvolutionSyncSource::ITEM_TOTAL,
|
||||
extra1);
|
||||
source.setItemStat(EvolutionSyncSource::ITEM_LOCAL,
|
||||
EvolutionSyncSource::ITEM_STATE_UPDATED,
|
||||
EvolutionSyncSource::ITEM_UPDATED,
|
||||
EvolutionSyncSource::ITEM_TOTAL,
|
||||
extra2);
|
||||
source.setItemStat(EvolutionSyncSource::ITEM_LOCAL,
|
||||
EvolutionSyncSource::ITEM_STATE_REMOVED,
|
||||
EvolutionSyncSource::ITEM_REMOVED,
|
||||
EvolutionSyncSource::ITEM_TOTAL,
|
||||
extra3);
|
||||
break;
|
||||
|
@ -800,15 +789,15 @@ void EvolutionSyncClient::displaySourceProgress(sysync::TEngineProgressEventType
|
|||
extra2=# updated,
|
||||
extra3=# deleted) */
|
||||
source.setItemStat(EvolutionSyncSource::ITEM_REMOTE,
|
||||
EvolutionSyncSource::ITEM_STATE_ADDED,
|
||||
EvolutionSyncSource::ITEM_ADDED,
|
||||
EvolutionSyncSource::ITEM_TOTAL,
|
||||
extra1);
|
||||
source.setItemStat(EvolutionSyncSource::ITEM_REMOTE,
|
||||
EvolutionSyncSource::ITEM_STATE_UPDATED,
|
||||
EvolutionSyncSource::ITEM_UPDATED,
|
||||
EvolutionSyncSource::ITEM_TOTAL,
|
||||
extra2);
|
||||
source.setItemStat(EvolutionSyncSource::ITEM_REMOTE,
|
||||
EvolutionSyncSource::ITEM_STATE_REMOVED,
|
||||
EvolutionSyncSource::ITEM_REMOVED,
|
||||
EvolutionSyncSource::ITEM_TOTAL,
|
||||
extra3);
|
||||
break;
|
||||
|
@ -816,18 +805,18 @@ void EvolutionSyncClient::displaySourceProgress(sysync::TEngineProgressEventType
|
|||
/* datastore statistics for local/remote rejects (extra1=# locally rejected,
|
||||
extra2=# remotely rejected) */
|
||||
source.setItemStat(EvolutionSyncSource::ITEM_LOCAL,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
EvolutionSyncSource::ITEM_REJECT,
|
||||
extra1);
|
||||
source.setItemStat(EvolutionSyncSource::ITEM_REMOTE,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
EvolutionSyncSource::ITEM_REJECT,
|
||||
extra2);
|
||||
break;
|
||||
case PEV_DSSTATS_S:
|
||||
/* datastore statistics for server slowsync (extra1=# slowsync matches) */
|
||||
source.setItemStat(EvolutionSyncSource::ITEM_REMOTE,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
EvolutionSyncSource::ITEM_MATCH,
|
||||
extra1);
|
||||
break;
|
||||
|
@ -836,15 +825,15 @@ void EvolutionSyncClient::displaySourceProgress(sysync::TEngineProgressEventType
|
|||
extra2=# client won,
|
||||
extra3=# duplicated) */
|
||||
source.setItemStat(EvolutionSyncSource::ITEM_REMOTE,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
EvolutionSyncSource::ITEM_CONFLICT_SERVER_WON,
|
||||
extra1);
|
||||
source.setItemStat(EvolutionSyncSource::ITEM_REMOTE,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
EvolutionSyncSource::ITEM_CONFLICT_CLIENT_WON,
|
||||
extra2);
|
||||
source.setItemStat(EvolutionSyncSource::ITEM_REMOTE,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
EvolutionSyncSource::ITEM_CONFLICT_DUPLICATED,
|
||||
extra3);
|
||||
break;
|
||||
|
@ -852,11 +841,11 @@ void EvolutionSyncClient::displaySourceProgress(sysync::TEngineProgressEventType
|
|||
/* datastore statistics for data volume (extra1=outgoing bytes,
|
||||
extra2=incoming bytes) */
|
||||
source.setItemStat(EvolutionSyncSource::ITEM_LOCAL,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
EvolutionSyncSource::ITEM_SENT_BYTES,
|
||||
extra1);
|
||||
source.setItemStat(EvolutionSyncSource::ITEM_LOCAL,
|
||||
EvolutionSyncSource::ITEM_STATE_ANY,
|
||||
EvolutionSyncSource::ITEM_ANY,
|
||||
EvolutionSyncSource::ITEM_RECEIVED_BYTES,
|
||||
extra2);
|
||||
break;
|
||||
|
@ -949,21 +938,6 @@ EvolutionSyncSource *EvolutionSyncClient::findSource(const char *name)
|
|||
return m_sourceListPtr ? (*m_sourceListPtr)[name] : NULL;
|
||||
}
|
||||
|
||||
AbstractSyncSourceConfig* EvolutionSyncClient::getAbstractSyncSourceConfig(const char* name) const
|
||||
{
|
||||
return m_sourceListPtr ? (*m_sourceListPtr)[name] : NULL;
|
||||
}
|
||||
|
||||
AbstractSyncSourceConfig* EvolutionSyncClient::getAbstractSyncSourceConfig(unsigned int i) const
|
||||
{
|
||||
return m_sourceListPtr ? (*m_sourceListPtr)[i] : NULL;
|
||||
}
|
||||
|
||||
unsigned int EvolutionSyncClient::getAbstractSyncSourceConfigsCount() const
|
||||
{
|
||||
return m_sourceListPtr ? m_sourceListPtr->size() : 0;
|
||||
}
|
||||
|
||||
void EvolutionSyncClient::setConfigFilter(bool sync, const FilterConfigNode::ConfigFilter &filter)
|
||||
{
|
||||
map<string, string>::const_iterator hasSync = filter.find(EvolutionSyncSourceConfig::m_sourcePropSync.getName());
|
||||
|
@ -1146,7 +1120,7 @@ int EvolutionSyncClient::sync()
|
|||
}
|
||||
|
||||
// redirect logging as soon as possible
|
||||
SourceList sourceList(m_server, m_doLogging, *this, m_quiet);
|
||||
SourceList sourceList(m_server, m_doLogging, m_quiet);
|
||||
m_sourceListPtr = &sourceList;
|
||||
|
||||
try {
|
||||
|
@ -1189,29 +1163,13 @@ int EvolutionSyncClient::sync()
|
|||
}
|
||||
|
||||
// give derived class also a chance to update the configs
|
||||
prepare(sourceList.getSourceArray());
|
||||
prepare(sourceList);
|
||||
|
||||
// ready to go: dump initial databases and prepare for final report
|
||||
sourceList.syncPrepare();
|
||||
|
||||
#ifndef SYNTHESIS
|
||||
// do it
|
||||
res = SyncClient::sync(*this, sourceList.getSourceArray());
|
||||
|
||||
// store modified properties: must be done even after failed
|
||||
// sync because the source's anchor might have been reset
|
||||
flush();
|
||||
|
||||
if (res) {
|
||||
if (getLastErrorCode() && getLastErrorMsg() && getLastErrorMsg()[0]) {
|
||||
throwError(getLastErrorMsg());
|
||||
}
|
||||
// no error code/description?!
|
||||
throwError("sync failed without an error description, check log");
|
||||
}
|
||||
#else
|
||||
// run sync session
|
||||
doSync();
|
||||
#endif
|
||||
|
||||
// all went well: print final report before cleaning up
|
||||
sourceList.syncDone(true);
|
||||
|
@ -1233,13 +1191,11 @@ int EvolutionSyncClient::sync()
|
|||
return res;
|
||||
}
|
||||
|
||||
void EvolutionSyncClient::prepare(SyncSource **sources) {
|
||||
void EvolutionSyncClient::prepare(const std::vector<EvolutionSyncSource *> &sources) {
|
||||
if (m_syncMode != SYNC_NONE) {
|
||||
for (SyncSource **source = sources;
|
||||
*source;
|
||||
source++) {
|
||||
(*source)->setPreferredSyncMode(m_syncMode);
|
||||
}
|
||||
// BOOST_FOREACH(EvolutionSyncSource *source, sources) {
|
||||
// @TODO source->setPreferredSyncMode(m_syncMode);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1251,6 +1207,35 @@ void EvolutionSyncClient::doSync()
|
|||
sysync::KeyH subkeyH;
|
||||
string s;
|
||||
|
||||
// create new sync engine for the duration of this function
|
||||
class SwapEngine {
|
||||
EvolutionSyncClient &m_client;
|
||||
sysync::TEngineModuleBridge *m_oldengine;
|
||||
|
||||
public:
|
||||
SwapEngine(EvolutionSyncClient &client) :
|
||||
m_client(client) {
|
||||
sysync::TEngineModuleBridge *syncengine = new sysync::TEngineModuleBridge();
|
||||
sysync::TSyError err;
|
||||
if (!syncengine ||
|
||||
(err = syncengine->Connect("[]", 0,
|
||||
sysync::DBG_PLUGIN_NONE|
|
||||
sysync::DBG_PLUGIN_INT|
|
||||
sysync::DBG_PLUGIN_DB|
|
||||
sysync::DBG_PLUGIN_EXOT|
|
||||
sysync::DBG_PLUGIN_ALL))) {
|
||||
m_client.throwError("create Syntesis engine for sync session");
|
||||
}
|
||||
m_oldengine = m_client.swapEngine(syncengine);
|
||||
}
|
||||
|
||||
~SwapEngine() {
|
||||
sysync::TEngineModuleBridge *syncengine =
|
||||
m_client.swapEngine(m_oldengine);
|
||||
delete syncengine;
|
||||
}
|
||||
} swapengine(*this);
|
||||
|
||||
err = getEngine().OpenKeyByPath(keyH, NULL, "/configvars", 0);
|
||||
if (err) {
|
||||
throwError("open config vars");
|
||||
|
@ -1551,7 +1536,7 @@ void EvolutionSyncClient::status()
|
|||
throwError("cannot proceed without configuration");
|
||||
}
|
||||
|
||||
SourceList sourceList(m_server, false, *this, false);
|
||||
SourceList sourceList(m_server, false, false);
|
||||
initSources(sourceList);
|
||||
BOOST_FOREACH(EvolutionSyncSource *source, sourceList) {
|
||||
source->checkPassword(*this);
|
||||
|
@ -1560,7 +1545,7 @@ void EvolutionSyncClient::status()
|
|||
source->open();
|
||||
}
|
||||
|
||||
sourceList.setLogdir(getLogDir(), 0, LOG_LEVEL_NONE);
|
||||
sourceList.setLogdir(getLogDir(), 0, 0);
|
||||
LoggerBase::instance().setLevel(Logger::INFO);
|
||||
string prevLogdir = sourceList.getPrevLogdir();
|
||||
bool found = access(prevLogdir.c_str(), R_OK|X_OK) == 0;
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
|
||||
#include "EvolutionSmartPtr.h"
|
||||
#include "SyncEvolutionConfig.h"
|
||||
#include <client/SyncClient.h>
|
||||
#include <spds/SyncManagerConfig.h>
|
||||
#include "SyncML.h"
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
@ -42,7 +41,7 @@ namespace sysync {
|
|||
* implementation of those uses stdin/out.
|
||||
*
|
||||
*/
|
||||
class EvolutionSyncClient : public SyncClient, public EvolutionSyncConfig, public ConfigUserInterface {
|
||||
class EvolutionSyncClient : public EvolutionSyncConfig, public ConfigUserInterface {
|
||||
const string m_server;
|
||||
const set<string> m_sources;
|
||||
const bool m_doLogging;
|
||||
|
@ -146,11 +145,6 @@ class EvolutionSyncClient : public SyncClient, public EvolutionSyncConfig, publi
|
|||
*/
|
||||
static EvolutionSyncSource *findSource(const char *name);
|
||||
|
||||
/* AbstractSyncConfig API */
|
||||
virtual AbstractSyncSourceConfig* getAbstractSyncSourceConfig(const char* name) const;
|
||||
virtual AbstractSyncSourceConfig* getAbstractSyncSourceConfig(unsigned int i) const;
|
||||
virtual unsigned int getAbstractSyncSourceConfigsCount() const;
|
||||
|
||||
/**
|
||||
* intercept config filters
|
||||
*
|
||||
|
@ -166,6 +160,12 @@ class EvolutionSyncClient : public SyncClient, public EvolutionSyncConfig, publi
|
|||
sysync::TEngineModuleBridge &getEngine() { return *m_engine; }
|
||||
const sysync::TEngineModuleBridge &getEngine() const { return *m_engine; }
|
||||
|
||||
sysync::TEngineModuleBridge *swapEngine(sysync::TEngineModuleBridge *newengine) {
|
||||
sysync::TEngineModuleBridge *oldengine = m_engine;
|
||||
m_engine = newengine;
|
||||
return oldengine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return skeleton Synthesis client XML configuration.
|
||||
*
|
||||
|
@ -216,7 +216,7 @@ class EvolutionSyncClient : public SyncClient, public EvolutionSyncConfig, publi
|
|||
*
|
||||
* @param sources a NULL terminated array of all active sources
|
||||
*/
|
||||
virtual void prepare(SyncSource **sources);
|
||||
virtual void prepare(const std::vector<EvolutionSyncSource *> &sources);
|
||||
|
||||
/**
|
||||
* instantiate transport agent
|
||||
|
|
|
@ -77,9 +77,7 @@ void EvolutionSyncSource::handleException()
|
|||
try {
|
||||
throw;
|
||||
} catch (std::exception &ex) {
|
||||
setErrorF(getLastErrorCode() == ERR_NONE ? ERR_UNSPECIFIED : getLastErrorCode(),
|
||||
"%s", ex.what());
|
||||
SE_LOG_ERROR(this, NULL, "%s", getLastErrorMsg());
|
||||
SE_LOG_ERROR(this, NULL, "%s", ex.what());
|
||||
setFailed(true);
|
||||
}
|
||||
}
|
||||
|
@ -342,20 +340,19 @@ void EvolutionSyncSource::getDatastoreXML(string &xml)
|
|||
xml = xmlstream.str();
|
||||
}
|
||||
|
||||
int EvolutionSyncSource::beginSync() throw()
|
||||
SyncMLStatus EvolutionSyncSource::beginSync(SyncMode mode) throw()
|
||||
{
|
||||
SyncMode mode = getSyncMode();
|
||||
|
||||
// start background thread if not running yet:
|
||||
// necessary to catch problems with Evolution backend
|
||||
EvolutionSyncClient::startLoopThread();
|
||||
|
||||
try {
|
||||
// @TODO: force slow sync if something goes wrong
|
||||
//
|
||||
// reset anchors now, once we proceed there is no going back
|
||||
// (because the change marker is about to be moved)
|
||||
// and the sync must either complete or result in a slow sync
|
||||
// the next time
|
||||
getConfig().setLast(0);
|
||||
|
||||
const char *error = getenv("SYNCEVOLUTION_BEGIN_SYNC_ERROR");
|
||||
if (error && strstr(error, getName())) {
|
||||
|
@ -409,9 +406,9 @@ int EvolutionSyncSource::beginSync() throw()
|
|||
rewindItems();
|
||||
} catch( ... ) {
|
||||
handleException();
|
||||
return 1;
|
||||
return STATUS_FATAL;
|
||||
}
|
||||
return 0;
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
void EvolutionSyncSource::rewindItems() throw()
|
||||
|
@ -419,19 +416,19 @@ void EvolutionSyncSource::rewindItems() throw()
|
|||
m_allItems.rewind();
|
||||
}
|
||||
|
||||
EvolutionSyncSource::NextItemState EvolutionSyncSource::nextItem(string *data, string &luid) throw()
|
||||
SyncItem::State EvolutionSyncSource::nextItem(string *data, string &luid) throw()
|
||||
{
|
||||
/** @TODO: avoid reading data if not necessary */
|
||||
SyncItem *item = m_allItems.iterate();
|
||||
NextItemState state = ITEM_EOF;
|
||||
SyncItem::State state = SyncItem::NO_MORE_ITEMS;
|
||||
|
||||
if (item) {
|
||||
if (m_newItems.find(item->getKey()) != m_newItems.end()) {
|
||||
state = ITEM_NEW;
|
||||
state = SyncItem::NEW;
|
||||
} else if (m_updatedItems.find(item->getKey()) != m_updatedItems.end()) {
|
||||
state = ITEM_UPDATED;
|
||||
state = SyncItem::UPDATED;
|
||||
} else {
|
||||
state = ITEM_UNCHANGED;
|
||||
state = SyncItem::UNCHANGED;
|
||||
}
|
||||
if (data) {
|
||||
data->assign((const char *)item->getData(), item->getDataSize());
|
||||
|
@ -441,7 +438,7 @@ EvolutionSyncSource::NextItemState EvolutionSyncSource::nextItem(string *data, s
|
|||
return state;
|
||||
}
|
||||
|
||||
int EvolutionSyncSource::endSync() throw()
|
||||
SyncMLStatus EvolutionSyncSource::endSync() throw()
|
||||
{
|
||||
try {
|
||||
endSyncThrow();
|
||||
|
@ -449,41 +446,31 @@ int EvolutionSyncSource::endSync() throw()
|
|||
handleException();
|
||||
}
|
||||
|
||||
// Do _not_ tell the caller (SyncManager) if an error occurred
|
||||
// @TODO: Do _not_ tell the caller (SyncManager) if an error occurred
|
||||
// because that causes Sync4jClient to abort processing for all
|
||||
// sync sources. Instead deal with failed sync sources in
|
||||
// EvolutionSyncClient::sync().
|
||||
return 0;
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
void EvolutionSyncSource::setItemStatus(const char *key, int status) throw()
|
||||
{
|
||||
try {
|
||||
// TODO: logging
|
||||
setItemStatusThrow(key, status);
|
||||
} catch (...) {
|
||||
handleException();
|
||||
}
|
||||
}
|
||||
|
||||
int EvolutionSyncSource::addItem(SyncItem& item) throw()
|
||||
SyncMLStatus EvolutionSyncSource::addItem(SyncItem& item) throw()
|
||||
{
|
||||
return processItem("add", &EvolutionSyncSource::addItemThrow, item, true);
|
||||
}
|
||||
|
||||
int EvolutionSyncSource::updateItem(SyncItem& item) throw()
|
||||
SyncMLStatus EvolutionSyncSource::updateItem(SyncItem& item) throw()
|
||||
{
|
||||
return processItem("update", &EvolutionSyncSource::updateItemThrow, item, true);
|
||||
}
|
||||
|
||||
int EvolutionSyncSource::deleteItem(SyncItem& item) throw()
|
||||
SyncMLStatus EvolutionSyncSource::deleteItem(SyncItem& item) throw()
|
||||
{
|
||||
return processItem("delete", &EvolutionSyncSource::deleteItemThrow, item, false);
|
||||
}
|
||||
|
||||
int EvolutionSyncSource::removeAllItems() throw()
|
||||
SyncMLStatus EvolutionSyncSource::removeAllItems() throw()
|
||||
{
|
||||
int status = 0;
|
||||
SyncMLStatus status = STATUS_OK;
|
||||
|
||||
try {
|
||||
BOOST_FOREACH(const string &key, m_allItems) {
|
||||
|
@ -495,17 +482,17 @@ int EvolutionSyncSource::removeAllItems() throw()
|
|||
}
|
||||
} catch (...) {
|
||||
handleException();
|
||||
status = 1;
|
||||
status = STATUS_FATAL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int EvolutionSyncSource::processItem(const char *action,
|
||||
int (EvolutionSyncSource::*func)(SyncItem& item),
|
||||
SyncItem& item,
|
||||
bool needData) throw()
|
||||
SyncMLStatus EvolutionSyncSource::processItem(const char *action,
|
||||
SyncMLStatus (EvolutionSyncSource::*func)(SyncItem& item),
|
||||
SyncItem& item,
|
||||
bool needData) throw()
|
||||
{
|
||||
int status = STC_COMMAND_FAILED;
|
||||
SyncMLStatus status = STATUS_FATAL;
|
||||
|
||||
try {
|
||||
logItem(item, action);
|
||||
|
@ -514,7 +501,7 @@ int EvolutionSyncSource::processItem(const char *action,
|
|||
// Shouldn't happen, but it did with one server and thus this
|
||||
// security check was added to prevent segfaults.
|
||||
logItem(item, "ignored due to missing data");
|
||||
status = STC_OK;
|
||||
status = STATUS_OK;
|
||||
} else {
|
||||
status = (this->*func)(item);
|
||||
}
|
||||
|
@ -526,21 +513,6 @@ int EvolutionSyncSource::processItem(const char *action,
|
|||
return status;
|
||||
}
|
||||
|
||||
void EvolutionSyncSource::setItemStatusThrow(const char *key, int status)
|
||||
{
|
||||
switch (status) {
|
||||
case STC_ALREADY_EXISTS:
|
||||
// found pair during slow sync, that's okay
|
||||
break;
|
||||
default:
|
||||
if (status < 200 || status > 300) {
|
||||
SE_LOG_ERROR(this, NULL, "unexpected SyncML status response %d for item %.80s\n",
|
||||
status, key);
|
||||
setFailed(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EvolutionSyncSource::sleepSinceModification(int seconds)
|
||||
{
|
||||
time_t current = time(NULL);
|
||||
|
@ -670,16 +642,13 @@ SyncItem *EvolutionSyncSource::Items::iterate()
|
|||
if (&m_source.m_deletedItems == this) {
|
||||
// just tell caller the uid of the deleted item
|
||||
// and the type that it probably had
|
||||
SyncItem *item = new SyncItem( uid.c_str() );
|
||||
item->setDataType(m_source.getMimeType());
|
||||
return item;
|
||||
cxxptr<SyncItem> item(new SyncItem());
|
||||
item->setKey(uid);
|
||||
return item.release();
|
||||
} else {
|
||||
// retrieve item with all its data
|
||||
try {
|
||||
cxxptr<SyncItem> item(m_source.createItem(uid));
|
||||
if (item) {
|
||||
item->setState(m_state);
|
||||
}
|
||||
return item.release();
|
||||
} catch(...) {
|
||||
m_source.handleException();
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "SyncEvolutionConfig.h"
|
||||
#include "EvolutionSmartPtr.h"
|
||||
#include "Logging.h"
|
||||
#include "eds_abi_wrapper.h"
|
||||
#include "SyncML.h"
|
||||
using namespace SyncEvolution;
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
@ -21,11 +23,6 @@ using namespace std;
|
|||
|
||||
#include <time.h>
|
||||
|
||||
#include <spds/SyncSource.h>
|
||||
#include <spdm/ManagementNode.h>
|
||||
#include "Logging.h"
|
||||
|
||||
#include "eds_abi_wrapper.h"
|
||||
|
||||
class EvolutionSyncSource;
|
||||
#include <synthesis/sync_declarations.h>
|
||||
|
@ -242,7 +239,7 @@ class RegisterSyncSourceTest
|
|||
* sources which normally use one format internally, but also
|
||||
* support another one (EvolutionContactSource).
|
||||
*/
|
||||
static int dump(ClientTest &client, SyncSource &source, const char *file);
|
||||
static int dump(ClientTest &client, EvolutionSyncSource &source, const char *file);
|
||||
|
||||
const string m_configName;
|
||||
const string m_testCaseName;
|
||||
|
@ -263,7 +260,6 @@ class TestRegistry : public vector<const RegisterSyncSourceTest *>
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* SyncEvolution accesses all sources through this interface. This
|
||||
* class also implements common functionality for all SyncSources:
|
||||
|
@ -284,25 +280,23 @@ class TestRegistry : public vector<const RegisterSyncSourceTest *>
|
|||
*
|
||||
* It also adds Evolution specific interfaces and utility functions.
|
||||
*/
|
||||
class EvolutionSyncSource : public SyncSource, public EvolutionSyncSourceConfig, public LoggerBase
|
||||
class EvolutionSyncSource : public EvolutionSyncSourceConfig, public LoggerBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates a new Evolution sync source.
|
||||
*/
|
||||
EvolutionSyncSource(const EvolutionSyncSourceParams ¶ms) :
|
||||
SyncSource(params.m_name.c_str(), NULL),
|
||||
EvolutionSyncSourceConfig(params.m_name, params.m_nodes),
|
||||
m_changeId( params.m_changeId ),
|
||||
m_allItems( *this, "existing", SYNC_STATE_NONE ),
|
||||
m_newItems( *this, "new", SYNC_STATE_NEW ),
|
||||
m_updatedItems( *this, "updated", SYNC_STATE_UPDATED ),
|
||||
m_deletedItems( *this, "deleted", SYNC_STATE_DELETED ),
|
||||
m_allItems( *this, "existing", SyncItem::NONE ),
|
||||
m_newItems( *this, "new", SyncItem::NEW ),
|
||||
m_updatedItems( *this, "updated", SyncItem::UPDATED ),
|
||||
m_deletedItems( *this, "deleted", SyncItem::DELETED ),
|
||||
m_isModified( false ),
|
||||
m_modTimeStamp(0),
|
||||
m_hasFailed( false )
|
||||
{
|
||||
setConfig(this);
|
||||
memset(m_stat, 0, sizeof(m_stat));
|
||||
}
|
||||
virtual ~EvolutionSyncSource() {}
|
||||
|
@ -412,8 +406,25 @@ class EvolutionSyncSource : public SyncSource, public EvolutionSyncSourceConfig,
|
|||
* (between SyncEvolution_Module_CreateContext() and
|
||||
* SyncEvolution_Module_DeleteContext())
|
||||
*/
|
||||
sysync::SDK_InterfaceType *getSynthesisAPI() { return m_synthesisAPI; }
|
||||
void setSynthesisAPI(sysync::SDK_InterfaceType *synthesisAPI) { m_synthesisAPI = synthesisAPI; }
|
||||
sysync::SDK_InterfaceType *getSynthesisAPI() {
|
||||
return m_synthesisAPI.empty() ?
|
||||
NULL :
|
||||
m_synthesisAPI[m_synthesisAPI.size() - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* change the Synthesis API that is used by the source
|
||||
*/
|
||||
void pushSynthesisAPI(sysync::SDK_InterfaceType *synthesisAPI) {
|
||||
m_synthesisAPI.push_back(synthesisAPI);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove latest Synthesis API and return to previous one (if any)
|
||||
*/
|
||||
void popSynthesisAPI() {
|
||||
m_synthesisAPI.pop_back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function, to be called inside a catch() block of
|
||||
|
@ -519,13 +530,6 @@ class EvolutionSyncSource : public SyncSource, public EvolutionSyncSourceConfig,
|
|||
virtual SyncItem* getNextItemKey() throw() { return m_allItems.iterate(); }
|
||||
/**@}*/
|
||||
|
||||
enum NextItemState {
|
||||
ITEM_UNCHANGED, /**< item is unchanged since last sync */
|
||||
ITEM_NEW, /**< new item */
|
||||
ITEM_UPDATED, /**< item was updated since last sync */
|
||||
ITEM_EOF, /**< no more items */
|
||||
ITEM_ERROR /**< item couldn't be extracted */
|
||||
};
|
||||
/**
|
||||
* get information about next item
|
||||
*
|
||||
|
@ -533,7 +537,7 @@ class EvolutionSyncSource : public SyncSource, public EvolutionSyncSourceConfig,
|
|||
* @retval luid local ID of item
|
||||
* @return status of item or error
|
||||
*/
|
||||
virtual NextItemState nextItem(string *data, string &luid) throw();
|
||||
virtual SyncItem::State nextItem(string *data, string &luid) throw();
|
||||
|
||||
/**
|
||||
* restart reading all items, automatically called at end of beginSync()
|
||||
|
@ -545,12 +549,11 @@ class EvolutionSyncSource : public SyncSource, public EvolutionSyncSourceConfig,
|
|||
* and implemented via the corresponding *Throw() calls
|
||||
*/
|
||||
/**@{*/
|
||||
virtual int beginSync() throw();
|
||||
virtual int endSync() throw();
|
||||
virtual void setItemStatus(const char *key, int status) throw();
|
||||
virtual int addItem(SyncItem& item) throw();
|
||||
virtual int updateItem(SyncItem& item) throw();
|
||||
virtual int deleteItem(SyncItem& item) throw();
|
||||
virtual SyncMLStatus beginSync(SyncMode mode) throw();
|
||||
virtual SyncMLStatus endSync() throw();
|
||||
virtual SyncMLStatus addItem(SyncItem& item) throw();
|
||||
virtual SyncMLStatus updateItem(SyncItem& item) throw();
|
||||
virtual SyncMLStatus deleteItem(SyncItem& item) throw();
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
|
@ -564,13 +567,7 @@ class EvolutionSyncSource : public SyncSource, public EvolutionSyncSourceConfig,
|
|||
*
|
||||
* @return 0 for success, non-zero for failure
|
||||
*/
|
||||
virtual int removeAllItems() throw();
|
||||
|
||||
/**
|
||||
* Disambiguate getName(): we have inherited it from both SyncSource and
|
||||
* AbstractSyncSourceConfig. Both must return the same string.
|
||||
*/
|
||||
const char *getName() throw() { return SyncSource::getName(); }
|
||||
virtual SyncMLStatus removeAllItems() throw();
|
||||
|
||||
/**
|
||||
* source specific part of beginSync() - throws exceptions in case of error
|
||||
|
@ -589,10 +586,9 @@ class EvolutionSyncSource : public SyncSource, public EvolutionSyncSourceConfig,
|
|||
*/
|
||||
/**@{*/
|
||||
virtual void endSyncThrow() = 0;
|
||||
virtual void setItemStatusThrow(const char *key, int status);
|
||||
virtual int addItemThrow(SyncItem& item) = 0;
|
||||
virtual int updateItemThrow(SyncItem& item) = 0;
|
||||
virtual int deleteItemThrow(SyncItem& item) = 0;
|
||||
virtual SyncMLStatus addItemThrow(SyncItem& item) = 0;
|
||||
virtual SyncMLStatus updateItemThrow(SyncItem& item) = 0;
|
||||
virtual SyncMLStatus deleteItemThrow(SyncItem& item) = 0;
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
|
@ -690,12 +686,10 @@ class EvolutionSyncSource : public SyncSource, public EvolutionSyncSourceConfig,
|
|||
ITEM_LOCATION_MAX
|
||||
};
|
||||
enum ItemState {
|
||||
// TODO: remove _STATE_ once we got rid of Funambol header files;
|
||||
// currently those have conflicting defines
|
||||
ITEM_STATE_ADDED,
|
||||
ITEM_STATE_UPDATED,
|
||||
ITEM_STATE_REMOVED,
|
||||
ITEM_STATE_ANY,
|
||||
ITEM_ADDED,
|
||||
ITEM_UPDATED,
|
||||
ITEM_REMOVED,
|
||||
ITEM_ANY,
|
||||
ITEM_STATE_MAX
|
||||
};
|
||||
enum ItemResult {
|
||||
|
@ -736,10 +730,10 @@ class EvolutionSyncSource : public SyncSource, public EvolutionSyncSourceConfig,
|
|||
const_iterator m_it;
|
||||
EvolutionSyncSource &m_source;
|
||||
const string m_type;
|
||||
const SyncState m_state;
|
||||
const SyncItem::State m_state;
|
||||
|
||||
public:
|
||||
Items( EvolutionSyncSource &source, const string &type, SyncState state ) :
|
||||
Items( EvolutionSyncSource &source, const string &type, SyncItem::State state ) :
|
||||
m_source( source ),
|
||||
m_type( type ),
|
||||
m_state( state )
|
||||
|
@ -790,10 +784,10 @@ class EvolutionSyncSource : public SyncSource, public EvolutionSyncSourceConfig,
|
|||
/**
|
||||
* private wrapper function for add/delete/updateItemThrow()
|
||||
*/
|
||||
int processItem(const char *action,
|
||||
int (EvolutionSyncSource::*func)(SyncItem& item),
|
||||
SyncItem& item,
|
||||
bool needData) throw();
|
||||
SyncMLStatus processItem(const char *action,
|
||||
SyncMLStatus (EvolutionSyncSource::*func)(SyncItem& item),
|
||||
SyncItem& item,
|
||||
bool needData) throw();
|
||||
|
||||
/** time stamp of latest database modification, for sleepSinceModification() */
|
||||
time_t m_modTimeStamp;
|
||||
|
@ -808,7 +802,7 @@ class EvolutionSyncSource : public SyncSource, public EvolutionSyncSourceConfig,
|
|||
* SyncEvolution_Module_DeleteContext(), in other words, while
|
||||
* the engine is running.
|
||||
*/
|
||||
sysync::SDK_InterfaceType *m_synthesisAPI;
|
||||
std::vector<sysync::SDK_InterfaceType *> m_synthesisAPI;
|
||||
|
||||
/** storage for getItemStat() */
|
||||
int m_stat[ITEM_LOCATION_MAX][ITEM_STATE_MAX][ITEM_RESULT_MAX];
|
||||
|
|
|
@ -13,16 +13,6 @@ else
|
|||
noinst_LTLIBRARIES = libsyncevolution.la
|
||||
endif
|
||||
|
||||
VOCL_SOURCES = \
|
||||
vocl/VObject.h \
|
||||
vocl/VProperty.h \
|
||||
vocl/VConverter.h \
|
||||
vocl/posixadapter.h \
|
||||
\
|
||||
vocl/VObject.cpp \
|
||||
vocl/VProperty.cpp \
|
||||
vocl/VConverter.cpp
|
||||
|
||||
CORE_SOURCES = \
|
||||
ConfigTree.h \
|
||||
ConfigNode.h \
|
||||
|
@ -78,9 +68,8 @@ CORE_SOURCES = \
|
|||
FileConfigTree.cpp \
|
||||
\
|
||||
TrackingSyncSource.h \
|
||||
TrackingSyncSource.cpp \
|
||||
\
|
||||
$(VOCL_SOURCES)
|
||||
TrackingSyncSource.cpp
|
||||
|
||||
|
||||
libsyncevolution_la_SOURCES = $(CORE_SOURCES)
|
||||
libsyncevolution_la_LIBADD = @EPACKAGE_LIBS@ @GLIB_LIBS@ @FUNAMBOL_LIBS@ $(TRANSPORT_LIBS) @LIBS@ $(SYNTHESIS_LIBS)
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
#include "FilterConfigNode.h"
|
||||
|
||||
#include "spds/AbstractSyncConfig.h"
|
||||
#include "spds/AbstractSyncSourceConfig.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
|
@ -446,7 +444,7 @@ class ConfigStringCache {
|
|||
* uses a FileConfigTree instance. Other implementations would be
|
||||
* possible.
|
||||
*/
|
||||
class EvolutionSyncConfig : public AbstractSyncConfig {
|
||||
class EvolutionSyncConfig {
|
||||
public:
|
||||
/**
|
||||
* Opens the configuration for a specific server,
|
||||
|
@ -627,10 +625,6 @@ class EvolutionSyncConfig : public AbstractSyncConfig {
|
|||
*/
|
||||
/**@{*/
|
||||
|
||||
virtual AbstractSyncSourceConfig* getAbstractSyncSourceConfig(const char* name) const { return NULL; }
|
||||
virtual AbstractSyncSourceConfig* getAbstractSyncSourceConfig(unsigned int i) const { return NULL; }
|
||||
virtual unsigned int getAbstractSyncSourceConfigsCount() const { return 0; }
|
||||
|
||||
virtual const char* getUsername() const;
|
||||
virtual void setUsername(const string &value, bool temporarily = false);
|
||||
virtual const char* getPassword() const;
|
||||
|
@ -790,7 +784,7 @@ struct ConstSyncSourceNodes {
|
|||
* Some properties are not configurable and have to be provided
|
||||
* by derived classes.
|
||||
*/
|
||||
class EvolutionSyncSourceConfig : public AbstractSyncSourceConfig {
|
||||
class EvolutionSyncSourceConfig {
|
||||
public:
|
||||
EvolutionSyncSourceConfig(const string &name, const SyncSourceNodes &nodes);
|
||||
|
||||
|
@ -944,9 +938,9 @@ class EvolutionSyncSourceConfig : public AbstractSyncSourceConfig {
|
|||
* returning an empty array implies that it supports all aspects.
|
||||
* This is the default implementation of this call.
|
||||
*
|
||||
* @return an ArrayList of CTCap
|
||||
* @TODO: per-source capabilities
|
||||
*/
|
||||
virtual const ArrayList& getCtCaps() const { static const ArrayList dummy; return dummy; }
|
||||
// virtual const ArrayList& getCtCaps() const { static const ArrayList dummy; return dummy; }
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
* Copyright (C) 2008 Patrick Ohly
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "SyncEvolutionUtil.h"
|
||||
#include "EvolutionSyncClient.h"
|
||||
#include <base/test.h>
|
||||
|
||||
#include <boost/scoped_array.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
#ifndef INCL_SYNCEVOLUTION_UTIL
|
||||
# define INCL_SYNCEVOLUTION_UTIL
|
||||
|
||||
#include <base/test.h>
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
|
|
116
src/core/SyncML.h
Normal file
116
src/core/SyncML.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Patrick Ohly
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* 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,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY, TITLE, NONINFRINGEMENT or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef INCL_SYNCML
|
||||
#define INCL_SYNCML
|
||||
|
||||
#include <string>
|
||||
|
||||
enum SyncMode {
|
||||
SYNC_NONE,
|
||||
SYNC_TWO_WAY,
|
||||
SYNC_SLOW,
|
||||
SYNC_ONE_WAY_FROM_CLIENT,
|
||||
SYNC_REFRESH_FROM_CLIENT,
|
||||
SYNC_ONE_WAY_FROM_SERVER,
|
||||
SYNC_REFRESH_FROM_SERVER,
|
||||
SYNC_MODE_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* simple container for SyncML items
|
||||
*/
|
||||
class SyncItem {
|
||||
private:
|
||||
/**
|
||||
* Data, might not be text. nul-byte not included in data size.
|
||||
*/
|
||||
std::string m_data;
|
||||
/**
|
||||
* Local unique ID of the item.
|
||||
*/
|
||||
std::string m_luid;
|
||||
/**
|
||||
* Empty string indicates the default format specified for a sync
|
||||
* source. Might be set to a mime type (e.g. "text/calendar") to
|
||||
* override the default format.
|
||||
*/
|
||||
std::string m_datatype;
|
||||
|
||||
|
||||
public:
|
||||
std::string getKey() const { return m_luid; }
|
||||
void setKey(const std::string &key) { m_luid = key; }
|
||||
const char *getData() const { return m_data.c_str(); }
|
||||
size_t getDataSize() const { return m_data.size(); }
|
||||
void setData(const char *data, size_t size) { m_data.assign(data, size); }
|
||||
void setDataType(const std::string &datatype) { m_datatype = datatype; }
|
||||
std::string getDataType() const { return m_datatype; }
|
||||
|
||||
/** result of change tracking and iteration over items */
|
||||
enum State {
|
||||
/** undefined state */
|
||||
NONE,
|
||||
/** not changed */
|
||||
UNCHANGED,
|
||||
/** item added */
|
||||
NEW,
|
||||
/** item updated */
|
||||
UPDATED,
|
||||
/** item deleted (only key, but no data available) */
|
||||
DELETED,
|
||||
/** end of iteration */
|
||||
NO_MORE_ITEMS,
|
||||
/** error reading item */
|
||||
ERROR,
|
||||
|
||||
/** end of enumeration */
|
||||
STATE_MAX,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* result of SyncML operations, same codes as in HTTP and the Synthesis engine
|
||||
*/
|
||||
enum SyncMLStatus {
|
||||
/** ok */
|
||||
STATUS_OK = 0,
|
||||
|
||||
/** no content / end of file / end of iteration / empty/NULL value */
|
||||
STATUS_NO_CONTENT = 204,
|
||||
/** external data has been merged */
|
||||
STATUS_DATA_MERGED = 207,
|
||||
|
||||
/** forbidden / access denied */
|
||||
STATUS_FORBIDDEN = 403,
|
||||
/** object not found / unassigned field */
|
||||
STATUS_NOT_FOUND = 404,
|
||||
/** command not allowed */
|
||||
STATUS_COMMAND_NOT_ALLOWED = 405,
|
||||
/** command failed / fatal DB error */
|
||||
STATUS_FATAL = 500,
|
||||
/** general DB error */
|
||||
STATUS_DATASTORE_FAILURE = 510,
|
||||
/** database / memory full error */
|
||||
STATUS_FULL = 420,
|
||||
|
||||
STATUS_MAX = 0x7FFFFFF
|
||||
};
|
||||
|
||||
#endif // INCL_SYNCML
|
|
@ -58,7 +58,7 @@ TSyError SyncEvolution_Module_CreateContext( CContext *mContext, cAppCharP mod
|
|||
TSyError err = LOCERR_WRONGUSAGE;
|
||||
EvolutionSyncSource *source = EvolutionSyncClient::findSource(mContextName);
|
||||
if (source) {
|
||||
source->setSynthesisAPI(mCB);
|
||||
source->pushSynthesisAPI(mCB);
|
||||
*mContext = (CContext)source;
|
||||
err = LOCERR_OK;
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ TSyError SyncEvolution_Module_DeleteContext( CContext mContext )
|
|||
{
|
||||
EvolutionSyncSource *source = MoC(mContext);
|
||||
DEBUG_DB(source->getSynthesisAPI(), MyDB, Mo_DC, "'%s'", source->getName());
|
||||
source->setSynthesisAPI(NULL);
|
||||
source->popSynthesisAPI();
|
||||
return LOCERR_OK;
|
||||
}
|
||||
|
||||
|
@ -404,7 +404,7 @@ TSyError SyncEvolution_CreateContext( CContext *aContext, cAppCharP aContextName
|
|||
TSyError err = LOCERR_WRONGUSAGE;
|
||||
EvolutionSyncSource *source = EvolutionSyncClient::findSource(aContextName);
|
||||
if (source) {
|
||||
source->setSynthesisAPI(aCB);
|
||||
source->pushSynthesisAPI(aCB);
|
||||
*aContext = (CContext)source;
|
||||
err = LOCERR_OK;
|
||||
}
|
||||
|
@ -587,12 +587,7 @@ TSyError SyncEvolution_StartDataRead( CContext aContext, cAppCharP lastToken,
|
|||
|
||||
TSyError res;
|
||||
// tell EvolutionSyncSource to be prepared for anything
|
||||
source->setSyncMode(SYNC_NONE);
|
||||
if (source->beginSync()) {
|
||||
res = DB_Fatal;
|
||||
} else {
|
||||
res = LOCERR_OK;
|
||||
}
|
||||
res = source->beginSync(SYNC_NONE);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -607,14 +602,14 @@ TSyError SyncEvolution_ReadNextItemAsKey( CContext aContext, ItemID aID, KeyH aI
|
|||
TSyError res = LOCERR_OK;
|
||||
string luid;
|
||||
switch (source->nextItem(NULL, luid)) {
|
||||
case EvolutionSyncSource::ITEM_UNCHANGED:
|
||||
case SyncItem::UNCHANGED:
|
||||
*aStatus = ReadNextItem_Unchanged;
|
||||
break;
|
||||
case EvolutionSyncSource::ITEM_NEW:
|
||||
case EvolutionSyncSource::ITEM_UPDATED:
|
||||
case SyncItem::NEW:
|
||||
case SyncItem::UPDATED:
|
||||
*aStatus = ReadNextItem_Changed;
|
||||
break;
|
||||
case EvolutionSyncSource::ITEM_EOF:
|
||||
case SyncItem::NO_MORE_ITEMS:
|
||||
*aStatus = ReadNextItem_EOF;
|
||||
break;
|
||||
default:
|
||||
|
@ -731,15 +726,9 @@ TSyError SyncEvolution_InsertItemAsKey( CContext aContext, KeyH aItemKey, ItemID
|
|||
if (!res) {
|
||||
SyncItem item;
|
||||
item.setData(data, len);
|
||||
switch (source->addItem(item)) {
|
||||
case STC_CONFLICT_RESOLVED_WITH_MERGE:
|
||||
case STC_OK:
|
||||
newID->item = StrAlloc(item.getKey());
|
||||
newID->parent = StrAlloc("");
|
||||
break;
|
||||
default:
|
||||
res = DB_Fatal;
|
||||
}
|
||||
res = source->addItem(item);
|
||||
newID->item = StrAlloc(item.getKey().c_str());
|
||||
newID->parent = StrAlloc("");
|
||||
}
|
||||
|
||||
delete [] data;
|
||||
|
@ -778,16 +767,10 @@ TSyError SyncEvolution_UpdateItemAsKey( CContext aContext, KeyH aItemKey, cItemI
|
|||
SyncItem item;
|
||||
item.setData(data, len);
|
||||
item.setKey(aID->item);
|
||||
switch (source->updateItem(item)) {
|
||||
case STC_CONFLICT_RESOLVED_WITH_MERGE:
|
||||
case STC_OK:
|
||||
if (strcmp(item.getKey(), aID->item)) {
|
||||
updID->item = StrAlloc(item.getKey());
|
||||
updID->parent = StrAlloc("");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
res = DB_Fatal;
|
||||
res = source->updateItem(item);
|
||||
if (item.getKey() == aID->item) {
|
||||
updID->item = StrAlloc(item.getKey().c_str());
|
||||
updID->parent = StrAlloc("");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -818,13 +801,7 @@ TSyError SyncEvolution_DeleteItem( CContext aContext, cItemID aID )
|
|||
TSyError res = LOCERR_OK;
|
||||
SyncItem item;
|
||||
item.setKey(aID->item);
|
||||
switch (source->deleteItem(item)) {
|
||||
case STC_OK:
|
||||
break;
|
||||
default:
|
||||
res = DB_Fatal;
|
||||
break;
|
||||
}
|
||||
res = source->deleteItem(item);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -904,6 +881,6 @@ TSyError SyncEvolution_DeleteContext( CContext aContext )
|
|||
/**** CAN BE ADAPTED BY USER ****/
|
||||
EvolutionSyncSource *source = DBC( aContext );
|
||||
DEBUG_DB( source->getSynthesisAPI(), MyDB,Da_DC, "%s", source->getName() );
|
||||
|
||||
source->popSynthesisAPI();
|
||||
return LOCERR_OK;
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ void TrackingSyncSource::exportData(ostream &out)
|
|||
}
|
||||
}
|
||||
|
||||
int TrackingSyncSource::addItemThrow(SyncItem& item)
|
||||
SyncMLStatus TrackingSyncSource::addItemThrow(SyncItem& item)
|
||||
{
|
||||
InsertItemResult res = insertItem("", item);
|
||||
item.setKey(res.m_uid.c_str());
|
||||
|
@ -134,10 +134,10 @@ int TrackingSyncSource::addItemThrow(SyncItem& item)
|
|||
throwError("could not add item");
|
||||
}
|
||||
m_trackingNode->setProperty(res.m_uid, res.m_revision);
|
||||
return res.m_merged ? STC_CONFLICT_RESOLVED_WITH_MERGE : STC_OK;
|
||||
return res.m_merged ? STATUS_DATA_MERGED : STATUS_OK;
|
||||
}
|
||||
|
||||
int TrackingSyncSource::updateItemThrow(SyncItem& item)
|
||||
SyncMLStatus TrackingSyncSource::updateItemThrow(SyncItem& item)
|
||||
{
|
||||
const string uid = item.getKey();
|
||||
InsertItemResult res = insertItem(uid, item);
|
||||
|
@ -149,17 +149,13 @@ int TrackingSyncSource::updateItemThrow(SyncItem& item)
|
|||
throwError("could not update item");
|
||||
}
|
||||
m_trackingNode->setProperty(res.m_uid, res.m_revision);
|
||||
return res.m_merged ? STC_CONFLICT_RESOLVED_WITH_MERGE : STC_OK;
|
||||
return res.m_merged ? STATUS_DATA_MERGED : STATUS_OK;
|
||||
}
|
||||
|
||||
int TrackingSyncSource::deleteItemThrow(SyncItem& item)
|
||||
SyncMLStatus TrackingSyncSource::deleteItemThrow(SyncItem& item)
|
||||
{
|
||||
const string uid = item.getKey();
|
||||
deleteItem(uid);
|
||||
m_trackingNode->removeProperty(uid);
|
||||
return STC_OK;
|
||||
}
|
||||
|
||||
void TrackingSyncSource::setItemStatusThrow(const char *uid, int status)
|
||||
{
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
|
|
@ -198,17 +198,15 @@ class TrackingSyncSource : public EvolutionSyncSource
|
|||
virtual void logItem(const string &uid, const string &info, bool debug = false) = 0;
|
||||
virtual void logItem(const SyncItem &item, const string &info, bool debug = false) = 0;
|
||||
|
||||
virtual void setItemStatusThrow(const char *key, int status);
|
||||
|
||||
private:
|
||||
/* implementations of EvolutionSyncSource callbacks */
|
||||
virtual void beginSyncThrow(bool needAll,
|
||||
bool needPartial,
|
||||
bool deleteLocal);
|
||||
virtual void endSyncThrow();
|
||||
virtual int addItemThrow(SyncItem& item);
|
||||
virtual int updateItemThrow(SyncItem& item);
|
||||
virtual int deleteItemThrow(SyncItem& item);
|
||||
virtual SyncMLStatus addItemThrow(SyncItem& item);
|
||||
virtual SyncMLStatus updateItemThrow(SyncItem& item);
|
||||
virtual SyncMLStatus deleteItemThrow(SyncItem& item);
|
||||
|
||||
boost::shared_ptr<ConfigNode> m_trackingNode;
|
||||
};
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
The code in this directory is a copy of the Funambol 3.x C++
|
||||
client api code, revision sdkcpp_3_0_17. It was forked because
|
||||
the upstream development broke the vCard 2.1 <-> 3.0 conversion
|
||||
that SyncEvolution needs.
|
|
@ -1,314 +0,0 @@
|
|||
/**
|
||||
* Copyright (C) 2003-2006 Funambol
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "posixadapter.h"
|
||||
|
||||
#include "VConverter.h"
|
||||
#include "base/util/WString.h"
|
||||
|
||||
namespace vocl {
|
||||
|
||||
VObject* VConverter::parse(wchar_t* buffer) {
|
||||
|
||||
wchar_t *objType = extractObjectType(buffer);
|
||||
wchar_t *objVersion = extractObjectVersion(buffer);
|
||||
if(!objType)
|
||||
return NULL;
|
||||
|
||||
VObject* vo = new VObject();
|
||||
vo->setVersion(objVersion);
|
||||
VProperty *prop;
|
||||
|
||||
wchar_t* buffCopy = new wchar_t[wcslen(buffer) + 1];
|
||||
wcscpy(buffCopy, buffer);
|
||||
|
||||
while ( true ) {
|
||||
prop = readFieldHeader(buffCopy);
|
||||
if (!prop) {
|
||||
break;
|
||||
}
|
||||
if ( readFieldBody(*vo, buffCopy, prop )) {
|
||||
// this makes a copy of prop, we still have to free it
|
||||
vo->addProperty(prop);
|
||||
}
|
||||
delete prop;
|
||||
}
|
||||
|
||||
delete [] buffCopy; buffCopy = NULL;
|
||||
|
||||
return vo;
|
||||
}
|
||||
|
||||
VProperty* VConverter::readFieldHeader(wchar_t* buffer) {
|
||||
|
||||
wchar_t* headerIndex = NULL;
|
||||
wchar_t* quotaIndex = NULL;
|
||||
quotaIndex = wcschr(buffer, '"');
|
||||
headerIndex = wcschr(buffer, ':');
|
||||
|
||||
|
||||
if(!headerIndex)
|
||||
return NULL;
|
||||
bool quota = false;
|
||||
// If the header contains a quotation mark,
|
||||
// then rescan it starting directly after the _quotation mark_
|
||||
// (not after the end of the header, as in the original code)
|
||||
// to find the real end of the header.
|
||||
//
|
||||
// The reason for this code apparently is that the simple search above
|
||||
// might have found a headerIndex which points into the middle of
|
||||
// the quoted string.
|
||||
//
|
||||
// A better solution would be to always scan the header properly.
|
||||
if(quotaIndex && quotaIndex < headerIndex) {
|
||||
quota = true;
|
||||
int len = int(wcslen(buffer));
|
||||
for(int i = int(quotaIndex - buffer) + 1; i < len; i++) {
|
||||
if(buffer[i] == '"')
|
||||
quota = !quota;
|
||||
if(buffer[i] == ':' && !quota) {
|
||||
headerIndex = &buffer[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(quota)
|
||||
return NULL;
|
||||
|
||||
VProperty* prop = new VProperty(NULL);
|
||||
|
||||
wchar_t* header = new wchar_t[wcslen(buffer) + 1];
|
||||
buffer[headerIndex - buffer] = '\0';
|
||||
wcscpy(header, buffer);
|
||||
// Shift the remaing string to the front of the buffer.
|
||||
// Using wcscpy() for that is incorrect because the standard
|
||||
// does not guarantee in which order bytes are moved!
|
||||
// wcscpy(buffer, ++headerIndex);
|
||||
++headerIndex;
|
||||
memmove(buffer, headerIndex, (wcslen(headerIndex) + 1) * sizeof(*headerIndex));
|
||||
|
||||
//if the header is folded (in .ics files)
|
||||
//we need to remove the folding
|
||||
wchar_t* headerFolding = NULL;
|
||||
if((headerFolding = wcsstr(header, TEXT("\n "))) != NULL) {
|
||||
header[headerFolding - header] = '\0';
|
||||
}
|
||||
|
||||
wchar_t seps[] = TEXT(";");
|
||||
wchar_t *token;
|
||||
bool first = true;
|
||||
|
||||
token = wcstok( header, seps );
|
||||
while( token != NULL ) {
|
||||
if (first) {
|
||||
|
||||
wchar_t* group = new wchar_t[wcslen(token) + 1];
|
||||
if(extractGroup(token, group))
|
||||
prop->addParameter(TEXT("GROUP"), group);
|
||||
else
|
||||
delete [] group; group= NULL;
|
||||
prop->setName(token);
|
||||
first = false;
|
||||
}
|
||||
else {
|
||||
wchar_t* paramIndex;
|
||||
paramIndex = wcschr(token, '=');
|
||||
|
||||
if(paramIndex) {
|
||||
wchar_t* paramName = new wchar_t[wcslen(token) + 1];
|
||||
token[paramIndex - token] = '\0';
|
||||
wcscpy(paramName, token);
|
||||
++paramIndex;
|
||||
memmove(token, paramIndex, (wcslen(paramIndex) + 1) * sizeof(*paramIndex));
|
||||
|
||||
wchar_t* paramVal = new wchar_t[wcslen(token) + 1];
|
||||
wcscpy(paramVal, token);
|
||||
prop->addParameter(paramName, paramVal);
|
||||
|
||||
delete [] paramName; paramName = NULL;
|
||||
delete [] paramVal; paramVal = NULL;
|
||||
}
|
||||
else {
|
||||
prop->addParameter(token,NULL);
|
||||
}
|
||||
}
|
||||
token = wcstok( NULL, seps );
|
||||
}
|
||||
|
||||
delete [] header; header = NULL;
|
||||
delete token; token = NULL;
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
bool VConverter::readFieldBody(VObject &vo, wchar_t* buffer, VProperty* vprop) {
|
||||
// old folding (vCard 2.1): folding insert CRLF before _existing_ space
|
||||
// new MIME folding( vCard 3.0, iCalendar): folding inserts CRLFSP
|
||||
bool isOldFolding = vo.getVersion() &&
|
||||
!bstrcmp(vo.getVersion(), "2.1");
|
||||
bool folding = false;
|
||||
wchar_t *c = buffer;
|
||||
int i = 0, j = 0;
|
||||
wchar_t* value = new wchar_t[wcslen(buffer) + 1];
|
||||
|
||||
wcscpy(value, TEXT(""));
|
||||
|
||||
if(vprop->equalsEncoding(TEXT("QUOTED-PRINTABLE"))) {
|
||||
bool afterEqual = false;
|
||||
while (c[i] != '\0') {
|
||||
if (c[i] == '\r') {
|
||||
if (c[i + 1] == '\n') {
|
||||
if (!afterEqual) {
|
||||
// end of property after \r\n,
|
||||
// ignore last two characters and stop
|
||||
i += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (c[i] == '\n') {
|
||||
if (!afterEqual) {
|
||||
// end of property after single \n,
|
||||
// ignore last two characters and stop
|
||||
i += 1;
|
||||
break;
|
||||
}
|
||||
} else if (c[i] == '=') {
|
||||
afterEqual = true;
|
||||
} else {
|
||||
// normal character
|
||||
afterEqual = false;
|
||||
}
|
||||
|
||||
value[j] = c[i];
|
||||
j++;
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
while (c[i] != '\0') {
|
||||
if(folding) {
|
||||
if((c[i] == ' ') || c[i] == '\t' ) {
|
||||
if (isOldFolding) {
|
||||
value[j] = c[i];
|
||||
j++;
|
||||
}
|
||||
folding = false;
|
||||
}
|
||||
else
|
||||
if((c[i] != '\r') && (c[i] != '\n'))
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if((c[i] == '\r') || c[i] == '\n' )
|
||||
folding = true;
|
||||
else {
|
||||
value[j] = c[i];
|
||||
j++;
|
||||
value[j] = '\0';
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
value[j] = 0;
|
||||
vprop->setValue(value);
|
||||
delete [] value; value = NULL;
|
||||
// wcscpy only valid for non-overlapping buffers.
|
||||
// This one here can overlap.
|
||||
// wcscpy(buffer, c+i);
|
||||
memmove(buffer, c+i, (wcslen(c+i) + 1) * sizeof(*c));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
wchar_t* VConverter::extractObjectProperty(wchar_t* buffer, const wchar_t *property,
|
||||
wchar_t * &buffCopy, size_t &buffCopyLen) {
|
||||
|
||||
// Memory handling in extractObjectType() and
|
||||
// extractObjectVersion() was broken:
|
||||
// they allocated a buffer, then returned a pointer into
|
||||
// parts of this buffer as result. The caller cannot
|
||||
// free the result in this case. The functions were also
|
||||
// duplicating the same code.
|
||||
//
|
||||
// This partial fix reuses previously allocated
|
||||
// memory if the function is called a second time.
|
||||
|
||||
size_t len = wcslen(buffer) + 1;
|
||||
if (buffCopyLen < len) {
|
||||
if (buffCopy) {
|
||||
delete [] buffCopy;
|
||||
}
|
||||
buffCopy = new wchar_t[len];
|
||||
buffCopyLen = len;
|
||||
}
|
||||
wcscpy(buffCopy, buffer);
|
||||
|
||||
wchar_t seps[] = TEXT(":\n");
|
||||
wchar_t *token;
|
||||
|
||||
token = wcstok( buffCopy, seps );
|
||||
while (token != NULL) {
|
||||
if(!wcscmp(token, TEXT(property))) {
|
||||
token = wcstok( NULL, seps );
|
||||
wchar_t* index = wcschr(token,'\r');
|
||||
if(index)
|
||||
token[index-token] = '\0';
|
||||
return token;
|
||||
}
|
||||
token = wcstok( NULL, seps );
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wchar_t* VConverter::extractObjectType(wchar_t* buffer) {
|
||||
static wchar_t* buffCopy;
|
||||
static size_t buffCopyLen;
|
||||
|
||||
return extractObjectProperty(buffer, "BEGIN",
|
||||
buffCopy, buffCopyLen);
|
||||
}
|
||||
|
||||
|
||||
wchar_t* VConverter::extractObjectVersion(wchar_t* buffer) {
|
||||
static wchar_t* buffCopy;
|
||||
static size_t buffCopyLen;
|
||||
|
||||
return extractObjectProperty(buffer, "VERSION",
|
||||
buffCopy, buffCopyLen);
|
||||
}
|
||||
|
||||
bool VConverter::extractGroup(wchar_t* propertyName, wchar_t* propertyGroup) {
|
||||
|
||||
wchar_t* groupIndex;
|
||||
groupIndex = wcschr(propertyName, '.');
|
||||
|
||||
if(!groupIndex)
|
||||
return false;
|
||||
|
||||
propertyName[groupIndex - propertyName] = '\0';
|
||||
wcscpy(propertyGroup, propertyName);
|
||||
wcscpy(propertyName, ++groupIndex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
|
@ -1,32 +0,0 @@
|
|||
#ifndef INCL_VIRTUAL_CONVERTER
|
||||
#define INCL_VIRTUAL_CONVERTER
|
||||
|
||||
#include "VObject.h"
|
||||
|
||||
namespace vocl {
|
||||
|
||||
class VConverter{
|
||||
|
||||
public:
|
||||
static VObject* parse(char* buffer);
|
||||
|
||||
private:
|
||||
static VProperty* readFieldHeader(char* buffer);
|
||||
static bool readFieldBody(VObject &vo, char* buffer, VProperty* property);
|
||||
|
||||
// Extract the parameter of certain properties, e.g. "BEGIN:" or "VERSION:".
|
||||
// The result is a pointer into buffCopy, which is expected to have
|
||||
// buffCopyLen wchars and will be reallocated if necessary.
|
||||
static char* extractObjectProperty(char* buffer, const char *property,
|
||||
char * &buffCopy, size_t &buffCopyLen);
|
||||
|
||||
// extractObjectType() and extractObjectVersion() contain static buffers,
|
||||
// copy the result before calling these functions again!
|
||||
static char* extractObjectType(char* buffer);
|
||||
static char* extractObjectVersion(char* buffer);
|
||||
static bool extractGroup(char* propertyName, char* propertyGroup);
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
#endif
|
|
@ -1,485 +0,0 @@
|
|||
/**
|
||||
* Copyright (C) 2003-2006 Funambol
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
// this code originally comes from the client library
|
||||
// and needs some of the internal defines in
|
||||
// posixadapter.h
|
||||
#include "posixadapter.h"
|
||||
|
||||
#include "base/util/utils.h"
|
||||
#include "base/util/WString.h"
|
||||
#include "base/Log.h"
|
||||
#include "VObject.h"
|
||||
|
||||
namespace vocl {
|
||||
|
||||
VObject::VObject() {
|
||||
productID = NULL;
|
||||
version = NULL;
|
||||
properties = new ArrayList();
|
||||
}
|
||||
|
||||
VObject::~VObject() {
|
||||
if (productID) {
|
||||
delete [] productID; productID = NULL;
|
||||
}
|
||||
if (version) {
|
||||
delete [] version; version = NULL;
|
||||
}
|
||||
if (properties) {
|
||||
delete properties; properties = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void VObject::set(wchar_t** p, const wchar_t* v) {
|
||||
if (*p) {
|
||||
delete [] *p;
|
||||
}
|
||||
*p = (v) ? wstrdup(v) : NULL;
|
||||
}
|
||||
|
||||
void VObject::setVersion(const wchar_t* ver) {
|
||||
set(&version, ver);
|
||||
}
|
||||
|
||||
void VObject::setProdID(const wchar_t* prodID) {
|
||||
set(&productID, prodID);
|
||||
}
|
||||
|
||||
wchar_t* VObject::getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
wchar_t* VObject::getProdID() {
|
||||
return productID;
|
||||
}
|
||||
|
||||
void VObject::addProperty(VProperty* vProp) {
|
||||
properties->add((ArrayElement&) *vProp);
|
||||
}
|
||||
|
||||
int VObject::propertiesCount() {
|
||||
return properties->size();
|
||||
}
|
||||
|
||||
bool VObject::removeProperty(int index) {
|
||||
if(index < 0 || index >= propertiesCount())
|
||||
return false;
|
||||
properties->removeElementAt(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
void VObject::removeProperty(const wchar_t* propName) {
|
||||
for (int i=0; i<properties->size(); i++) {
|
||||
VProperty *property;
|
||||
property = (VProperty* )properties->get(i);
|
||||
if(!wcscmp(property->getName(), propName)) {
|
||||
properties->removeElementAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool VObject::containsProperty(const wchar_t* propName) {
|
||||
for (int i=0; i<properties->size(); i++) {
|
||||
VProperty *property;
|
||||
property = (VProperty* )properties->get(i);
|
||||
if(!wcscmp(property->getName(), propName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
VProperty* VObject::getProperty(int index) {
|
||||
return (VProperty*)properties->get(index);
|
||||
}
|
||||
|
||||
VProperty* VObject::getProperty(const wchar_t* propName) {
|
||||
for (int i=0; i<properties->size(); i++) {
|
||||
|
||||
VProperty *property;
|
||||
property = (VProperty* )properties->get(i);
|
||||
|
||||
if(!wcscmp(property->getName(), propName)) {
|
||||
return property;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wchar_t* VObject::toString() {
|
||||
|
||||
WString strVObject;
|
||||
const wchar_t* eof;
|
||||
|
||||
// vcard 2.1 and 3.0 both use \r\n as line ending
|
||||
eof = TEXT("\r\n");
|
||||
|
||||
for (int i=0; i<properties->size(); i++) {
|
||||
VProperty *property;
|
||||
property = (VProperty*)properties->get(i);
|
||||
if(property->containsParameter(TEXT("GROUP"))) {
|
||||
strVObject.append(property->getParameterValue(TEXT("GROUP")));
|
||||
strVObject.append(TEXT("."));
|
||||
property->removeParameter(TEXT("GROUP"));
|
||||
}
|
||||
strVObject.append(property->getName());
|
||||
|
||||
for(int k=0; k<property->parameterCount(); k++) {
|
||||
strVObject.append(TEXT(";"));
|
||||
|
||||
wchar_t* paramName = new wchar_t[wcslen(property->getParameter(k))+1];
|
||||
wcscpy(paramName, property->getParameter(k));
|
||||
|
||||
strVObject.append(paramName);
|
||||
const wchar_t *value = property->getParameterValue(k);
|
||||
if(value) {
|
||||
strVObject.append(TEXT("="));
|
||||
strVObject.append(value);
|
||||
}
|
||||
delete [] paramName; paramName = NULL;
|
||||
}
|
||||
|
||||
strVObject.append(TEXT(":"));
|
||||
if(property->getValue()) {
|
||||
if(property->equalsEncoding(TEXT("BASE64"))) {
|
||||
wchar_t delim[] = TEXT("\r\n ");
|
||||
int fold = 76;
|
||||
int sizeOfValue = int(wcslen(property->getValue()));
|
||||
int size = sizeOfValue + (int)(sizeOfValue/fold + 2)*int(wcslen(delim));
|
||||
int index = 0;
|
||||
|
||||
wchar_t* output = new wchar_t[size + 1];
|
||||
wcscpy(output, TEXT("\0"));
|
||||
|
||||
while (index<sizeOfValue)
|
||||
{
|
||||
wcscat(output,delim);
|
||||
wcsncat(output,property->getValue()+index,fold);
|
||||
index+=fold;
|
||||
}
|
||||
|
||||
strVObject.append(output);
|
||||
// the extra empty line is needed because the Bachus-Naur
|
||||
// specification of vCard 2.1 says so
|
||||
strVObject.append(eof);
|
||||
delete [] output;
|
||||
}
|
||||
else
|
||||
strVObject.append(property->getValue());
|
||||
}
|
||||
strVObject.append(eof);
|
||||
}
|
||||
|
||||
// memory must be free by caller with delete []
|
||||
wchar_t *str = new wchar_t[strVObject.length() + 1];
|
||||
wcscpy(str, strVObject.c_str());
|
||||
return str;
|
||||
}
|
||||
|
||||
void VObject::insertProperty(VProperty* property) {
|
||||
|
||||
if (propertiesCount() == 0 || wcscmp(getProperty(propertiesCount()-1)->getName(),TEXT("END")))
|
||||
addProperty(property);
|
||||
else {
|
||||
VProperty* lastProperty = getProperty(TEXT("END"));
|
||||
removeProperty(TEXT("END"));
|
||||
addProperty(property);
|
||||
addProperty(lastProperty);
|
||||
}
|
||||
}
|
||||
|
||||
void VObject::addFirstProperty(VProperty* property) {
|
||||
properties->add(0,(ArrayElement&)*property);
|
||||
}
|
||||
|
||||
void VObject::removeAllProperies(const wchar_t* propName) {
|
||||
for(int i = 0, m = propertiesCount(); i < m ; i++)
|
||||
if(!wcscmp(getProperty(i)->getName(), propName)) {
|
||||
removeProperty(i);
|
||||
--i;
|
||||
--m;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Patrick Ohly: hack below, see header file
|
||||
|
||||
static int hex2int( wchar_t x )
|
||||
{
|
||||
return (x >= '0' && x <= '9') ? x - '0' :
|
||||
(x >= 'A' && x <= 'F') ? x - 'A' + 10 :
|
||||
(x >= 'a' && x <= 'f') ? x - 'a' + 10 :
|
||||
0;
|
||||
}
|
||||
|
||||
void VObject::toNativeEncoding()
|
||||
{
|
||||
bool is_30 = !wcscmp(getVersion(), TEXT("3.0"));
|
||||
// line break is encoded with either one or two
|
||||
// characters on different platforms
|
||||
const int linebreaklen = wcslen(SYNC4J_LINEBREAK);
|
||||
|
||||
for (int index = propertiesCount() - 1; index >= 0; index--) {
|
||||
VProperty *vprop = getProperty(index);
|
||||
wchar_t *name = vprop->getName();
|
||||
wchar_t *foreign = vprop->getValue();
|
||||
// the native encoding is always shorter than the foreign one
|
||||
wchar_t *native = new wchar_t[wcslen(foreign) + 1];
|
||||
|
||||
if (vprop->equalsEncoding(TEXT("QUOTED-PRINTABLE"))) {
|
||||
int in = 0, out = 0;
|
||||
wchar_t curr;
|
||||
|
||||
// this is a very crude quoted-printable decoder,
|
||||
// based on Wikipedia's explanation of quoted-printable
|
||||
while ((curr = foreign[in]) != 0) {
|
||||
in++;
|
||||
if (curr == '=') {
|
||||
wchar_t values[2];
|
||||
values[0] = foreign[in];
|
||||
in++;
|
||||
if (!values[0]) {
|
||||
// incomplete?!
|
||||
break;
|
||||
}
|
||||
values[1] = foreign[in];
|
||||
in++;
|
||||
if (values[0] == '\r' && values[1] == '\n') {
|
||||
// soft line break, ignore it
|
||||
} else {
|
||||
native[out] = (hex2int(values[0]) << 4) |
|
||||
hex2int(values[1]);
|
||||
out++;
|
||||
|
||||
// replace \r\n with \n?
|
||||
if ( linebreaklen == 1 &&
|
||||
out >= 2 &&
|
||||
native[out - 2] == '\r' &&
|
||||
native[out - 1] == '\n' ) {
|
||||
native[out - 2] = SYNC4J_LINEBREAK[0];
|
||||
out--;
|
||||
}
|
||||
|
||||
// the conversion to wchar on Windows is
|
||||
// probably missing here
|
||||
}
|
||||
} else {
|
||||
native[out] = curr;
|
||||
out++;
|
||||
}
|
||||
}
|
||||
native[out] = 0;
|
||||
out++;
|
||||
} else {
|
||||
wcscpy(native, foreign);
|
||||
}
|
||||
|
||||
// decode escaped characters after backslash:
|
||||
// \n is line break only in 3.0
|
||||
wchar_t curr;
|
||||
int in = 0, out = 0;
|
||||
while ((curr = native[in]) != 0) {
|
||||
in++;
|
||||
switch (curr) {
|
||||
case '\\':
|
||||
curr = native[in];
|
||||
in++;
|
||||
switch (curr) {
|
||||
case 'n':
|
||||
if (is_30) {
|
||||
// replace with line break
|
||||
wcsncpy(native + out, SYNC4J_LINEBREAK, linebreaklen);
|
||||
out += linebreaklen;
|
||||
} else {
|
||||
// normal escaped character
|
||||
native[out] = curr;
|
||||
out++;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
// unexpected end of string
|
||||
break;
|
||||
default:
|
||||
// just copy next character
|
||||
native[out] = curr;
|
||||
out++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ';':
|
||||
// Might be field separator, but beware:
|
||||
// in vCard 2.1 a single, unescaped semicolon is valid in all
|
||||
// properties which are single values and not structured.
|
||||
// Some encoders even do that in 3.0, so always accept a literal
|
||||
// ; as it is in properties which are not multi-value.
|
||||
if (!wcsicmp(name, "N") ||
|
||||
!wcsicmp(name, "ADR") ||
|
||||
!wcsicmp(name, "ORG")) {
|
||||
// must replace with something special
|
||||
// so that we can encode it again in fromNativeEncoding()
|
||||
native[out] = SEMICOLON_REPLACEMENT;
|
||||
out++;
|
||||
} else {
|
||||
// copy literally
|
||||
native[out] = ';';
|
||||
out++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
native[out] = curr;
|
||||
out++;
|
||||
}
|
||||
}
|
||||
native[out] = 0;
|
||||
out++;
|
||||
|
||||
// charset handling:
|
||||
// - doesn't exist at the moment, vCards have to be in ASCII or UTF-8
|
||||
// - an explicit CHARSET parameter is removed because its parameter
|
||||
// value might differ between 2.1 and 3.0 (quotation marks allowed in
|
||||
// 3.0 but not 2.1) and thus would require extra code to convert it;
|
||||
// when charsets really get supported this needs to be addressed
|
||||
wchar_t *charset = vprop->getParameterValue(TEXT("CHARSET"));
|
||||
if (charset) {
|
||||
// proper decoding of the value and the property value text
|
||||
// would go here, for the time being we just remove the
|
||||
// value
|
||||
if (_wcsicmp(charset, TEXT("UTF-8")) &&
|
||||
_wcsicmp(charset, TEXT("\"UTF-8\""))) {
|
||||
// log error("ignoring unsupported charset");
|
||||
}
|
||||
vprop->removeParameter(TEXT("CHARSET"));
|
||||
}
|
||||
|
||||
vprop->setValue(native);
|
||||
delete [] native;
|
||||
}
|
||||
}
|
||||
|
||||
void VObject::fromNativeEncoding()
|
||||
{
|
||||
bool is_30 = !wcscmp(getVersion(), TEXT("3.0"));
|
||||
|
||||
for (int index = propertiesCount() - 1; index >= 0; index--) {
|
||||
VProperty *vprop = getProperty(index);
|
||||
|
||||
wchar_t *native = vprop->getValue();
|
||||
// in the worst case every comma/linebreak is replaced with
|
||||
// two characters and each \n with =0D=0A
|
||||
wchar_t *foreign = new wchar_t[6 * wcslen(native) + 1];
|
||||
wchar_t curr;
|
||||
int in = 0, out = 0;
|
||||
// line break is encoded with either one or two
|
||||
// characters on different platforms
|
||||
const int linebreaklen = wcslen(SYNC4J_LINEBREAK);
|
||||
|
||||
// use backslash for special characters,
|
||||
// if necessary do quoted-printable encoding
|
||||
bool doquoted = !is_30 &&
|
||||
wcsstr(native, SYNC4J_LINEBREAK) != NULL;
|
||||
|
||||
if (vprop->equalsEncoding(TEXT("QUOTED-PRINTABLE"))) {
|
||||
// remove it, recreate if doing 2.1
|
||||
vprop->removeParameter(TEXT("ENCODING"));
|
||||
if (!is_30) {
|
||||
doquoted = true;
|
||||
}
|
||||
}
|
||||
|
||||
// non-ASCII character encountered
|
||||
bool utf8 = false;
|
||||
|
||||
while ((curr = native[in]) != 0) {
|
||||
in++;
|
||||
switch (curr) {
|
||||
case ',':
|
||||
if (!is_30) {
|
||||
// normal character
|
||||
foreign[out] = curr;
|
||||
out++;
|
||||
break;
|
||||
}
|
||||
// no break!
|
||||
case ';':
|
||||
case '\\':
|
||||
foreign[out] = '\\';
|
||||
out++;
|
||||
foreign[out] = curr;
|
||||
out++;
|
||||
break;
|
||||
case SEMICOLON_REPLACEMENT:
|
||||
foreign[out] = ';';
|
||||
out++;
|
||||
break;
|
||||
default:
|
||||
bool currIsUTF8 = (unsigned char)curr >= 128;
|
||||
|
||||
if (currIsUTF8) {
|
||||
utf8 = true;
|
||||
if (!is_30 && !doquoted) {
|
||||
// vCard 2.1 defaults to 7-bit; instead of
|
||||
// overriding that we fall back to quoted-printable
|
||||
doquoted = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (doquoted &&
|
||||
(curr == '=' || currIsUTF8)) {
|
||||
// escape = and non-ASCII characters
|
||||
wsprintf(foreign + out, TEXT("=%02X"), (unsigned int)(unsigned char)curr);
|
||||
out += 3;
|
||||
} else if (!wcsncmp(native + in - 1,
|
||||
SYNC4J_LINEBREAK,
|
||||
linebreaklen)) {
|
||||
// line break
|
||||
if (is_30) {
|
||||
foreign[out] = '\\';
|
||||
out++;
|
||||
foreign[out] = 'n';
|
||||
out++;
|
||||
} else {
|
||||
wcscpy(foreign + out, TEXT("=0D=0A"));
|
||||
out += 6;
|
||||
}
|
||||
in += linebreaklen - 1;
|
||||
} else {
|
||||
foreign[out] = curr;
|
||||
out++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
foreign[out] = 0;
|
||||
vprop->setValue(foreign);
|
||||
delete [] foreign;
|
||||
if (doquoted) {
|
||||
// we have used quoted-printable encoding
|
||||
vprop->addParameter(TEXT("ENCODING"), TEXT("QUOTED-PRINTABLE"));
|
||||
}
|
||||
if (utf8 &&
|
||||
!is_30 &&
|
||||
!vprop->getParameterValue("CHARSET")) {
|
||||
vprop->addParameter("CHARSET", "UTF-8");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
|
@ -1,88 +0,0 @@
|
|||
#ifndef INCL_VIRTUAL_OBJECT
|
||||
#define INCL_VIRTUAL_OBJECT
|
||||
|
||||
#include "VProperty.h"
|
||||
|
||||
namespace vocl {
|
||||
|
||||
class VObject {
|
||||
|
||||
private:
|
||||
|
||||
char* version;
|
||||
char* productID;
|
||||
ArrayList* properties;
|
||||
void set(char**, const char*);
|
||||
|
||||
public:
|
||||
|
||||
VObject();
|
||||
~VObject();
|
||||
void setVersion (const char* ver);
|
||||
void setProdID (const char* prodID);
|
||||
char* getVersion();
|
||||
char* getProdID();
|
||||
void addProperty(VProperty* property);
|
||||
void addProperty(const char *name, const char *value) { VProperty vprop(name, value); addProperty(&vprop); }
|
||||
void addFirstProperty(VProperty* property);
|
||||
void insertProperty(VProperty* property);
|
||||
bool removeProperty(int index);
|
||||
void removeProperty(const char* propName);
|
||||
void removeAllProperies(const char* propName);
|
||||
//removes all properties having name - propName;
|
||||
bool containsProperty(const char* propName);
|
||||
int propertiesCount();
|
||||
VProperty* getProperty(int index);
|
||||
VProperty* getProperty(const char* propName);
|
||||
char* toString();
|
||||
|
||||
// Patrick Ohly:
|
||||
//
|
||||
// Normally the class does not change the encoding
|
||||
// of properties. That means that users of this class
|
||||
// have to be prepared to handle e.g. quoted-printable
|
||||
// encoding of non-ASCII characters or \n as line break
|
||||
// in vCard 3.0.
|
||||
//
|
||||
// This function decodes all property strings into the
|
||||
// native format. It supports:
|
||||
// - decoding quoted-printable characters if
|
||||
// ENCODING=QUOTED-PRINTABLE
|
||||
// - replacement of \n with a line break and \, with
|
||||
// single comma if version is 3.0
|
||||
//
|
||||
// It does not support charset conversions, so everything
|
||||
// has to be UTF-8 to work correctly.
|
||||
//
|
||||
// This function does not modify the property parameters,
|
||||
// so one could convert back into the original format.
|
||||
//
|
||||
// Consider this function a hack: at this time it is not
|
||||
// clear how the class is supposed to handle different
|
||||
// encodings, but I needed a solution, so here it is.
|
||||
//
|
||||
void toNativeEncoding();
|
||||
|
||||
//
|
||||
// Converts properties in native format according to
|
||||
// their parameters.
|
||||
//
|
||||
// It only supports:
|
||||
// - replacement of line breaks and commas (if 3.0)
|
||||
//
|
||||
// It does not support any charsets or encoding.
|
||||
// ENCODING=QUOTED-PRINTABLE will be removed because
|
||||
// it no longer applies when toNativeEncoding() was
|
||||
// used before, but the other parameters are preserved:
|
||||
// this might be good enough to recreate the original
|
||||
// object.
|
||||
//
|
||||
void fromNativeEncoding();
|
||||
|
||||
/** in native property values this special character separates sub-values in multi-value properties */
|
||||
static const char SEMICOLON_REPLACEMENT = '\a';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,296 +0,0 @@
|
|||
/**
|
||||
* Copyright (C) 2003-2006 Funambol
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "posixadapter.h"
|
||||
|
||||
#include "base/util/utils.h"
|
||||
#include "base/util/StringBuffer.h"
|
||||
#include "VProperty.h"
|
||||
|
||||
namespace vocl {
|
||||
|
||||
VProperty::VProperty(const wchar_t* propname, const wchar_t* propvalue) {
|
||||
|
||||
name = (propname) ? wstrdup(propname) : NULL;
|
||||
value = (propvalue) ? wstrdup(propvalue) : NULL;
|
||||
parameters = new ArrayList();
|
||||
}
|
||||
|
||||
VProperty::~VProperty() {
|
||||
|
||||
if (name) {
|
||||
delete [] name; name = NULL;
|
||||
}
|
||||
if (value) {
|
||||
delete [] value; value = NULL;
|
||||
}
|
||||
if (parameters) {
|
||||
delete parameters; parameters = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void VProperty::setName (const wchar_t* s) {
|
||||
|
||||
set(&name, s);
|
||||
}
|
||||
|
||||
void VProperty::setValue (const wchar_t* s) {
|
||||
|
||||
set(&value, s);
|
||||
}
|
||||
|
||||
wchar_t* VProperty::getName(wchar_t* buf, int size) {
|
||||
|
||||
if (buf == NULL) {
|
||||
return name;
|
||||
}
|
||||
|
||||
if (size >= 0) {
|
||||
wcsncpy(buf, name, size);
|
||||
}
|
||||
else {
|
||||
wcscpy(buf, name);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
wchar_t* VProperty::getValue(wchar_t* buf, int size) {
|
||||
|
||||
if (buf == NULL) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (size >= 0) {
|
||||
wcsncpy(buf, value, size);
|
||||
}
|
||||
else {
|
||||
wcscpy(buf, value);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void VProperty::addParameter (const wchar_t* paramName, const wchar_t* paramValue) {
|
||||
|
||||
if(paramName) {
|
||||
WKeyValuePair *parameter = new WKeyValuePair(paramName, paramValue);
|
||||
parameters->add((ArrayElement &)*parameter);
|
||||
|
||||
delete parameter; parameter = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void VProperty::removeParameter(const wchar_t* paramName) {
|
||||
|
||||
if (parameters != NULL) {
|
||||
for (int i=0; i<parameters->size(); i++){
|
||||
WKeyValuePair *parameter;
|
||||
parameter = (WKeyValuePair* )parameters->get(i);
|
||||
if(!wcscmp(parameter->getKey(), paramName)) {
|
||||
parameters->removeElementAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VProperty::removeParameter(int index) {
|
||||
parameters->removeElementAt(index);
|
||||
}
|
||||
|
||||
bool VProperty::containsParameter(const wchar_t* paramName) {
|
||||
|
||||
if (parameters != NULL) {
|
||||
for (int i=0; i<parameters->size(); i++){
|
||||
WKeyValuePair *parameter;
|
||||
parameter = (WKeyValuePair* )parameters->get(i);
|
||||
if(!wcscmp(parameter->getKey(), paramName)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
wchar_t* VProperty::getParameterValue(const wchar_t* paramName) {
|
||||
|
||||
if (parameters != NULL) {
|
||||
for (int i=0; i<parameters->size(); i++) {
|
||||
WKeyValuePair *parameter;
|
||||
parameter = (WKeyValuePair* )parameters->get(i);
|
||||
if(!wcscmp(parameter->getKey(), paramName))
|
||||
return ((wchar_t *)parameter->getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
wchar_t* VProperty::getParameterValue(int index) {
|
||||
|
||||
if (parameters != NULL) {
|
||||
WKeyValuePair *parameter;
|
||||
parameter = (WKeyValuePair*)parameters->get(index);
|
||||
return parameter ? (wchar_t *)parameter->getValue() : NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void VProperty::set(wchar_t** p, const wchar_t* v) {
|
||||
|
||||
if (*p) {
|
||||
delete [] *p;
|
||||
}
|
||||
*p = (v) ? wstrdup(v) : NULL;
|
||||
}
|
||||
|
||||
ArrayElement* VProperty::clone() {
|
||||
|
||||
if(name) {
|
||||
|
||||
VProperty *cloneProperty = new VProperty(name);
|
||||
|
||||
if(value)
|
||||
cloneProperty->setValue(value);
|
||||
|
||||
if (parameters != NULL) {
|
||||
for (int i=0; i<parameters->size(); i++) {
|
||||
WKeyValuePair* parameterCopy;
|
||||
parameterCopy = (WKeyValuePair*)parameters->get(i)->clone();
|
||||
cloneProperty->addParameter(parameterCopy->getKey(), parameterCopy->getValue());
|
||||
delete parameterCopy;
|
||||
}
|
||||
}
|
||||
return cloneProperty;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int VProperty::parameterCount() {
|
||||
|
||||
return parameters->size();
|
||||
}
|
||||
|
||||
wchar_t* VProperty::toString() {
|
||||
|
||||
wchar_t *propertyString = new wchar_t[VPROPETY_BUFFER];
|
||||
if (name!=NULL){
|
||||
wcscpy(propertyString, name);
|
||||
if(parameterCount()>0) {
|
||||
for (int i=0; i<parameters->size(); i++) {
|
||||
WKeyValuePair *parameter;
|
||||
parameter = (WKeyValuePair*)parameters->get(i);
|
||||
if(parameter->getKey()!= NULL) {
|
||||
wcscat(propertyString, TEXT(";"));
|
||||
wcscat(propertyString, parameter->getKey());
|
||||
}
|
||||
if(parameter->getValue()!= NULL) {
|
||||
wcscat(propertyString, TEXT("="));
|
||||
wcscat(propertyString, parameter->getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
wcscat(propertyString, TEXT(":"));
|
||||
if(value!=NULL) {
|
||||
wcscat(propertyString, value);
|
||||
}
|
||||
}
|
||||
return propertyString;
|
||||
}
|
||||
|
||||
wchar_t* VProperty::getParameter(int index){
|
||||
|
||||
WKeyValuePair *parameter;
|
||||
parameter = (WKeyValuePair*)parameters->get(index);
|
||||
return (wchar_t *)parameter->getKey();
|
||||
}
|
||||
|
||||
bool VProperty::equalsEncoding(const wchar_t* encoding) {
|
||||
|
||||
if ((encoding != NULL) && ((containsParameter(TEXT("ENCODING")) &&
|
||||
!wcscmp(getParameterValue(TEXT("ENCODING")),encoding)) ||
|
||||
containsParameter(encoding)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
wchar_t* VProperty::getPropComponent(int i) {
|
||||
|
||||
|
||||
if (!getValue() || !wcscmp(getValue(),TEXT("")))
|
||||
return NULL;
|
||||
|
||||
wchar_t *value = new wchar_t[wcslen(getValue()) + 1];
|
||||
wchar_t* component = new wchar_t[wcslen(getValue()) + 1];
|
||||
|
||||
wcscpy(value, getValue());
|
||||
wchar_t* componentIndex;
|
||||
int j=0;
|
||||
|
||||
while (j < i) {
|
||||
componentIndex = wcschr(value, ';');
|
||||
if(componentIndex) {
|
||||
value[componentIndex - value] = 0;
|
||||
wcscpy(component, value);
|
||||
wcscpy(value, ++componentIndex);
|
||||
j++;
|
||||
}
|
||||
else
|
||||
if(j<i-1)
|
||||
return NULL;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
delete [] value; value = NULL;
|
||||
if(component && wcscmp(component, TEXT("")))
|
||||
return component;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool VProperty::isType(const wchar_t* type) {
|
||||
if(containsParameter(type))
|
||||
return true;
|
||||
|
||||
for (int paramindex = 0;
|
||||
paramindex < parameterCount();
|
||||
paramindex++) {
|
||||
wchar_t *value = getParameterValue(paramindex);
|
||||
wchar_t *param = getParameter(paramindex);
|
||||
if (value && param && !strcasecmp(param, "TYPE")) {
|
||||
wchar_t seps[] = TEXT(",");
|
||||
wchar_t* token;
|
||||
|
||||
StringBuffer buff(value);
|
||||
|
||||
token = wcstok((char *)buff.c_str(), seps);
|
||||
while( token != NULL ) {
|
||||
if(!wcscmp(type, token))
|
||||
return true;
|
||||
token = wcstok( NULL, seps );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
|
@ -1,70 +0,0 @@
|
|||
/**
|
||||
* Copyright (C) 2005-2006 Funambol
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef INCL_VIRTUAL_PROPERTY
|
||||
#define INCL_VIRTUAL_PROPERTY
|
||||
|
||||
#include "base/fscapi.h"
|
||||
#include "base/util/WKeyValuePair.h"
|
||||
#include "base/util/ArrayList.h"
|
||||
|
||||
namespace vocl {
|
||||
|
||||
#define VPROPETY_BUFFER 500
|
||||
|
||||
class VProperty : public ArrayElement {
|
||||
|
||||
private:
|
||||
|
||||
char* name;
|
||||
char* value;
|
||||
void set(char** p, const char* v);
|
||||
ArrayList* parameters;
|
||||
|
||||
public:
|
||||
|
||||
VProperty(const char* propName , const char* propValue = NULL);
|
||||
~VProperty();
|
||||
ArrayElement* clone();
|
||||
void setName (const char* name);
|
||||
void setValue (const char* value);
|
||||
char* getName(char* buf = NULL, int size = -1);
|
||||
char* getValue(char* buf = NULL, int size = -1);
|
||||
void addParameter(const char* paramName, const char* paramValue);
|
||||
void removeParameter(const char* paramName);
|
||||
void removeParameter(int index);
|
||||
bool containsParameter(const char* paramName);
|
||||
// Warning: the name does not always uniquely identify
|
||||
// the parameter, some of them may occur multiple times.
|
||||
// Use getParameterValue(int index) to get the value which
|
||||
// corresponds to a specific parameter.
|
||||
char* getParameterValue(const char* paramName);
|
||||
char* getParameterValue(int index);
|
||||
char* getParameter(int index);
|
||||
int parameterCount();
|
||||
bool equalsEncoding(const char* encoding);
|
||||
char* getPropComponent(int i);
|
||||
bool isType(const char* type);
|
||||
char* toString();
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2006 Funambol
|
||||
* Author Patrick Ohly
|
||||
*/
|
||||
|
||||
#ifndef INCL_POSIX_ADAPTER
|
||||
#define INCL_POSIX_ADAPTER
|
||||
|
||||
|
||||
/*
|
||||
* POSIX environment, configured and compiled with automake/autoconf
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <string>
|
||||
#include <cwchar>
|
||||
#include <iostream>
|
||||
|
||||
// For ntoh functions
|
||||
#include <netinet/in.h>
|
||||
|
||||
// Cygwin version of gcc does have these builtin
|
||||
#ifndef __CYGWIN__
|
||||
# define __declspec(x)
|
||||
# define __cdecl
|
||||
#endif
|
||||
|
||||
//#ifdef ENABLE_NLS
|
||||
//# include <libintl.h>
|
||||
//# define TEXT(String) gettext (String)
|
||||
//#else
|
||||
//# define TEXT(String) (String)
|
||||
//# endif
|
||||
#define TEXT(_x) _x
|
||||
#define CHR(_x) _x
|
||||
#define T(_x) _x
|
||||
|
||||
#define EXTRA_SECTION_00
|
||||
#define EXTRA_SECTION_01
|
||||
#define EXTRA_SECTION_02
|
||||
#define EXTRA_SECTION_03
|
||||
#define EXTRA_SECTION_04
|
||||
#define EXTRA_SECTION_05
|
||||
#define EXTRA_SECTION_06
|
||||
|
||||
#define BOOL int
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define SYNC4J_LINEBREAK "\n"
|
||||
|
||||
/* map wchar_t and its functions back to standard functions */
|
||||
#undef wchar_t
|
||||
#define wchar_t char
|
||||
#undef BCHAR
|
||||
typedef char BCHAR;
|
||||
typedef char WCHAR;
|
||||
|
||||
#define bsprintf sprintf
|
||||
|
||||
#define bstrlen strlen
|
||||
#define bstrcpy strcpy
|
||||
#define bstrcat strcat
|
||||
#define bstrstr strstr
|
||||
#define bstrchr strchr
|
||||
#define bstrrchr strrchr
|
||||
#define bscanf scanf
|
||||
#define bstrcmp strcmp
|
||||
#define bstricmp _stricmp
|
||||
#define bstrncpy strncpy
|
||||
#define bstrncmp strncmp
|
||||
#define bstrtol strtol
|
||||
#define bstrtoul strtoul
|
||||
|
||||
#define wsprintf sprintf
|
||||
#define _wfopen fopen
|
||||
#define wprintf printf
|
||||
#define fwprintf fprintf
|
||||
#define wsprintf sprintf
|
||||
#define swprintf sprintf
|
||||
#define wcscpy strcpy
|
||||
#define wcsncpy strncpy
|
||||
#define wcsncmp strncmp
|
||||
#define wcslen strlen
|
||||
#define wcstol strtol
|
||||
#define wcstoul strtoul
|
||||
#define wcsstr strstr
|
||||
#define wcscmp strcmp
|
||||
#define wcstok strtok
|
||||
inline char towlower(char x) { return tolower(x); }
|
||||
inline char towupper(char x) { return toupper(x); }
|
||||
#define wmemmove memmove
|
||||
#define wmemcpy memcpy
|
||||
#define wmemcmp memcmp
|
||||
#define wmemset memset
|
||||
#define wcschr strchr
|
||||
#define wcsrchr strrchr
|
||||
#define wcscat strcat
|
||||
#define wcsncat strncat
|
||||
#define _wtoi atoi
|
||||
#define wcstod strtod
|
||||
#define wcsicmp strcasecmp
|
||||
#define _wcsicmp strcasecmp
|
||||
#define _stricmp strcasecmp
|
||||
|
||||
/* some of the code compares NULL against integers, which
|
||||
fails if NULL is defined as (void *)0 */
|
||||
#undef NULL
|
||||
#define NULL 0
|
||||
|
||||
template <class T> T min(T x, T y) { return x < y ? x : y; }
|
||||
template <class T> T max(T x, T y) { return x > y ? x : y; }
|
||||
|
||||
#endif
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2006 Funambol
|
||||
*/
|
||||
|
||||
/**
|
||||
* This program reads one vcard from the file
|
||||
* given as first parameter and applies certain
|
||||
* conversions to it.
|
||||
*
|
||||
* The content of the file has to be ASCII or
|
||||
* UTF-8 encoded.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <memory>
|
||||
|
||||
#include "posixadapter.h"
|
||||
#include "VConverter.h"
|
||||
#include "base/util/utils.h"
|
||||
|
||||
using namespace vocl;
|
||||
|
||||
// very simply auto_ptr for arrays
|
||||
template <class T> class auto_array {
|
||||
T *m_array;
|
||||
public:
|
||||
auto_array(T *array = 0) : m_array(array) {}
|
||||
~auto_array() { if (m_array) delete [] m_array; }
|
||||
|
||||
void operator = (T *array) {
|
||||
if (m_array) delete [] m_array;
|
||||
m_array = array;
|
||||
}
|
||||
operator T * () { return m_array; }
|
||||
T *get() { return m_array; }
|
||||
T &operator [] (int index) { return m_array[index]; }
|
||||
};
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
char *sep = TEXT("--------------- %s -----------------------\n");
|
||||
char *sep2 = TEXT("-----------------------------------------------------------\n");
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stdout, "usage: %s <vcard file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// read as char *
|
||||
char *buffer;
|
||||
size_t len;
|
||||
if (!readFile(argv[1], &buffer, &len, true)) {
|
||||
fprintf(stdout, "%s: reading failed", argv[1]);
|
||||
}
|
||||
auto_array<char> vcard(buffer);
|
||||
|
||||
// convert to wchar_t
|
||||
auto_array<wchar_t> wvcard(toWideChar(vcard));
|
||||
fwprintf(stdout, sep, TEXT("original vcard"));
|
||||
fwprintf(stdout, TEXT("%s\n"), wvcard.get());
|
||||
fwprintf(stdout, sep2);
|
||||
fwprintf(stdout, TEXT("\n"));
|
||||
|
||||
// parse it
|
||||
std::auto_ptr<VObject> vobj(VConverter::parse(wvcard));
|
||||
if (vobj.get() == 0) {
|
||||
fprintf(stdout, "VConverter::parse()failed\n");
|
||||
return 1;
|
||||
}
|
||||
vobj->toNativeEncoding();
|
||||
|
||||
VProperty *fileas = vobj->getProperty(TEXT("X-EVOLUTION-FILE-AS"));
|
||||
VProperty *n = vobj->getProperty(TEXT("FN"));
|
||||
fwprintf(stdout,
|
||||
TEXT("version: %s\nprodid: %s\nfull name: %s\nfile-as: %s\n\n"),
|
||||
vobj->getVersion(),
|
||||
vobj->getProdID(),
|
||||
n ? n->getValue() : TEXT("<not set>"),
|
||||
fileas ? fileas->getValue() : TEXT("<not set>"));
|
||||
|
||||
// convert into the other version, then back again
|
||||
wchar_t *versions[2];
|
||||
if (!wcscmp(vobj->getVersion(), TEXT("3.0"))) {
|
||||
versions[0] = TEXT("2.1");
|
||||
versions[1] = TEXT("3.0");
|
||||
} else {
|
||||
versions[0] = TEXT("3.0");
|
||||
versions[1] = TEXT("2.1");
|
||||
}
|
||||
for (int index = 0; index < 2; index++) {
|
||||
vobj->setVersion(versions[index]);
|
||||
VProperty *vprop = vobj->getProperty(TEXT("VERSION"));
|
||||
|
||||
for (int property = vobj->propertiesCount() - 1;
|
||||
property >= 0;
|
||||
property--) {
|
||||
VProperty *vprop = vobj->getProperty(property);
|
||||
|
||||
// replace 3.0 ENCODING=B with 2.1 ENCODING=BASE64 and vice versa
|
||||
char *encoding = vprop->getParameterValue("ENCODING");
|
||||
if (encoding &&
|
||||
(!wcsicmp(TEXT("B"), encoding) || !wcsicmp(TEXT("BASE64"), encoding))) {
|
||||
vprop->removeParameter("ENCODING");
|
||||
vprop->addParameter("ENCODING",
|
||||
!wcscmp(versions[index], TEXT("2.1")) ?
|
||||
"BASE64" : "b");
|
||||
}
|
||||
}
|
||||
|
||||
vprop->setValue(versions[index]);
|
||||
vobj->fromNativeEncoding();
|
||||
wvcard = vobj->toString();
|
||||
vobj->toNativeEncoding();
|
||||
fwprintf(stdout, sep, versions[index]);
|
||||
fwprintf(stdout, TEXT("%s\n"), wvcard.get());
|
||||
fwprintf(stdout, sep2);
|
||||
fwprintf(stdout, TEXT("\n"));
|
||||
}
|
||||
|
||||
#if 0
|
||||
// convert into validated contact
|
||||
vCardConverter converter;
|
||||
converter.setSource(wvcard);
|
||||
Contact *contactPtr;
|
||||
long errorCode;
|
||||
if (!converter.convert(lastErrorMsg, &errorCode)) {
|
||||
fwprintf(stdout, TEXT("converter failed: %s (%ld)\n"), lastErrorMsg, errorCode);
|
||||
return 1;
|
||||
}
|
||||
converter.getContact(&contactPtr);
|
||||
std::auto_ptr<Contact> contact(contactPtr);
|
||||
wvcard = contact->toString();
|
||||
fwprintf(stdout, sep, TEXT("after parsing"));
|
||||
fwprintf(stdout, TEXT("%s\n"), wvcard.get());
|
||||
fwprintf(stdout, sep2);
|
||||
fwprintf(stdout, TEXT("\n"));
|
||||
|
||||
// let's see how the Contact class interprets the properties
|
||||
Name *name = contact->getName();
|
||||
vCardProperty *displayname = name->getDisplayName();
|
||||
fwprintf(stdout,
|
||||
TEXT("display name\nencoding: %s\ncharset: %s\nlanguage: %s\nvalue: %s\n\n"),
|
||||
displayname->getEncoding(),
|
||||
displayname->getCharset(),
|
||||
displayname->getLanguage(),
|
||||
displayname->getValue());
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -4,9 +4,6 @@
|
|||
|
||||
#include <config.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <spds/spdsutils.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
using namespace std;
|
||||
|
@ -67,7 +64,6 @@ int main( int argc, char **argv )
|
|||
g_type_init();
|
||||
#endif
|
||||
|
||||
resetError();
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
|
||||
|
|
Loading…
Reference in a new issue