On Tue, 2011-11-01 at 13:43 +0100, Patrick Ohly wrote:
> > But I guess this won't resolve the "new CalDAV item does not have
> right
> > RECURRENCE-ID" fatal error. Hmm...
> 
> Indeed, that is a different problem. I'm working on a patch.

I got carried away a bit ;-) After writing tests for this particular
problem I was convinced enough that the code works that I already merged
it into the master branch.

See the attached patches.

-- 
Best Regards, Patrick Ohly

The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.

>From bee26ca9f9464c7b83dc9729ae57f1c38aa4235f Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
Date: Wed, 2 Nov 2011 11:57:22 +0100
Subject: [PATCH 1/3] Smart Pointer: added eptr support for icalproperty and icalparameter

Needed for code which creates icalproperty or icalparameter and does
not immediately add it to a parent.
---
 src/syncevo/SmartPtr.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/src/syncevo/SmartPtr.h b/src/syncevo/SmartPtr.h
index c1594b2..59baa83 100644
--- a/src/syncevo/SmartPtr.h
+++ b/src/syncevo/SmartPtr.h
@@ -73,6 +73,8 @@ class Unref {
 #endif // HAVE_GLIB
 #ifdef ENABLE_ICAL
     static void unref(icalcomponent *pointer) { icalcomponent_free(pointer); }
+    static void unref(icalproperty *pointer) { icalproperty_free(pointer); }
+    static void unref(icalparameter *pointer) { icalparameter_free(pointer); }
     static void unref(icaltimezone *pointer) { icaltimezone_free(pointer, 1); }
 #endif // ENABLE_ICAL
 };
-- 
1.7.2.5

>From a2add05a345b80280b86c44e33ebc3542bcf3efe Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
Date: Wed, 2 Nov 2011 14:02:11 +0100
Subject: [PATCH 2/3] EDS compatibility: added icalparameter_new_clone + icalproperty_new_recurrenceid

Needed for re-adding RECURRENCE-ID when missing.
---
 src/syncevo/eds_abi_wrapper.cpp |    2 ++
 src/syncevo/eds_abi_wrapper.h   |    4 ++++
 2 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/src/syncevo/eds_abi_wrapper.cpp b/src/syncevo/eds_abi_wrapper.cpp
index 9d06130..ac1ca33 100644
--- a/src/syncevo/eds_abi_wrapper.cpp
+++ b/src/syncevo/eds_abi_wrapper.cpp
@@ -282,6 +282,7 @@ extern "C" void EDSAbiWrapperInit()
                 &EDSAbiWrapperSingleton.icalparameter_get_tzid, "icalparameter_get_tzid",
                 &EDSAbiWrapperSingleton.icalparameter_set_tzid, "icalparameter_set_tzid",
                 &EDSAbiWrapperSingleton.icalparameter_new_from_value_string, "icalparameter_new_from_value_string",
+                &EDSAbiWrapperSingleton.icalparameter_new_clone, "icalparameter_new_clone",
                 &EDSAbiWrapperSingleton.icalproperty_new_clone, "icalproperty_new_clone",
                 &EDSAbiWrapperSingleton.icalproperty_free, "icalproperty_free",
                 &EDSAbiWrapperSingleton.icalproperty_get_description, "icalproperty_get_description",
@@ -299,6 +300,7 @@ extern "C" void EDSAbiWrapperInit()
                 &EDSAbiWrapperSingleton.icalproperty_new_summary, "icalproperty_new_summary",
                 &EDSAbiWrapperSingleton.icalproperty_new_uid, "icalproperty_new_uid",
                 &EDSAbiWrapperSingleton.icalproperty_new_sequence, "icalproperty_new_sequence",
+                &EDSAbiWrapperSingleton.icalproperty_new_recurrenceid, "icalproperty_new_recurrenceid",
                 &EDSAbiWrapperSingleton.icalproperty_set_value_from_string, "icalproperty_set_value_from_string",
                 &EDSAbiWrapperSingleton.icalproperty_set_dtstamp, "icalproperty_set_dtstamp",
                 &EDSAbiWrapperSingleton.icalproperty_set_lastmodified, "icalproperty_set_lastmodified",
diff --git a/src/syncevo/eds_abi_wrapper.h b/src/syncevo/eds_abi_wrapper.h
index de534e2..abb98f3 100644
--- a/src/syncevo/eds_abi_wrapper.h
+++ b/src/syncevo/eds_abi_wrapper.h
@@ -180,6 +180,7 @@ struct EDSAbiWrapper {
     const char* (*icalparameter_get_tzid) (const icalparameter* value);
     void (*icalparameter_set_tzid) (icalparameter* value, const char* v);
     icalparameter *(*icalparameter_new_from_value_string)(icalparameter_kind kind, const char *value);
+    icalparameter *(*icalparameter_new_clone)(icalparameter *param);
     icalproperty *(*icalproperty_new_clone)(icalproperty *prop);
     void (*icalproperty_free)(icalproperty *prop);
     const char* (*icalproperty_get_description) (const icalproperty* prop);
@@ -197,6 +198,7 @@ struct EDSAbiWrapper {
     icalproperty* (*icalproperty_new_summary) (const char* v);
     icalproperty* (*icalproperty_new_sequence) (int v);
     icalproperty* (*icalproperty_new_uid) (const char* v);
+    icalproperty* (*icalproperty_new_recurrenceid) (icaltimetype v);
     void (*icalproperty_set_value_from_string) (icalproperty* prop,const char* value, const char* kind);
     void (*icalproperty_set_dtstamp) (icalproperty* prop, struct icaltimetype v);
     void (*icalproperty_set_lastmodified) (icalproperty* prop, struct icaltimetype v);
@@ -347,6 +349,7 @@ extern struct EDSAbiWrapper EDSAbiWrapperSingleton;
 #   define icalparameter_get_tzid EDSAbiWrapperSingleton.icalparameter_get_tzid
 #   define icalparameter_set_tzid EDSAbiWrapperSingleton.icalparameter_set_tzid
 #   define icalparameter_new_from_value_string EDSAbiWrapperSingleton.icalparameter_new_from_value_string
+#   define icalparameter_new_clone EDSAbiWrapperSingleton.icalparameter_new_clone
 #   define icalproperty_new_clone EDSAbiWrapperSingleton.icalproperty_new_clone
 #   define icalproperty_free EDSAbiWrapperSingleton.icalproperty_free
 #   define icalproperty_get_description EDSAbiWrapperSingleton.icalproperty_get_description
@@ -364,6 +367,7 @@ extern struct EDSAbiWrapper EDSAbiWrapperSingleton;
 #   define icalproperty_new_summary EDSAbiWrapperSingleton.icalproperty_new_summary
 #   define icalproperty_new_uid EDSAbiWrapperSingleton.icalproperty_new_uid
 #   define icalproperty_new_sequence EDSAbiWrapperSingleton.icalproperty_new_sequence
+#   define icalproperty_new_recurrenceid EDSAbiWrapperSingleton.icalproperty_new_recurrenceid
 #   define icalproperty_set_value_from_string EDSAbiWrapperSingleton.icalproperty_set_value_from_string
 #   define icalproperty_set_dtstamp EDSAbiWrapperSingleton.icalproperty_set_dtstamp
 #   define icalproperty_set_lastmodified EDSAbiWrapperSingleton.icalproperty_set_lastmodified
-- 
1.7.2.5

>From 03d3c720bab43323addb1c7c70ad033b8204833e Mon Sep 17 00:00:00 2001
From: Patrick Ohly <[email protected]>
Date: Wed, 2 Nov 2011 12:02:04 +0100
Subject: [PATCH 3/3] CalDAV: add RECURRENCE-ID in update

When storing an updated detached recurrence, the VEVENT was expected
to contain a RECURRENCE-ID. This might not be the case when the peer
in a local sync (typically the local storage) was unable to store that
property.

Support such a local storage by re-adding the RECURRENCE-ID based on
the available information:
- RECURRENCE-ID value from sub ID
- TZID from parent event's DTSTART (if parent exists) or
  current event's DTSTART (otherwise)

Tests for different scenarios (all-day event with date-only RECURRENCE-ID,
with TZID, without TZID) will be committed separately.
---
 src/backends/webdav/CalDAVSource.cpp |   49 ++++++++++++++++++++++++++++++++-
 1 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/src/backends/webdav/CalDAVSource.cpp b/src/backends/webdav/CalDAVSource.cpp
index cfb25c5..aab2a82 100644
--- a/src/backends/webdav/CalDAVSource.cpp
+++ b/src/backends/webdav/CalDAVSource.cpp
@@ -498,10 +498,55 @@ SubSyncSource::SubItemResult CalDAVSource::insertSubItem(const std::string &luid
             }
         }
     } else {
-        if (subid != knownSubID) {
-            SE_THROW("new CalDAV item does not have right RECURRENCE-ID");
+        if (!subid.empty() && subid != knownSubID) {
+            SE_THROW(StringPrintf("new CalDAV item does not have right RECURRENCE-ID: item %s != expected %s",
+                                  subid.c_str(), knownSubID.c_str()));
         }
         Event &event = loadItem(davLUID);
+
+        if (subid.empty() && subid != knownSubID) {
+            // fix incomplete iCalendar 2.0 item: should have had a RECURRENCE-ID
+            icalcomponent *newcomp =
+                icalcomponent_get_first_component(newEvent->m_calendar, ICAL_VEVENT_COMPONENT);
+            icalproperty *prop = icalcomponent_get_first_property(newcomp, ICAL_RECURRENCEID_PROPERTY);
+            if (prop) {
+                icalcomponent_remove_property(newcomp, prop);
+                icalproperty_free(prop);
+            }
+
+            // reconstruct RECURRENCE-ID with known value and TZID from start time of
+            // the parent event or (if not found) the current event
+            eptr<icalproperty> rid(icalproperty_new_recurrenceid(icaltime_from_string(knownSubID.c_str())),
+                                   "new rid");
+            icalproperty *dtstart = NULL;
+            icalcomponent *comp;
+            // look for parent first
+            for (comp = icalcomponent_get_first_component(event.m_calendar, ICAL_VEVENT_COMPONENT);
+                 comp && !dtstart;
+                 comp = icalcomponent_get_next_component(event.m_calendar, ICAL_VEVENT_COMPONENT)) {
+                if (!icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY)) {
+                    dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY);
+                }
+            }
+            // fall back to current event
+            if (!dtstart) {
+                dtstart = icalcomponent_get_first_property(newcomp, ICAL_DTSTART_PROPERTY);
+            }
+            // ignore missing TZID
+            if (dtstart) {
+                icalparameter *tzid = icalproperty_get_first_parameter(dtstart, ICAL_TZID_PARAMETER);
+                if (tzid) {
+                    icalproperty_set_parameter(rid, icalparameter_new_clone(tzid));
+                }
+            }
+
+            // finally add RECURRENCE-ID and fix newEvent's meta information
+            icalcomponent_add_property(newcomp, rid.release());
+            subid = knownSubID;
+            newEvent->m_subids.erase("");
+            newEvent->m_subids.insert(subid);
+        }
+
         // no changes expected yet, copy previous attributes
         subres.m_mainid = davLUID;
         subres.m_uid = event.m_UID;
-- 
1.7.2.5

_______________________________________________
SyncEvolution mailing list
[email protected]
http://lists.syncevolution.org/listinfo/syncevolution

Reply via email to