summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2012-11-01 14:39:31 +0100
committerPatrick Ohly <patrick.ohly@intel.com>2012-11-01 19:13:58 +0100
commit340579cbdbd8f630846d85319b274a3e41a6313a (patch)
treee6b17f0911e3d8bd241eb74e5b14a5c0b7532740
parent6648a36578e2c5b2e87c3bc749c81e8414f423a5 (diff)
parent0d86dc14312ac548fdd5b7c513ef2ab851964f3f (diff)
Merge branch 'HARMATTAN-1-3-1'
Fetched the code and its history from the 1.3.1 archives at: http://people.debian.org/~ovek/maemo/ http://people.debian.org/~ovek/harmattan/ Merged almost everything, except for Maemo/Harmattan specific build files: autogen-maemo.sh builddeb buildsrc debian The following changes were also removed, because they are either local workarounds or merge artifacts which probably also don't belong into the Maemo/Harmattan branch: diff --git a/configure.ac b/configure.ac index cb66617..2c4403c 100644 --- a/configure.ac +++ b/configure.ac @@ -44,7 +44,7 @@ if test "$enable_release_mode" = "yes"; then AC_DEFINE(SYNCEVOLUTION_STABLE_RELEASE, 1, [binary is meant for end-users]) fi -AM_INIT_AUTOMAKE([1.11.1 tar-ustar silent-rules subdir-objects -Wno-portability]) +AM_INIT_AUTOMAKE([subdir-objects -Wno-portability]) AM_PROG_CC_C_O diff --git a/src/backends/webdav/CalDAVSource.cpp b/src/backends/webdav/CalDAVSource.cpp index decd170..7d338ac 100644 --- a/src/backends/webdav/CalDAVSource.cpp +++ b/src/backends/webdav/CalDAVSource.cpp @@ -1282,6 +1282,7 @@ void CalDAVSource::Event::fixIncomingCalendar(icalcomponent *calendar) // time. bool ridInUTC = false; const icaltimezone *zone = NULL; + icalcomponent *parent = NULL; for (icalcomponent *comp = icalcomponent_get_first_component(calendar, ICAL_VEVENT_COMPONENT); comp; @@ -1295,6 +1296,7 @@ void CalDAVSource::Event::fixIncomingCalendar(icalcomponent *calendar) // is parent event? -> remember time zone unless it is UTC static const struct icaltimetype null = { 0 }; if (!memcmp(&rid, &null, sizeof(null))) { + parent = comp; struct icaltimetype dtstart = icalcomponent_get_dtstart(comp); if (!icaltime_is_utc(dtstart)) { zone = icaltime_get_timezone(dtstart); diff --git a/src/backends/webdav/CalDAVSource.h b/src/backends/webdav/CalDAVSource.h index 517ac2f..fa7c2ca 100644 --- a/src/backends/webdav/CalDAVSource.h +++ b/src/backends/webdav/CalDAVSource.h @@ -45,6 +45,10 @@ class CalDAVSource : public WebDAVSource, virtual void removeMergedItem(const std::string &luid); virtual void flushItem(const string &uid); virtual std::string getSubDescription(const string &uid, const string &subid); + virtual void updateSynthesisInfo(SynthesisInfo &info, + XMLConfigFragments &fragments) { + info.m_backendRule = "HAVE-SYNCEVOLUTION-EXDATE-DETACHED"; + } // implementation of SyncSourceLogging callback virtual std::string getDescription(const string &luid); Making SySync_ConsolePrintf a real instance inside SyncEvolution leads to link errors in other configurations. It really has to be extern. Added a comment to the master branch to make that more obvious: -extern "C" { // without curly braces, g++ 4.2 thinks the variable is extern - int (*SySync_ConsolePrintf)(FILE *stream, const char *format, ...); -} +// This is just the declaration. The actual function pointer instance +// is inside libsynthesis, which, for historic purposes, doesn't define +// it in its header files (yet). +extern "C" int (*SySync_ConsolePrintf)(FILE *stream, const char *format, ...);
-rw-r--r--.gitignore4
-rw-r--r--configure.ac9
-rw-r--r--src/backends/evolution/configure-sub.in5
-rw-r--r--src/backends/kcalextended/KCalExtendedSource.cpp170
-rw-r--r--src/backends/kcalextended/KCalExtendedSource.h19
-rw-r--r--src/backends/kcalextended/KCalExtendedSourceRegister.cpp63
-rw-r--r--src/backends/maemo/MaemoCalendarSource.cpp104
-rw-r--r--src/backends/maemo/MaemoCalendarSource.h21
-rw-r--r--src/backends/maemo/MaemoCalendarSourceRegister.cpp6
-rw-r--r--src/backends/qtcontacts/QtContactsSource.cpp40
-rwxr-xr-xsrc/backends/webdav/syncevo-webdav-lookup.sh13
-rw-r--r--src/backends/webdav/webdav.am2
-rw-r--r--src/syncevo/CurlTransportAgent.cpp3
-rw-r--r--src/syncevo/LocalTransportAgent.cpp2
-rw-r--r--src/syncevo/SyncContext.cpp3
-rw-r--r--src/syncevo/eds_abi_wrapper.h2
-rw-r--r--test/ClientTest.cpp18
17 files changed, 397 insertions, 87 deletions
diff --git a/.gitignore b/.gitignore
index bf29bed4..07ffa646 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,7 @@ Makefile.in
/config.sub
/configure
/depcomp
+/INSTALL
/install-sh
/libtool
/ltmain.sh
@@ -35,6 +36,9 @@ Makefile.in
/syncevolution.1
/syncevolution-*.tar.gz
+# for Maemo build
+/libsynthesis
+
# po
/po/*.gmo
/po/.intltool-merge-cache
diff --git a/configure.ac b/configure.ac
index 4a957425..cb66617e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -55,7 +55,8 @@ dnl Specify git revisions/branches without prefix, i.e., without 'origin'.
dnl We'll sort that out below.
define([SYNTHESISSRC_REVISION], [syncevolution-0.9])
AC_CONFIG_HEADERS(config.h)
-LT_INIT([dlopen])
+AC_LIBTOOL_DLOPEN
+AC_PROG_LIBTOOL
dnl check for programs.
AC_PROG_CXX
@@ -677,7 +678,11 @@ AC_SUBST(GUI_DESKTOP_FILES)
# C++ regular expression support is required often enough to make it
# mandatory.
-PKG_CHECK_MODULES(PCRECPP, libpcrecpp)
+PKG_CHECK_MODULES(PCRECPP, libpcrecpp,,
+AC_CHECK_LIB(pcrecpp,main,
+AC_SUBST(PCRECPP_LIBS,-lpcrecpp),
+AC_MSG_ERROR([pcrecpp not found])
+))
# need rst2man for man pages
AC_ARG_WITH(rst2man,
diff --git a/src/backends/evolution/configure-sub.in b/src/backends/evolution/configure-sub.in
index 8ffad9dc..e27b0307 100644
--- a/src/backends/evolution/configure-sub.in
+++ b/src/backends/evolution/configure-sub.in
@@ -68,7 +68,10 @@ if test "$enable_evo" = "yes"; then
# Only the EClient code supports the API in EDS 3.5.x.
PKG_CHECK_MODULES(EDS_VERSION, [libedataserver-1.2 >= 3.5],
[AC_DEFINE(USE_EDS_CLIENT, 1, [use e_book/cal_client_* calls])],
- [true])
+ [CFLAGS_old="$CFLAGS"
+ CFLAGS="$CFLAGS $EPACKAGE_CFLAGS"
+ AC_CHECK_HEADERS(libedataserver/eds-version.h)
+ CFLAGS="$CFLAGS_old"])
else
EPACKAGE_CFLAGS=
EPACKAGE_LIBS=
diff --git a/src/backends/kcalextended/KCalExtendedSource.cpp b/src/backends/kcalextended/KCalExtendedSource.cpp
index 8849c733..0e3cbebd 100644
--- a/src/backends/kcalextended/KCalExtendedSource.cpp
+++ b/src/backends/kcalextended/KCalExtendedSource.cpp
@@ -65,12 +65,26 @@ class KCalExtendedData
public:
KCalExtendedData(KCalExtendedSource *parent,
const QString &notebook,
- const KCalCore::IncidenceBase::IncidenceType &type) :
+ const KCalExtendedSource::Type &type) :
m_parent(parent),
m_modified(false),
- m_notebook(notebook),
- m_type(type)
+ m_notebook(notebook)
{
+ switch (type)
+ {
+ case KCalExtendedSource::Event:
+ m_type = KCalCore::IncidenceBase::TypeEvent;
+ break;
+ case KCalExtendedSource::Todo:
+ m_type = KCalCore::IncidenceBase::TypeTodo;
+ break;
+ case KCalExtendedSource::Journal:
+ m_type = KCalCore::IncidenceBase::TypeJournal;
+ break;
+ default:
+ m_type = KCalCore::IncidenceBase::TypeUnknown;
+ break;
+ }
if (!qApp) {
static const char *argv[] = { "SyncEvolution" };
static int argc = 1;
@@ -176,25 +190,36 @@ KCalExtendedData::ItemID KCalExtendedData::getItemID(const KCalCore::Incidence::
return ItemID(qstring2std(uid), ridStr);
}
-KCalExtendedSource::KCalExtendedSource(const SyncSourceParams &params) :
+KCalExtendedSource::KCalExtendedSource(const SyncSourceParams &params, Type type) :
TestingSyncSource(params)
{
SyncSourceRevisions::init(this, this, 0, m_operations);
- SyncSourceLogging::init(InitList<std::string>("SUMMARY") + "LOCATION",
- ", ",
- m_operations);
-#if 0
- // VTODO
- SyncSourceLogging::init(InitList<std::string>("SUMMARY"),
- ", ",
- m_operations);
- // VJOURNAL
- SyncSourceLogging::init(InitList<std::string>("SUBJECT"),
- ", ",
- m_operations);
-#endif
+ switch (type)
+ {
+ case Event:
+ SyncSourceLogging::init(InitList<std::string>("SUMMARY") + "LOCATION",
+ ", ",
+ m_operations);
+ break;
+ case Todo:
+ SyncSourceLogging::init(InitList<std::string>("SUMMARY"),
+ ", ",
+ m_operations);
+ break;
+ case Journal:
+ SyncSourceLogging::init(InitList<std::string>("SUBJECT"),
+ ", ",
+ m_operations);
+ break;
+ default:
+ throwError("invalid calendar type");
+ break;
+ }
m_data = NULL;
+ m_type = type;
+ m_delete_run = 0;
+ m_insert_run = 0;
}
KCalExtendedSource::~KCalExtendedSource()
@@ -202,14 +227,25 @@ KCalExtendedSource::~KCalExtendedSource()
delete m_data;
}
+std::string KCalExtendedSource::getMimeType() const
+{
+ return m_type == Journal ?
+ "text/calendar+plain" :
+ "text/calendar";
+}
+
+std::string KCalExtendedSource::getMimeVersion() const
+{
+ return "2.0";
+}
+
void KCalExtendedSource::open()
{
// read specified database name from "database" property
std::string databaseID = getDatabaseID();
// TODO: also support todoType
- m_data = new KCalExtendedData(this, databaseID.c_str(),
- KCalCore::IncidenceBase::TypeEvent);
+ m_data = new KCalExtendedData(this, databaseID.c_str(), m_type);
m_data->m_calendar = mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(KDateTime::Spec::LocalZone()));
if (databaseID.empty() || boost::starts_with(databaseID, "file://") ) {
@@ -227,11 +263,40 @@ void KCalExtendedSource::open()
if (!m_data->m_storage->open()) {
throwError("failed to open storage");
}
+#ifdef ENABLE_MAEMO
+ mKCal::Notebook::Ptr defaultNotebook;
+ // For notes, we need a different default database:
+ // Notes (uid:66666666-7777-8888-9999-000000000000)
+ if (databaseID.empty() && m_type == Journal)
+ {
+ defaultNotebook = m_data->m_storage->notebook("66666666-7777-8888-9999-000000000000");
+ }
+ else
+ {
+ defaultNotebook = m_data->m_storage->defaultNotebook();
+ }
+#else
mKCal::Notebook::Ptr defaultNotebook = m_data->m_storage->defaultNotebook();
+#endif
if (!defaultNotebook) {
throwError("no default Notebook");
}
m_data->m_notebookUID = defaultNotebook->uid();
+#ifdef ENABLE_MAEMO
+ } else if (boost::starts_with(databaseID, "uid:")) {
+ // if databaseID has a "uid:" prefix, open existing notebook with given ID in default storage
+ m_data->m_storage = mKCal::ExtendedCalendar::defaultStorage(m_data->m_calendar);
+ if (!m_data->m_storage->open()) {
+ throwError("failed to open storage");
+ }
+ QString uid = databaseID.c_str() + strlen("uid:");
+ mKCal::Notebook::Ptr notebook = m_data->m_storage->notebook(uid);
+
+ if ( !notebook ) {
+ throwError(string("no such notebook with UID \"") + uid.toStdString() + string("\" in default storage"));
+ }
+ m_data->m_notebookUID = notebook->uid();
+#endif
} else {
// use databaseID as notebook name to search for an existing notebook
// if found use it, otherwise:
@@ -270,14 +335,24 @@ void KCalExtendedSource::open()
// we are not currently using partial loading because there were
// issues with it (BMC #6061); the load() calls elsewhere in this
// file are commented out
- if (!m_data->m_storage->load()) {
+ if (!m_data->m_storage->loadNotebookIncidences(m_data->m_notebookUID)) {
throwError("failed to load calendar");
}
}
bool KCalExtendedSource::isEmpty()
{
- return false;
+ switch (m_data->m_type)
+ {
+ case KCalCore::IncidenceBase::TypeEvent:
+ return !m_data->m_calendar->eventCount();
+ case KCalCore::IncidenceBase::TypeTodo:
+ return !m_data->m_calendar->todoCount();
+ case KCalCore::IncidenceBase::TypeJournal:
+ return !m_data->m_calendar->journalCount();
+ default:
+ return true;
+ }
}
void KCalExtendedSource::close()
@@ -305,8 +380,7 @@ KCalExtendedSource::Databases KCalExtendedSource::getDatabases()
{
Databases result;
- m_data = new KCalExtendedData(this, getDatabaseID().c_str(),
- KCalCore::IncidenceBase::TypeEvent);
+ m_data = new KCalExtendedData(this, getDatabaseID().c_str(), m_type);
m_data->m_calendar = mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(KDateTime::Spec::LocalZone()));
m_data->m_storage = mKCal::ExtendedCalendar::defaultStorage(m_data->m_calendar);
if (!m_data->m_storage->open()) {
@@ -315,10 +389,21 @@ KCalExtendedSource::Databases KCalExtendedSource::getDatabases()
mKCal::Notebook::List notebookList = m_data->m_storage->notebooks();
mKCal::Notebook::List::Iterator it;
for ( it = notebookList.begin(); it != notebookList.end(); ++it ) {
+#ifdef ENABLE_MAEMO
+ string name = (*it)->name().toStdString();
+ string uid = (*it)->uid().toStdString();
+ // For notes, we need a different default database:
+ // Notes (uid:66666666-7777-8888-9999-000000000000)
+ bool isDefault = (m_type != Journal) ?
+ (*it)->isDefault() :
+ (uid == "66666666-7777-8888-9999-000000000000");
+ result.push_back(Database( name, "uid:" + uid, isDefault ));
+#else
bool isDefault = (*it)->isDefault();
result.push_back(Database( (*it)->name().toStdString(),
(m_data->m_storage).staticCast<mKCal::SqliteStorage>()->databaseName().toStdString(),
isDefault));
+#endif
}
m_data->m_storage->close();
m_data->m_calendar->close();
@@ -330,9 +415,10 @@ void KCalExtendedSource::beginSync(const std::string &lastToken, const std::stri
const char *anchor = resumeToken.empty() ? lastToken.c_str() : resumeToken.c_str();
KCalCore::Incidence::List incidences;
// return all items
- if (!m_data->m_storage->allIncidences(&incidences, m_data->m_notebookUID)) {
- throwError("allIncidences() failed");
- }
+ incidences = m_data->m_calendar->incidences();
+ // if (!m_data->m_storage->allIncidences(&incidences, m_data->m_notebookUID)) {
+ // throwError("allIncidences() failed");
+ // }
m_data->extractIncidences(incidences, SyncSourceChanges::ANY, *this);
if (*anchor) {
SE_LOG_DEBUG(NULL, NULL, "checking for changes since %s UTC", anchor);
@@ -372,6 +458,8 @@ std::string KCalExtendedSource::endSync(bool success)
sleep(1 - (current - modtime));
current = time(NULL);
} while (current - modtime < 1);
+ m_delete_run = 0;
+ m_insert_run = 0;
}
QDateTime now = QDateTime::currentDateTime().toUTC();
@@ -393,6 +481,21 @@ void KCalExtendedSource::readItem(const string &uid, std::string &item)
TestingSyncSource::InsertItemResult KCalExtendedSource::insertItem(const string &uid, const std::string &item)
{
+ if (m_delete_run > 0)
+ {
+ // Since the storage's save() might do deletes *after* inserts,
+ // the final save() could fail if we're doing a refresh-from-peer
+ // (where everything is first deleted and then reinserted), as
+ // the inserts will fail due to the existing entries not being
+ // deleted yet. To avoid the problem, make sure we save between
+ // the deletes and the inserts.
+ if (!m_data->m_storage->save()) {
+ throwError("could not save calendar");
+ }
+ m_delete_run = 0;
+ m_insert_run = 0;
+ }
+
KCalCore::Calendar::Ptr calendar(new KCalCore::MemoryCalendar(KDateTime::Spec::LocalZone()));
KCalCore::ICalFormat parser;
if (!parser.fromString(calendar, std2qstring(item))) {
@@ -402,7 +505,7 @@ TestingSyncSource::InsertItemResult KCalExtendedSource::insertItem(const string
if (incidences.empty()) {
throwError("iCalendar 2.0 item empty?!");
}
- bool updated;
+ InsertItemResultState updated;
string newUID;
string oldUID = uid;
@@ -437,7 +540,7 @@ TestingSyncSource::InsertItemResult KCalExtendedSource::insertItem(const string
if (oldUID.empty()) {
KCalCore::Incidence::Ptr incidence = incidences[0];
- updated = false;
+ updated = ITEM_OKAY;
if (!m_data->m_calendar->addIncidence(incidence)) {
throwError("could not add incidence");
}
@@ -445,7 +548,7 @@ TestingSyncSource::InsertItemResult KCalExtendedSource::insertItem(const string
newUID = m_data->getItemID(incidence).getLUID();
} else {
KCalCore::Incidence::Ptr incidence = incidences[0];
- updated = true;
+ updated = uid.empty() ? ITEM_REPLACED : ITEM_OKAY;
newUID = oldUID;
KCalCore::Incidence::Ptr original = m_data->findIncidence(oldUID);
if (!original) {
@@ -475,6 +578,7 @@ TestingSyncSource::InsertItemResult KCalExtendedSource::insertItem(const string
}
m_data->m_modified = true;
+ m_insert_run++;
return InsertItemResult(newUID,
"",
@@ -495,14 +599,16 @@ void KCalExtendedSource::deleteItem(const string &uid)
throwError(string("could not delete incidence") + uid);
}
m_data->m_modified = true;
+ m_delete_run++;
}
void KCalExtendedSource::listAllItems(RevisionMap_t &revisions)
{
KCalCore::Incidence::List incidences;
- if (!m_data->m_storage->allIncidences(&incidences, m_data->m_notebookUID)) {
- throwError("allIncidences() failed");
- }
+ incidences = m_data->m_calendar->incidences();
+ // if (!m_data->m_storage->allIncidences(&incidences, m_data->m_notebookUID)) {
+ // throwError("allIncidences() failed");
+ // }
foreach (KCalCore::Incidence::Ptr incidence, incidences) {
if (incidence->type() == m_data->m_type) {
revisions[m_data->getItemID(incidence).getLUID()] = "1";
diff --git a/src/backends/kcalextended/KCalExtendedSource.h b/src/backends/kcalextended/KCalExtendedSource.h
index 49af80a0..179fd860 100644
--- a/src/backends/kcalextended/KCalExtendedSource.h
+++ b/src/backends/kcalextended/KCalExtendedSource.h
@@ -45,8 +45,14 @@ class KCalExtendedData;
*/
class KCalExtendedSource : public TestingSyncSource, private SyncSourceAdmin, private SyncSourceBlob, private SyncSourceRevisions, public SyncSourceLogging, private boost::noncopyable
{
- public:
- KCalExtendedSource(const SyncSourceParams &params);
+ public:
+ enum Type {
+ Event = 0,
+ Todo = 1,
+ Journal = 2
+ };
+
+ KCalExtendedSource(const SyncSourceParams &params, Type type);
~KCalExtendedSource();
protected:
@@ -57,7 +63,7 @@ class KCalExtendedSource : public TestingSyncSource, private SyncSourceAdmin, pr
virtual Databases getDatabases();
virtual void enableServerMode();
virtual bool serverModeEnabled() const;
- virtual std::string getPeerMimeType() const { return "text/calendar"; }
+ virtual std::string getPeerMimeType() const { return getMimeType(); }
/* implementation of SyncSourceSession interface */
virtual void beginSync(const std::string &lastToken, const std::string &resumeToken);
@@ -67,8 +73,8 @@ class KCalExtendedSource : public TestingSyncSource, private SyncSourceAdmin, pr
virtual void deleteItem(const string &luid);
/* implementation of SyncSourceSerialize interface */
- virtual std::string getMimeType() const { return "text/calendar"; }
- virtual std::string getMimeVersion() const { return "2.0"; }
+ virtual std::string getMimeType() const;
+ virtual std::string getMimeVersion() const;
virtual InsertItemResult insertItem(const std::string &luid, const std::string &item);
virtual void readItem(const std::string &luid, std::string &item);
@@ -84,6 +90,9 @@ class KCalExtendedSource : public TestingSyncSource, private SyncSourceAdmin, pr
private:
KCalExtendedData *m_data;
+ Type m_type;
+ unsigned m_delete_run;
+ unsigned m_insert_run;
};
SE_END_CXX
diff --git a/src/backends/kcalextended/KCalExtendedSourceRegister.cpp b/src/backends/kcalextended/KCalExtendedSourceRegister.cpp
index 8d69696e..6a06346a 100644
--- a/src/backends/kcalextended/KCalExtendedSourceRegister.cpp
+++ b/src/backends/kcalextended/KCalExtendedSourceRegister.cpp
@@ -27,7 +27,7 @@ SE_BEGIN_CXX
static SyncSource *createSource(const SyncSourceParams &params)
{
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
- bool isMe = sourceType.m_backend == "mkcal";
+ bool isMe = sourceType.m_backend == "mkcal-events";
bool maybeMe = sourceType.m_backend == "calendar";
if (isMe || maybeMe) {
@@ -37,11 +37,44 @@ static SyncSource *createSource(const SyncSourceParams &params)
sourceType.m_format == "text/calendar") {
return
#ifdef ENABLE_KCALEXTENDED
- true ? new KCalExtendedSource(params) :
+ true ? new KCalExtendedSource(params, KCalExtendedSource::Event) :
#endif
isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
}
}
+
+ isMe = sourceType.m_backend == "mkcal-todos";
+ maybeMe = sourceType.m_backend == "todo";
+
+ if (isMe || maybeMe) {
+ if (sourceType.m_format == "" ||
+ sourceType.m_format == "text/x-vcalendar" ||
+ sourceType.m_format == "text/x-calendar" ||
+ sourceType.m_format == "text/calendar") {
+ return
+#ifdef ENABLE_KCALEXTENDED
+ true ? new KCalExtendedSource(params, KCalExtendedSource::Todo) :
+#endif
+ isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
+ }
+ }
+
+ isMe = sourceType.m_backend == "mkcal-notes";
+ maybeMe = sourceType.m_backend == "memo";
+
+ if (isMe || maybeMe) {
+ if (sourceType.m_format == "" ||
+ sourceType.m_format == "text/x-vcalendar" ||
+ sourceType.m_format == "text/x-calendar" ||
+ sourceType.m_format == "text/calendar") {
+ return
+#ifdef ENABLE_KCALEXTENDED
+ true ? new KCalExtendedSource(params, KCalExtendedSource::Journal) :
+#endif
+ isMe ? RegisterSyncSource::InactiveSource(params) : NULL;
+ }
+ }
+
return NULL;
}
@@ -52,16 +85,36 @@ static RegisterSyncSource registerMe("KCalExtended",
false,
#endif
createSource,
- "mkcal = KCalExtended = calendar\n"
+ "mkcal-events = mkcal = KCalExtended = calendar\n"
" 'database' normally is the name of a calendar\n"
" inside the default calendar storage. If it starts\n"
" with the 'SyncEvolution_Test_' prefix, it will be\n"
" created as needed, otherwise it must exist.\n"
+#ifdef ENABLE_MAEMO
+ " If it starts with the 'uid:' prefix, the specified\n"
+ " calendar in the default SQLite storage file will\n"
+ " be used. It must exist.\n"
+#endif
" If it starts with the 'file://' prefix, the default\n"
" calendar in the specified SQLite storage file will\n"
- " created (if needed) and used.\n",
+ " created (if needed) and used.\n"
+ "mkcal-todos = todo\n"
+ " Same as above.\n"
+ "mkcal-notes = memo\n"
+#ifdef ENABLE_MAEMO
+ " Same as above. Keep in mind that, by default, notes\n"
+ " are stored in their own database, separate from\n"
+ " events and todos. The name of this database is\n"
+ " hardcoded into the device's builtin Notes app.\n"
+ " Don't override the default unless you know what\n"
+ " you are doing.\n",
+#else
+ " Same as above.\n",
+#endif
Values() +
- (Aliases("mkcal") + "KCalExtended" + "MeeGo Calendar"));
+ (Aliases("mkcal-events") + "mkcal" + "KCalExtended" + "MeeGo Calendar") +
+ (Aliases("mkcal-todos") + "MeeGo Tasks") +
+ (Aliases("mkcal-notes") + "MeeGo Notes"));
#ifdef ENABLE_KCALEXTENDED
#ifdef ENABLE_UNIT_TESTS
diff --git a/src/backends/maemo/MaemoCalendarSource.cpp b/src/backends/maemo/MaemoCalendarSource.cpp
index 39a4682a..6b7300c1 100644
--- a/src/backends/maemo/MaemoCalendarSource.cpp
+++ b/src/backends/maemo/MaemoCalendarSource.cpp
@@ -46,6 +46,26 @@ MaemoCalendarSource::MaemoCalendarSource(int EntryType, int EntryFormat,
TrackingSyncSource(params),
entry_type(EntryType), entry_format(EntryFormat)
{
+ switch (EntryType) {
+ case EVENT:
+ SyncSourceLogging::init(InitList<std::string>("SUMMARY") + "LOCATION",
+ ", ",
+ m_operations);
+ break;
+ case TODO:
+ SyncSourceLogging::init(InitList<std::string>("SUMMARY"),
+ ", ",
+ m_operations);
+ break;
+ case JOURNAL:
+ SyncSourceLogging::init(InitList<std::string>("SUBJECT"),
+ ", ",
+ m_operations);
+ break;
+ default:
+ throwError("invalid calendar type");
+ break;
+ }
mc = CMulticalendar::MCInstance();
cal = NULL;
if (!mc) {
@@ -53,17 +73,19 @@ MaemoCalendarSource::MaemoCalendarSource(int EntryType, int EntryFormat,
}
}
-const char *MaemoCalendarSource::getMimeType() const
+std::string MaemoCalendarSource::getMimeType() const
{
switch (entry_format) {
case -1: return "text/plain";
- case ICAL_TYPE: return "text/calendar";
+ case ICAL_TYPE: return entry_type == JOURNAL ?
+ "text/calendar+plain" :
+ "text/calendar";
case VCAL_TYPE: return "text/x-calendar";
default: return NULL;
}
}
-const char *MaemoCalendarSource::getMimeVersion() const
+std::string MaemoCalendarSource::getMimeVersion() const
{
switch (entry_format) {
case -1: return "1.0";
@@ -113,10 +135,13 @@ void MaemoCalendarSource::open()
bool MaemoCalendarSource::isEmpty()
{
- // TODO: provide a real implementation. Always returning false
- // here disables the "allow slow sync when no local data" heuristic
- // for preventSlowSync=1.
- return false;
+ int id = cal->getCalendarId(), err;
+ switch (entry_type) {
+ case EVENT: return !mc->getEventCount(id, err);
+ case TODO: return !mc->getTodoCount(id, err);
+ case JOURNAL: return !mc->getNoteCount(id, err);
+ default: return true;
+ }
}
void MaemoCalendarSource::close()
@@ -125,9 +150,6 @@ void MaemoCalendarSource::close()
conv = NULL;
delete cal;
cal = NULL;
- // since timestamps are rounded down to nearest second,
- // sleep until next second, just in case
- sleep(1);
}
MaemoCalendarSource::Databases MaemoCalendarSource::getDatabases()
@@ -159,7 +181,9 @@ void MaemoCalendarSource::listAllItems(RevisionMap_t &revisions)
#if 0 /* this code exposes a bug in calendar-backend, https://bugs.maemo.org/show_bug.cgi?id=8277 */
// I've found no way to query the last modified time of a component
// without getting the whole component.
- // This limit should hopefully reduce memory usage of that a bit
+ // This limit should hopefully reduce memory usage of that a bit,
+ // though it could be bad if the database happens to change
+ // between getComponents() calls.
static const int limit = 1024;
int ofs = 0, err;
vector< CComponent * > comps;
@@ -180,14 +204,20 @@ void MaemoCalendarSource::listAllItems(RevisionMap_t &revisions)
}
}
#else
- // this avoids the calendar-backend bug, but may use unlimited memory;
- // hopefully the users aren't saving their entire life here!
+ // Instead, get a full list of IDs from getIdList(), then
+ // load each entry from the calendar one by one. The
+ // alternative would be to load the whole calendar into
+ // memory all at once, but that's probably not all that
+ // desirable, given the N900's limited memory.
int err;
- vector< CComponent * > comps;
-
- comps = cal->getComponents(entry_type, -1, -1, err);
- BOOST_FOREACH(CComponent * c, comps) {
- revisions[c->getId()] = get_revision(c);
+ vector< string > ids = cal->getIdList(entry_type, err);
+ BOOST_FOREACH(std::string& id, ids) {
+ CComponent *c = cal->getEntry(id, entry_type, err);
+ if (!c)
+ {
+ throwError(string("retrieving item: ") + id);
+ }
+ revisions[id] = get_revision(c);
delete c;
}
#endif
@@ -201,7 +231,7 @@ void MaemoCalendarSource::readItem(const string &uid, std::string &item, bool ra
throwError(string("retrieving item: ") + uid);
}
if (entry_format == -1) {
- item = c->getDescription();
+ item = c->getSummary();
err = CALENDAR_OPERATION_SUCCESSFUL;
} else {
item = conv->localToIcalVcal(c, FileType(entry_format), err);
@@ -216,7 +246,8 @@ TrackingSyncSource::InsertItemResult MaemoCalendarSource::insertItem(const strin
{
int err;
CComponent *c;
- bool r, u = false;
+ bool r;
+ InsertItemResultState u = ITEM_OKAY;
TrackingSyncSource::InsertItemResult result;
if (cal->getCalendarType() == BIRTHDAY_CALENDAR) {
@@ -275,7 +306,7 @@ TrackingSyncSource::InsertItemResult MaemoCalendarSource::insertItem(const strin
throwError(string("creating item "));
}
if (err == CALENDAR_ENTRY_DUPLICATED) {
- u = true;
+ u = ITEM_REPLACED;
}
}
@@ -288,6 +319,12 @@ TrackingSyncSource::InsertItemResult MaemoCalendarSource::insertItem(const strin
void MaemoCalendarSource::removeItem(const string &uid)
{
int err;
+
+ if (cal->getCalendarType() == BIRTHDAY_CALENDAR) {
+ // stubbornly refuse to try this
+ throwError(string("can't sync smart calendar ") + cal->getCalendarName());
+ }
+
cal->deleteComponent(uid, err);
if (err != CALENDAR_OPERATION_SUCCESSFUL) {
throwError(string("deleting item: ") + uid);
@@ -304,6 +341,31 @@ string MaemoCalendarSource::get_revision(CComponent * c)
return revision.str();
}
+std::string MaemoCalendarSource::getDescription(const string &uid)
+{
+ string ret;
+ int err;
+ CComponent * c = cal->getEntry(uid, entry_type, err);
+ if (c) {
+ list<string> parts;
+ string str;
+ str = c->getSummary();
+ if (!str.empty()) {
+ parts.push_back(str);
+ }
+ if (entry_type == EVENT)
+ {
+ str = c->getLocation();
+ if (!str.empty()) {
+ parts.push_back(str);
+ }
+ }
+ ret = boost::join(parts, ", ");
+ delete c;
+ }
+ return ret;
+}
+
SE_END_CXX
#endif /* ENABLE_MAEMO_CALENDAR */
diff --git a/src/backends/maemo/MaemoCalendarSource.h b/src/backends/maemo/MaemoCalendarSource.h
index 5f68cfe7..b995600e 100644
--- a/src/backends/maemo/MaemoCalendarSource.h
+++ b/src/backends/maemo/MaemoCalendarSource.h
@@ -35,13 +35,13 @@ SE_BEGIN_CXX
/**
* Implement access to Maemo calendar.
- * Change tracking is done by using the last-modified time.
- * It might be possible to improve on it by taking the last sync time
- * and calling the getAllAdded/Modified/Deleted(...) methods provided by
- * the CCalendar class, instead of comparing every single record in
- * the database like TrackingSyncSource probably needs to do otherwise.
+ * Change tracking is done by using the last-modified time
+ * as TrackingSyncSource revisions. While it might be possible
+ * to improve performance by using the getAllAdded/Modified
+ * etc methods, it would make the change tracking less robust,
+ * so it doesn't seem worth it.
*/
-class MaemoCalendarSource : public TrackingSyncSource, private boost::noncopyable
+class MaemoCalendarSource : public TrackingSyncSource, public SyncSourceLogging, private boost::noncopyable
{
public:
MaemoCalendarSource(int EntryType, int EntryFormat,
@@ -54,8 +54,8 @@ class MaemoCalendarSource : public TrackingSyncSource, private boost::noncopyabl
virtual bool isEmpty();
virtual void close();
virtual Databases getDatabases();
- virtual const char *getMimeType() const;
- virtual const char *getMimeVersion() const;
+ virtual std::string getMimeType() const;
+ virtual std::string getMimeVersion() const;
virtual void getSynthesisInfo(SynthesisInfo &info,
XMLConfigFragments &fragments);
@@ -63,8 +63,11 @@ class MaemoCalendarSource : public TrackingSyncSource, private boost::noncopyabl
virtual void listAllItems(RevisionMap_t &revisions);
virtual InsertItemResult insertItem(const string &luid, const std::string &item, bool raw);
void readItem(const std::string &luid, std::string &item, bool raw);
- virtual void removeItem(const string &uid);
+ virtual void removeItem(const string &luid);
+ /* implementation of SyncSourceLogging interface */
+ virtual std::string getDescription(const string &luid);
+
private:
CMulticalendar *mc; /**< multicalendar */
CCalendar *cal; /**< calendar */
diff --git a/src/backends/maemo/MaemoCalendarSourceRegister.cpp b/src/backends/maemo/MaemoCalendarSourceRegister.cpp
index a42aa8d2..fceeb909 100644
--- a/src/backends/maemo/MaemoCalendarSourceRegister.cpp
+++ b/src/backends/maemo/MaemoCalendarSourceRegister.cpp
@@ -68,12 +68,12 @@ static SyncSource *createSource(const SyncSourceParams &params)
maybeMe = sourceType.m_backend == "memo";
if (isMe || maybeMe) {
- if (sourceType.m_format == "" || sourceType.m_format == "text/plain") {
- return new MaemoCalendarSource(JOURNAL, -1, params);
- } else if (sourceType.m_format == "text/calendar") {
+ if (sourceType.m_format == "" || sourceType.m_format == "text/calendar") {
return new MaemoCalendarSource(JOURNAL, ICAL_TYPE, params);
} else if (sourceType.m_format == "text/x-vcalendar") {
return new MaemoCalendarSource(JOURNAL, VCAL_TYPE, params);
+ } else if (sourceType.m_format == "text/plain") {
+ return new MaemoCalendarSource(JOURNAL, -1, params);
} else {
return NULL;
}
diff --git a/src/backends/qtcontacts/QtContactsSource.cpp b/src/backends/qtcontacts/QtContactsSource.cpp
index da7b5f8b..2b94cfd5 100644
--- a/src/backends/qtcontacts/QtContactsSource.cpp
+++ b/src/backends/qtcontacts/QtContactsSource.cpp
@@ -36,6 +36,8 @@
#include <QContactLocalIdFilter>
#include <QContactThumbnail>
#include <QContactAvatar>
+#include <QContactSyncTarget>
+#include <QContactDetailFilter>
#include <QVersitContactExporter>
#include <QVersitContactImporter>
@@ -422,17 +424,42 @@ QtContactsSource::Databases QtContactsSource::getDatabases()
{
Databases result;
QStringList availableManagers = QContactManager::availableManagers();
+ bool isDefault = true;
+#if 0
result.push_back(Database("select database via QtContacts Manager URL",
"qtcontacts:tracker:"));
+#endif
+
+ foreach (QString manager, availableManagers) {
+ QMap<QString, QString> params;
+ QString uri = QContactManager::buildUri(manager, params);
+ result.push_back(Database(manager.toStdString(),
+ uri.toStdString(),
+ isDefault));
+ isDefault = false;
+ }
return result;
}
void QtContactsSource::listAllItems(RevisionMap_t &revisions)
{
+#ifdef ENABLE_MAEMO
+ QContactLocalId self_id = m_data->m_manager->selfContactId();
+#endif
+
QContactFetchRequest fetch;
fetch.setManager(m_data->m_manager.get());
+#ifdef ENABLE_MAEMO
+ // only sync contacts from addressbook, not from Telepathy or wherever
+ QContactDetailFilter filter;
+ filter.setDetailDefinitionName(QContactSyncTarget::DefinitionName, QContactSyncTarget::FieldSyncTarget);
+ filter.setValue("addressbook");
+ filter.setMatchFlags(QContactFilter::MatchExactly);
+ fetch.setFilter(filter);
+#endif
+
// only need ID and time stamps
QContactFetchHint hint;
hint.setOptimizationHints(QContactFetchHint::OptimizationHints(QContactFetchHint::NoRelationships|QContactFetchHint::NoBinaryBlobs));
@@ -443,6 +470,13 @@ void QtContactsSource::listAllItems(RevisionMap_t &revisions)
fetch.waitForFinished();
m_data->checkError("read all items", fetch);
foreach (const QContact &contact, fetch.contacts()) {
+#ifdef ENABLE_MAEMO
+ if (contact.localId() == self_id) {
+ // Do not synchronize "self" contact
+ continue;
+ }
+#endif
+
string revision = QtContactsData::getRev(contact);
string luid = QtContactsData::getLUID(contact);
if (luid == "2147483647" &&
@@ -478,6 +512,10 @@ void QtContactsSource::readItem(const string &uid, std::string &item, bool raw)
thumbnail.setThumbnail(image);
contact.saveDetail(&thumbnail);
}
+
+// foreach (const QContactSyncTarget &target, contact.details<QContactSyncTarget>()) {
+// std::cout << " Sync Target: " << target.syncTarget().toUtf8().data() << std::endl;
+// }
}
QStringList profiles;
@@ -559,7 +597,7 @@ TrackingSyncSource::InsertItemResult QtContactsSource::insertItem(const string &
return InsertItemResult(QtContactsData::getLUID(savedContact),
QtContactsData::getRev(finalContact),
- false);
+ ITEM_OKAY);
}
diff --git a/src/backends/webdav/syncevo-webdav-lookup.sh b/src/backends/webdav/syncevo-webdav-lookup.sh
index a30aa1f0..88496f72 100755
--- a/src/backends/webdav/syncevo-webdav-lookup.sh
+++ b/src/backends/webdav/syncevo-webdav-lookup.sh
@@ -1,4 +1,4 @@
-#! /bin/bash
+#! /bin/sh
#
# Copyright (C) 2011 Intel Corporation
#
@@ -49,7 +49,7 @@ trap "[ -s $LOG ] && ( echo $0 failed to find '$TYPE $DOMAIN':; cat $LOG >&2 );
# find one of the supported tools for DNS queries
TOOL=
-ALTERNATIVES="adnshost host nslookup"
+ALTERNATIVES="adnshost host /usr/lib/syncevolution/host nslookup"
for i in $ALTERNATIVES; do
if which $i >/dev/null; then
TOOL=$i
@@ -89,11 +89,12 @@ for type in ${TYPE}s ${TYPE}; do
PORT=`echo $res | sed -e 's;.*service = [^ ]* [^ ]* \([^ ]*\) \([^ ]*\)\.;\1;'`
HOSTNAME=`echo $res | sed -e 's;.*service = [^ ]* [^ ]* \([^ ]*\) \([^ ]*\)\.;\2;'`
;;
- host)
- res=`$TOOL -t srv _$type._tcp.$DOMAIN | tee -a $LOG | grep "has SRV record" | head -1`
+ host|*/host)
+ res=`$TOOL -t srv _$type._tcp.$DOMAIN | tee -a $LOG | grep "\<SRV\>" | head -1`
# _caldavs._tcp.yahoo.com has SRV record 1 1 443 caldav.calendar.yahoo.com.
- PORT=`echo $res | sed -e 's;.* \([^ ]*\) \([^ ]*\)\.;\1;'`
- HOSTNAME=`echo $res | sed -e 's;.* \([^ ]*\) \([^ ]*\)\.;\2;'`
+ # _caldavs._tcp.yahoo.com SRV 1 1 443 caldav.calendar.yahoo.com
+ PORT=`echo $res | sed -e 's;.* \([^ ]*\) \([^. ]\+\(\.[^. ]\+\)*\)\.\?;\1;'`
+ HOSTNAME=`echo $res | sed -e 's;.* \([^ ]*\) \([^. ]\+\(\.[^. ]\+\)*\)\.\?;\2;'`
;;
*)
echo "unsupported tool $TOOL"
diff --git a/src/backends/webdav/webdav.am b/src/backends/webdav/webdav.am
index 2cf392e9..10b2075b 100644
--- a/src/backends/webdav/webdav.am
+++ b/src/backends/webdav/webdav.am
@@ -18,7 +18,7 @@ CLEANFILES += src/backends/webdav/syncevo-webdav-lookup
src/backends/webdav/syncevo-webdav-lookup: $(srcdir)/src/backends/webdav/syncevo-webdav-lookup.sh
$(AM_V_GEN)rm -f $@ ; \
- ln -s $< $@
+ cd src/backends/webdav && ln -s $(notdir $<) $(notdir $@)
src_backends_webdav_src = \
src/backends/webdav/CalDAVSource.h \
diff --git a/src/syncevo/CurlTransportAgent.cpp b/src/syncevo/CurlTransportAgent.cpp
index 8d940b3b..01d92c76 100644
--- a/src/syncevo/CurlTransportAgent.cpp
+++ b/src/syncevo/CurlTransportAgent.cpp
@@ -39,6 +39,9 @@ CurlTransportAgent::CurlTransportAgent() :
m_replyLen(0),
m_replySize(0)
{
+#ifdef ENABLE_MAEMO /* hack because Maemo doesn't support IPv6 yet */
+ curl_easy_setopt(m_easyHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
+#endif
/*
* set up for post where message is pushed into curl via
* its read callback and reply is stored in write callback
diff --git a/src/syncevo/LocalTransportAgent.cpp b/src/syncevo/LocalTransportAgent.cpp
index 3232d0bd..f9ad91f7 100644
--- a/src/syncevo/LocalTransportAgent.cpp
+++ b/src/syncevo/LocalTransportAgent.cpp
@@ -873,7 +873,7 @@ public:
// for a password. However, that does not cover failures
// like the parent not asking us to sync in the first place
// and also does not work with libdbus (https://bugs.freedesktop.org/show_bug.cgi?id=49728).
- m_forkexec->m_onQuit.connect(onParentQuit);
+ m_forkexec->m_onQuit.connect(&onParentQuit);
m_forkexec->connect();
}
diff --git a/src/syncevo/SyncContext.cpp b/src/syncevo/SyncContext.cpp
index c0092a86..67e2239a 100644
--- a/src/syncevo/SyncContext.cpp
+++ b/src/syncevo/SyncContext.cpp
@@ -2815,6 +2815,9 @@ void SyncContext::initEngine(bool logXML)
}
}
+// This is just the declaration. The actual function pointer instance
+// is inside libsynthesis, which, for historic purposes, doesn't define
+// it in its header files (yet).
extern "C" int (*SySync_ConsolePrintf)(FILE *stream, const char *format, ...);
static int nopPrintf(FILE *stream, const char *format, ...) { return 0; }
diff --git a/src/syncevo/eds_abi_wrapper.h b/src/syncevo/eds_abi_wrapper.h
index 2750a57c..186fab29 100644
--- a/src/syncevo/eds_abi_wrapper.h
+++ b/src/syncevo/eds_abi_wrapper.h
@@ -55,7 +55,9 @@
#if defined(USE_EDS_CLIENT)
#include <libedataserver/libedataserver.h>
#else
+#ifdef HAVE_LIBEDATASERVER_EDS_VERSION_H
#include <libedataserver/eds-version.h>
+#endif
#include <libedataserver/e-source.h>
#include <libedataserver/e-source-list.h>
#endif
diff --git a/test/ClientTest.cpp b/test/ClientTest.cpp
index b9bdca72..e504f2aa 100644
--- a/test/ClientTest.cpp
+++ b/test/ClientTest.cpp
@@ -1758,6 +1758,24 @@ void LocalTests::testLinkedItemsParentChild() {
CT_ASSERT_MESSAGE(exdate + " not found in:\n" + parentDataEngine, pos != parentDataEngine.npos);
}
+ if (config.m_supportsReccurenceEXDates) {
+ TestingSyncSourcePtr source;
+ SOURCE_ASSERT_NO_FAILURE(source.get(), source.reset(createSourceA()));
+ CLIENT_TEST_LOG("retrieve parent as reported to the Synthesis engine, check for X-SYNCEVOLUTION-EXDATE-DETACHED");
+ std::string parentDataEngine;
+ CT_ASSERT_NO_THROW(source->readItem(parent, parentDataEngine));
+ size_t pos = childData.find("RECURRENCE-ID");
+ CT_ASSERT(pos != childData.npos);
+ size_t end = childData.find_first_of("\r\n", pos);
+ CT_ASSERT(end != childData.npos);
+ std::string exdate = childData.substr(pos, end - pos);
+ boost::replace_first(exdate, "RECURRENCE-ID", "X-SYNCEVOLUTION-EXDATE-DETACHED");
+ // not generated because not needed by Synthesis engine
+ boost::replace_first(exdate, ";VALUE=DATE", "");
+ pos = parentDataEngine.find(exdate);
+ CT_ASSERT_MESSAGE(exdate + " not found in:\n" + parentDataEngine, pos != parentDataEngine.npos);
+ }
+
if (getenv("CLIENT_TEST_LINKED_ITEMS_NO_DELETE")) {
return;
}