added synchronization of Memos as plain text

git-svn-id: https://zeitsenke.de/svn/SyncEvolution/trunk@360 15ad00c4-1369-45f4-8270-35d70d36bdcd
This commit is contained in:
Patrick Ohly 2007-04-15 13:42:42 +00:00
parent 5cbc7c0e6d
commit 36f2140ce2
9 changed files with 307 additions and 9 deletions

View File

@ -74,7 +74,7 @@ funambol_2/spds/sources/todo_2/config.txt : funambol_1/spds/sources/addressbook_
funambol_2/spds/sources/memo_2/config.txt : funambol_1/spds/sources/addressbook_1/config.txt
mkdir -p $(@D)
sed -e s/addressbook_1/memo_2/ -e s/#1/#2/ -e 's:type = text/x-vcard:type = text/x-journal:' -e 's/uri = card/uri = note/' -e 's/sync = two-way/sync = none/' $< >$@
sed -e s/addressbook_1/memo_2/ -e s/#1/#2/ -e 's:type = text/x-vcard:type = text/plain:' -e 's/uri = card/uri = note/' -e 's/sync = two-way/sync = none/' $< >$@
funambol_1/spds/sources/calendar_1/config.txt : funambol_1/spds/sources/addressbook_1/config.txt
mkdir -p $(@D)
@ -86,7 +86,7 @@ funambol_1/spds/sources/todo_1/config.txt : funambol_1/spds/sources/addressbook_
funambol_1/spds/sources/memo_1/config.txt : funambol_1/spds/sources/addressbook_1/config.txt
mkdir -p $(@D)
sed -e s/addressbook_1/memo_1/ -e 's:type = text/x-vcard:type = text/x-journal:' -e 's/uri = card/uri = note/' -e 's/sync = two-way/sync = none/' $< >$@
sed -e s/addressbook_1/memo_1/ -e 's:type = text/x-vcard:type = text/plain:' -e 's/uri = card/uri = note/' -e 's/sync = two-way/sync = none/' $< >$@
# www.scheduleworld.com configuration:

View File

@ -19,7 +19,10 @@ syncModes = slow,two-way,refresh-from-client,refresh-from-server
#
# text/calendar = Evolution calender data (in iCalendar 2.0 format)
# text/x-todo = Evolution task data (iCalendar 2.0)
# text/x-journal = Evolution memos (iCalendar 2.0)
# text/x-journal = Evolution memos (iCalendar 2.0) - not supported by any
# known SyncML server and not actively tested
# text/plain = Evolution memos in plain text format, UTF-8 encoding,
# first line acts as summary
# text/x-vcard = Evolution contact data in vCard 2.1 format
# (works with most servers)
# test/vcard = Evolution contact data in vCard 3.0 (RFC 2425) format

View File

@ -25,6 +25,7 @@ using namespace std;
#ifdef ENABLE_ECAL
#include "EvolutionCalendarSource.h"
#include "EvolutionMemoSource.h"
#include "EvolutionSmartPtr.h"
#include <common/base/Log.h>
@ -501,6 +502,8 @@ extern "C" EvolutionSyncSource *SyncEvolutionCreateSource(const string &name,
return new EvolutionCalendarSource(E_CAL_SOURCE_TYPE_TODO, name, sc, changeId, id);
} else if (mimeType == "text/x-journal") {
return new EvolutionCalendarSource(E_CAL_SOURCE_TYPE_JOURNAL, name, sc, changeId, id);
} else if (mimeType == "text/plain") {
return new EvolutionMemoSource(E_CAL_SOURCE_TYPE_JOURNAL, name, sc, changeId, id);
} else if (mimeType == "text/calendar" ||
mimeType == "text/x-vcalendar") {
return new EvolutionCalendarSource(E_CAL_SOURCE_TYPE_EVENT, name, sc, changeId, id);

View File

@ -86,7 +86,7 @@ class EvolutionCalendarSource : public EvolutionSyncSource
virtual void logItem(const string &uid, const string &info, bool debug = false);
virtual void logItem(SyncItem &item, const string &info, bool debug = false);
private:
protected:
/** valid after open(): the calendar that this source references */
eptr<ECal, GObject> m_calendar;
@ -110,7 +110,7 @@ class EvolutionCalendarSource : public EvolutionSyncSource
* - then either insert or update it, trying update if insert fails because it exists already
* - also import timezones
*/
int insertItem(SyncItem &item, bool update);
virtual int insertItem(SyncItem &item, bool update);
/** returns the type which the ical library uses for our components */
icalcomponent_kind getCompType() {

146
src/EvolutionMemoSource.cpp Normal file
View File

@ -0,0 +1,146 @@
/*
* Copyright (C) 2005-2006 Patrick Ohly
* Copyright (C) 2007 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 <memory>
using namespace std;
#include "config.h"
#ifdef ENABLE_ECAL
#include "EvolutionMemoSource.h"
#include "EvolutionSmartPtr.h"
#include <common/base/Log.h>
SyncItem *EvolutionMemoSource::createItem( const string &uid, SyncState state )
{
logItem( uid, "extracting from EV" );
eptr<icalcomponent> comp(retrieveItem(uid));
auto_ptr<SyncItem> item(new SyncItem(uid.c_str()));
item->setData("", 0);
icalcomponent *cal = icalcomponent_get_first_component(comp, ICAL_VCALENDAR_COMPONENT);
if (!cal) {
cal = comp;
}
icalcomponent *journal = icalcomponent_get_first_component(cal, ICAL_VJOURNAL_COMPONENT);
if (!journal) {
journal = comp;
}
icalproperty *desc = icalcomponent_get_first_property(journal, ICAL_DESCRIPTION_PROPERTY);
if (desc) {
const char *text = icalproperty_get_description(desc);
if (text) {
item->setData(text, strlen(text));
}
}
item->setDataType("text/plain");
item->setModificationTime(0);
item->setState(state);
return item.release();
}
int EvolutionMemoSource::insertItem(SyncItem& item, bool update)
{
const char *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")) {
return EvolutionCalendarSource::insertItem(item, update);
}
bool fallback = false;
eptr<char> text;
text.set((char *)malloc(item.getDataSize() + 1), "copy of item");
memcpy(text, item.getData(), item.getDataSize());
text[item.getDataSize()] = 0;
const char *eol = strchr(text, '\n');
string summary;
if (eol) {
summary.insert(0, (char *)text, eol - (char *)text);
} else {
summary = (char *)text;
}
eptr<icalcomponent> subcomp(icalcomponent_vanew(
ICAL_VJOURNAL_COMPONENT,
icalproperty_new_summary(summary.c_str()),
icalproperty_new_description(text),
0));
if( !subcomp ) {
throwError( string( "creating vjournal " ) + summary,
NULL );
}
GError *gerror = NULL;
char *uid = NULL;
int status = STC_OK;
if (!update) {
if(!e_cal_create_object(m_calendar, subcomp, &uid, &gerror)) {
if (gerror->domain == E_CALENDAR_ERROR &&
gerror->code == E_CALENDAR_STATUS_OBJECT_ID_ALREADY_EXISTS) {
// Deal with error due to adding already existing item.
// Should never happen for plain text journal entries because
// they have no embedded ID, but who knows...
logItem(item, "exists already, updating instead");
fallback = true;
g_clear_error(&gerror);
} else {
throwError( "storing new memo item", gerror );
}
} else {
if (uid) {
item.setKey(uid);
}
}
}
if (update || fallback) {
// ensure that the component has the right UID
if (update && item.getKey() && item.getKey()[0]) {
icalcomponent_set_uid(subcomp, item.getKey());
}
if (!e_cal_modify_object(m_calendar, subcomp, CALOBJ_MOD_ALL, &gerror)) {
throwError(string("updating memo item ") + item.getKey(), gerror);
}
string uid = getCompUID(subcomp);
if (uid.size()) {
item.setKey(uid.c_str());
}
if (fallback) {
status = STC_CONFLICT_RESOLVED_WITH_MERGE;
}
}
return status;
}
#endif /* ENABLE_ECAL */

59
src/EvolutionMemoSource.h Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2005-2006 Patrick Ohly
* Copyright (C) 2007 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_EVOLUTIONMEMOSOURCE
#define INCL_EVOLUTIONMEMOSOURCE
#include <config.h>
#include "EvolutionCalendarSource.h"
#ifdef ENABLE_ECAL
/**
* Implements access to Evolution memo lists (stored as calendars),
* exporting/importing the memos in plain UTF-8 text. Only the DESCRIPTION
* part of a memo is synchronized.
*/
class EvolutionMemoSource : public EvolutionCalendarSource
{
public:
EvolutionMemoSource(ECalSourceType type,
const string &name,
SyncSourceConfig *sc,
const string &changeId,
const string &id) :
EvolutionCalendarSource(type, name, sc, changeId, id) {}
//
// implementation of EvolutionSyncSource
//
virtual SyncItem *createItem( const string &uid, SyncState state );
//
// implementation of SyncSource
//
virtual ArrayElement *clone() { return new EvolutionMemoSource(*this); }
private:
virtual int insertItem(SyncItem &item, bool update);
};
#endif // ENABLE_ECAL
#endif // INCL_EVOLUTIONMEMOSOURCE

View File

@ -22,6 +22,7 @@
#include "EvolutionSyncSource.h"
#include "EvolutionContactSource.h"
#include "EvolutionCalendarSource.h"
#include "EvolutionMemoSource.h"
#include <common/base/Log.h>
@ -228,6 +229,14 @@ EvolutionSyncSource *EvolutionSyncSource::createSource(
if (error) {
throw runtime_error(name + ": access to memos not compiled into this binary, text/x-journal not supported");
}
#endif
} else if (mimeType == "text/plain") {
#ifdef ENABLE_ECAL
return new EvolutionMemoSource(E_CAL_SOURCE_TYPE_JOURNAL, name, sc, strippedChangeId, id);
#else
if (error) {
throw runtime_error(name + ": access to memos not compiled into this binary, text/plain not supported");
}
#endif
} else if (mimeType == "text/calendar" ||
mimeType == "text/x-vcalendar") {

View File

@ -45,7 +45,9 @@ CORE_SOURCES = \
SYNCECAL_SOURCES = \
EvolutionCalendarSource.h \
EvolutionCalendarSource.cpp
EvolutionMemoSource.h \
EvolutionCalendarSource.cpp \
EvolutionMemoSource.cpp
SYNCEBOOK_SOURCES = \
EvolutionContactSource.h \

View File

@ -29,6 +29,7 @@
#include "EvolutionSyncClient.h"
#include "EvolutionCalendarSource.h"
#include "EvolutionMemoSource.h"
#include "EvolutionContactSource.h"
/** a wrapper class which automatically does an open() in the constructor and a close() in the destructor */
@ -81,7 +82,7 @@ public:
/* check sources */
const char *sourcelist = getenv("CLIENT_TEST_SOURCES");
if (!sourcelist) {
sourcelist = "vcard21,vcard30,ical20,imemo20,itodo20";
sourcelist = "vcard21,vcard30,ical20,text,itodo20";
}
numSources = 0;
for (SourceType sourceType = (SourceType)0; sourceType < TEST_MAX_SOURCE; sourceType = (SourceType)((int)sourceType + 1) ) {
@ -93,7 +94,9 @@ public:
}
#endif
#ifndef ENABLE_ECAL
if (sourceType == TEST_CALENDAR_SOURCE || sourceType == TEST_TASK_SOURCE) {
if (sourceType == TEST_CALENDAR_SOURCE ||
sourceType == TEST_TASK_SOURCE ||
sourceType == TEST_MEMO_SOURCE) {
continue;
}
#endif
@ -154,7 +157,7 @@ public:
TEST_CONTACT30_SOURCE,
TEST_CALENDAR_SOURCE,
TEST_TASK_SOURCE,
// TEST_MEMO_SOURCE,
TEST_MEMO_SOURCE,
TEST_MAX_SOURCE
};
@ -186,6 +189,49 @@ public:
getTestData("itodo20", config);
config.type = "text/x-todo"; // special type required by SyncEvolution
break;
case TEST_MEMO_SOURCE:
config.sourceName = "text";
config.uri = "note"; // ScheduleWorld
config.type = "text/plain";
config.insertItem =
"BEGIN:VCALENDAR\n"
"PRODID:-//Ximian//NONSGML Evolution Calendar//EN\n"
"VERSION:2.0\n"
"METHOD:PUBLISH\n"
"BEGIN:VJOURNAL\n"
"SUMMARY:Summary\n"
"DESCRIPTION:Summary\\nBody text\n"
"END:VJOURNAL\n"
"END:VCALENDAR\n";
config.updateItem =
"BEGIN:VCALENDAR\n"
"PRODID:-//Ximian//NONSGML Evolution Calendar//EN\n"
"VERSION:2.0\n"
"METHOD:PUBLISH\n"
"BEGIN:VJOURNAL\n"
"SUMMARY:Summary Modified\n"
"DESCRIPTION:Summary Modified\\nBody text\n"
"END:VJOURNAL\n"
"END:VCALENDAR\n";
/* change summary, as in updateItem, and the body in the other merge item */
config.mergeItem1 = config.updateItem;
config.mergeItem2 =
"BEGIN:VCALENDAR\n"
"PRODID:-//Ximian//NONSGML Evolution Calendar//EN\n"
"VERSION:2.0\n"
"METHOD:PUBLISH\n"
"BEGIN:VJOURNAL\n"
"SUMMARY:Summary\n"
"DESCRIPTION:Summary\\nBody modified\n"
"END:VJOURNAL\n"
"END:VCALENDAR\n";
config.templateItem = config.insertItem;
config.uniqueProperties = "SUMMARY:DESCRIPTION";
config.sizeProperty = "DESCRIPTION";
config.import = ClientTest::import;
config.dump = dumpMemoSource;
config.testcases = "testcases/imemo20.ics";
break;
default:
CPPUNIT_ASSERT(sourceType < TEST_MAX_SOURCE);
break;
@ -304,6 +350,9 @@ private:
case TEST_TASK_SOURCE:
return "itodo20";
break;
case TEST_MEMO_SOURCE:
return "text";
break;
default:
CPPUNIT_ASSERT(type >= 0 && type < TEST_MAX_SOURCE);
break;
@ -338,12 +387,39 @@ private:
#endif
break;
case TEST_TASK_SOURCE:
#ifdef ENABLE_ECAL
return new TestEvolutionSyncSource<EvolutionCalendarSource>(E_CAL_SOURCE_TYPE_TODO, changeID, database);
#else
return NULL;
#endif
break;
case TEST_MEMO_SOURCE:
#ifdef ENABLE_ECAL
return new TestEvolutionSyncSource<EvolutionMemoSource>(E_CAL_SOURCE_TYPE_JOURNAL, changeID, database);
#else
return NULL;
#endif
break;
default:
CPPUNIT_ASSERT(type >= 0 && type < TEST_MAX_SOURCE);
return NULL;
}
}
/**
* dump memos in iCalendar 2.0 format for synccompare: ClientTest::dump() would
* dump the plain text
*/
static int dumpMemoSource(ClientTest &client, SyncSource &source, const char *file) {
std::ofstream out(file);
#ifdef ENABLE_ECAL
((EvolutionMemoSource &)source).exportData(out);
#endif
out.close();
return out.bad();
}
};
static class RegisterTestEvolution {