2007-04-15 15:42:42 +02:00
|
|
|
/*
|
2008-08-26 19:45:28 +02:00
|
|
|
* Copyright (C) 2005-2008 Patrick Ohly
|
2007-04-15 15:42:42 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#ifdef ENABLE_ECAL
|
|
|
|
|
|
|
|
#include "EvolutionMemoSource.h"
|
|
|
|
#include "EvolutionSmartPtr.h"
|
|
|
|
|
|
|
|
#include <common/base/Log.h>
|
|
|
|
|
2008-04-07 19:59:17 +02:00
|
|
|
SyncItem *EvolutionMemoSource::createItem(const string &luid)
|
2007-04-15 15:42:42 +02:00
|
|
|
{
|
2008-04-07 19:59:17 +02:00
|
|
|
logItem( luid, "extracting from EV" );
|
|
|
|
|
2008-08-16 09:34:17 +02:00
|
|
|
ItemID id(luid);
|
2008-04-07 19:59:17 +02:00
|
|
|
eptr<icalcomponent> comp(retrieveItem(id));
|
|
|
|
auto_ptr<SyncItem> item(new SyncItem(luid.c_str()));
|
2007-04-15 15:42:42 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2008-06-25 21:54:55 +02:00
|
|
|
icalproperty *summaryprop = icalcomponent_get_first_property(journal, ICAL_SUMMARY_PROPERTY);
|
|
|
|
string summary;
|
|
|
|
if (summaryprop) {
|
|
|
|
const char *summaryptr = icalproperty_get_summary(summaryprop);
|
|
|
|
if (summaryptr) {
|
|
|
|
summary = summaryptr;
|
|
|
|
}
|
|
|
|
}
|
2007-04-15 15:42:42 +02:00
|
|
|
icalproperty *desc = icalcomponent_get_first_property(journal, ICAL_DESCRIPTION_PROPERTY);
|
|
|
|
if (desc) {
|
|
|
|
const char *text = icalproperty_get_description(desc);
|
|
|
|
if (text) {
|
2008-06-25 21:54:55 +02:00
|
|
|
size_t len = strlen(text);
|
|
|
|
bool insertSummary = false;
|
|
|
|
const char *eol;
|
|
|
|
|
|
|
|
// Check the first line: if it is the same as the summary,
|
|
|
|
// then ignore the summary. Otherwise include the summary
|
|
|
|
// as first line in the text body. At a receiving Evolution
|
|
|
|
// the summary will remain part of the text for compatibility
|
|
|
|
// with other clients which might use the first line as part
|
|
|
|
// of the normal text.
|
|
|
|
eol = strchr(text, '\n');
|
|
|
|
if (!eol) {
|
|
|
|
eol = text + len;
|
|
|
|
}
|
|
|
|
if (summary.size() &&
|
|
|
|
summary.compare(0, summary.size(), text, eol - text)) {
|
|
|
|
insertSummary = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Replace all \n with \r\n: in the worst case the text
|
|
|
|
// becomes twice as long. Also make room for summary.
|
|
|
|
eptr<char> dostext((char *)malloc(len * 2 + 1 +
|
|
|
|
(insertSummary ? summary.size() + 2 : 0)));
|
2007-12-09 17:16:48 +01:00
|
|
|
const char *from = text;
|
|
|
|
char *to = dostext;
|
2008-06-25 21:54:55 +02:00
|
|
|
if (insertSummary) {
|
|
|
|
memcpy(to, summary.c_str(), summary.size());
|
|
|
|
memcpy(to + summary.size(), "\r\n", 2);
|
|
|
|
to += summary.size() + 2;
|
|
|
|
}
|
|
|
|
eol = strchr(from, '\n');
|
2007-12-09 17:16:48 +01:00
|
|
|
while (eol) {
|
|
|
|
size_t linelen = eol - from;
|
|
|
|
memcpy(to, from, linelen);
|
|
|
|
to += linelen;
|
|
|
|
from += linelen;
|
|
|
|
to[0] = '\r';
|
|
|
|
to[1] = '\n';
|
|
|
|
to += 2;
|
|
|
|
from++;
|
|
|
|
|
|
|
|
eol = strchr(from, '\n');
|
|
|
|
}
|
|
|
|
memcpy(to, from, strlen(from) + 1);
|
|
|
|
item->setData(dostext, strlen(dostext));
|
2007-04-15 15:42:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
item->setDataType("text/plain");
|
|
|
|
item->setModificationTime(0);
|
|
|
|
|
|
|
|
return item.release();
|
|
|
|
}
|
|
|
|
|
2008-04-07 20:38:25 +02:00
|
|
|
EvolutionCalendarSource::InsertItemResult EvolutionMemoSource::insertItem(const string &luid, const SyncItem &item)
|
2007-04-15 15:42:42 +02:00
|
|
|
{
|
|
|
|
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")) {
|
2008-04-07 20:38:25 +02:00
|
|
|
return EvolutionCalendarSource::insertItem(luid, item);
|
2007-04-15 15:42:42 +02:00
|
|
|
}
|
|
|
|
|
2008-04-07 19:59:17 +02:00
|
|
|
bool update = !luid.empty();
|
2008-04-07 20:38:25 +02:00
|
|
|
bool merged = false;
|
|
|
|
string newluid = luid;
|
2008-04-07 19:59:17 +02:00
|
|
|
string modTime;
|
|
|
|
|
2007-04-15 15:42:42 +02:00
|
|
|
eptr<char> text;
|
|
|
|
text.set((char *)malloc(item.getDataSize() + 1), "copy of item");
|
|
|
|
memcpy(text, item.getData(), item.getDataSize());
|
|
|
|
text[item.getDataSize()] = 0;
|
|
|
|
|
2007-12-09 17:16:48 +01:00
|
|
|
// replace all \r\n with \n
|
|
|
|
char *from = text, *to = text;
|
|
|
|
const char *eol = strstr(from, "\r\n");
|
|
|
|
while (eol) {
|
|
|
|
size_t linelen = eol - from;
|
|
|
|
if (to != from) {
|
|
|
|
memmove(to, from, linelen);
|
|
|
|
}
|
|
|
|
to += linelen;
|
|
|
|
from += linelen;
|
|
|
|
*to = '\n';
|
|
|
|
to++;
|
|
|
|
from += 2;
|
|
|
|
|
|
|
|
eol = strstr(from, "\r\n");
|
|
|
|
}
|
|
|
|
if (to != from) {
|
|
|
|
memmove(to, from, strlen(from) + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
eol = strchr(text, '\n');
|
2007-04-15 15:42:42 +02:00
|
|
|
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 ) {
|
2008-08-09 12:26:52 +02:00
|
|
|
throwError(string("failure creating vjournal " ) + summary);
|
2007-04-15 15:42:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
GError *gerror = NULL;
|
|
|
|
char *uid = NULL;
|
|
|
|
|
|
|
|
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");
|
2008-04-07 19:59:17 +02:00
|
|
|
merged = true;
|
2007-04-15 15:42:42 +02:00
|
|
|
g_clear_error(&gerror);
|
|
|
|
} else {
|
|
|
|
throwError( "storing new memo item", gerror );
|
|
|
|
}
|
|
|
|
} else {
|
2008-04-07 19:59:17 +02:00
|
|
|
ItemID id(uid, "");
|
2008-04-07 20:38:25 +02:00
|
|
|
newluid = id.getLUID();
|
2008-04-07 19:59:17 +02:00
|
|
|
modTime = getItemModTime(id);
|
2007-04-15 15:42:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-07 19:59:17 +02:00
|
|
|
if (update || merged) {
|
2008-08-16 09:34:17 +02:00
|
|
|
ItemID id(newluid);
|
2008-04-10 20:49:45 +02:00
|
|
|
|
2007-04-15 15:42:42 +02:00
|
|
|
// ensure that the component has the right UID
|
2008-04-10 20:49:45 +02:00
|
|
|
if (update && !id.m_uid.empty()) {
|
|
|
|
icalcomponent_set_uid(subcomp, id.m_uid.c_str());
|
2007-04-15 15:42:42 +02:00
|
|
|
}
|
2008-04-10 20:49:45 +02:00
|
|
|
|
2007-04-15 15:42:42 +02:00
|
|
|
if (!e_cal_modify_object(m_calendar, subcomp, CALOBJ_MOD_ALL, &gerror)) {
|
|
|
|
throwError(string("updating memo item ") + item.getKey(), gerror);
|
|
|
|
}
|
2008-04-10 20:49:45 +02:00
|
|
|
ItemID newid = getItemID(subcomp);
|
|
|
|
newluid = newid.getLUID();
|
|
|
|
modTime = getItemModTime(newid);
|
2007-04-15 15:42:42 +02:00
|
|
|
}
|
|
|
|
|
2008-04-07 20:38:25 +02:00
|
|
|
return InsertItemResult(newluid, modTime, merged);
|
2007-04-15 15:42:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* ENABLE_ECAL */
|