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:
parent
5cbc7c0e6d
commit
36f2140ce2
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
|
@ -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") {
|
||||
|
|
|
@ -45,7 +45,9 @@ CORE_SOURCES = \
|
|||
|
||||
SYNCECAL_SOURCES = \
|
||||
EvolutionCalendarSource.h \
|
||||
EvolutionCalendarSource.cpp
|
||||
EvolutionMemoSource.h \
|
||||
EvolutionCalendarSource.cpp \
|
||||
EvolutionMemoSource.cpp
|
||||
|
||||
SYNCEBOOK_SOURCES = \
|
||||
EvolutionContactSource.h \
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue