From eb4d68df8d06f734e79e13ea05f7755aa5b0a5f3 Mon Sep 17 00:00:00 2001 From: Nicolas VIVIEN Date: Wed, 26 May 2010 19:18:09 +0200 Subject: [PATCH] Fix multi-calendar using & sync MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit With the new devices, we can have several calendar database. We have one calendar per mails account. If I sync calendar, it's OK the first time : 1°/ a) Evolution : add a new event b) BlackBerry : empty (event isn't still knonw) 2°/ run sync 3°/ a) Evolution : event (no changement) b) BlackBerry : new event is added in the default calendar (OK) 4°/ a) Evolution : edit the event b) BlackBerry : no modification 5°/ run sync 6°/ a) Evolution : event (no changement) b) BlackBerry : event is synced, but we loose the calendar link ! 6°/ b) => KO. Other test case : 1°/ a) Evolution : empty (event isn't still known) b) BlackBerry : add a new event associated to a mails account 2°/ run sync 3°/ a) Evolution : new event is added in the default calendar (OK) b) BlackBerry : event (no changement) 4°/ a) Evolution : edit the event b) BlackBerry : no modification 5°/ run sync 6°/ a) Evolution : event (no changement) b) BlackBerry : event is synced, but we loose the calendar link ! To illustrate it : + Create calendar entry on the BlackBerry : Calendar entry: 0x5b17e358 (5) All Day Event: no Class: Public Free/Busy: Busy Subject: Test Location: Home Notification Time: Sat May 29 09:45:00 2010 Start Time: Sat May 29 10:00:00 2010 End Time: Sat May 29 11:00:00 2010 Recurring: no Unknowns: Type: 0x2a Data: 00000000: 36 35 36 33 39 36 34 39 34 31 39 35 30 37 37 32 6563964941950772 00000010: 30 35 35 00 055. Type: 0x2b Data: 00000000: 64 71 2d 92 ec f0 93 bf dq-..... <== seems to the calendar link Type: 0x2c Data: 00000000: ff ff ff ff ff ff ff ff ........ Type: 0x12 Data: 00000000: 00 00 00 00 .... Type: 0x1b Data: 00000000: 0c 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 ................ + Sync after Evolution editing : Calendar entry: 0x5b17e358 (5) All Day Event: no Class: Public Free/Busy: Free Subject: Test modif Location: Home Notification Time: Sat May 29 09:45:00 2010 Start Time: Sat May 29 10:00:00 2010 End Time: Sat May 29 11:00:00 2010 Recurring: no Unknowns: Type: 0x2a Data: 00000000: 36 35 36 33 39 36 34 39 35 39 31 33 30 36 34 31 6563964959130641 00000010: 32 34 33 00 243. Type: 0x2b Data: 00000000: ff ff ff ff ff ff ff ff ........ <== information lost ! Type: 0x2c Data: 00000000: ff ff ff ff ff ff ff ff ........ Type: 0x12 Data: 00000000: 00 00 00 00 .... Type: 0x1b Data: 00000000: 0c 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................ So, fix create a new CalendarID field "0x2b", by default is set to '-1' and not used. If we detect that this field exists and is different to '-1', we use this field (permit to compliant with old devices) --- opensync-plugin-0.4x/src/vevent.cc | 29 ++++++++++++++++++++++++++++- opensync-plugin-0.4x/src/vevent.h | 5 +++++ src/r_calendar.cc | 18 ++++++++++++++++++ src/r_calendar.h | 1 + 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/opensync-plugin-0.4x/src/vevent.cc b/opensync-plugin-0.4x/src/vevent.cc index 919e0fb9..811e8ade 100644 --- a/opensync-plugin-0.4x/src/vevent.cc +++ b/opensync-plugin-0.4x/src/vevent.cc @@ -722,6 +722,16 @@ bool VEventConverter::ParseData(const char *data) return true; } +bool VEventConverter::MergeData(const Barry::Calendar &origin) +{ + // Save CalendarID value + // CalendarID field is used to link an entry event to an account mail + if (origin.CalendarID != m_Cal.CalendarID) + m_Cal.CalendarID = origin.CalendarID; + + return true; +} + // Barry storage operator void VEventConverter::operator()(const Barry::Calendar &rec) { @@ -733,8 +743,10 @@ void VEventConverter::operator()(const Barry::Calendar &rec) m_Data = 0; } - try { + // Keep a trace of Calendar object (need to merge with the new event) + m_Cal = rec; + try { vCalendar vcal; vcal.ToVCal(rec); m_Data = vcal.ExtractVCal(); @@ -805,6 +817,21 @@ bool VEventConverter::CommitRecordData(BarryEnvironment *env, unsigned int dbId, return false; } + // If we modify a data, we read at first its current value + // then we merge with the parsed value from the other opensync member + // Merge function is important because, we have to save some BlackBerry fields. + // Fix an issue with the new OS release who supports several calendar. + if( !add ) { + using namespace Barry; + + VEventConverter cal2event; + RecordParser parser(cal2event); + env->m_pDesktop->GetRecord(dbId, StateIndex, parser); + Calendar cal = cal2event.GetCalendar(); + + convert.MergeData(cal); + } + Barry::RecordBuilder builder(convert); if( add ) { diff --git a/opensync-plugin-0.4x/src/vevent.h b/opensync-plugin-0.4x/src/vevent.h index f024d6be..1e54a4e9 100644 --- a/opensync-plugin-0.4x/src/vevent.h +++ b/opensync-plugin-0.4x/src/vevent.h @@ -88,9 +88,14 @@ public: // Transfers ownership of m_Data to the caller char* ExtractData(); + const Barry::Calendar& GetCalendar() const { return m_Cal; }; + // Parses vevent data bool ParseData(const char *data); + // Merge vevent data + bool MergeData(const Barry::Calendar &origin); + // Barry storage operator void operator()(const Barry::Calendar &rec); diff --git a/src/r_calendar.cc b/src/r_calendar.cc index 4c365f28..8f5e3555 100644 --- a/src/r_calendar.cc +++ b/src/r_calendar.cc @@ -95,6 +95,7 @@ uint8_t Calendar::ClassFlagRec2Proto(ClassFlagType f) #define CALFC_FREEBUSY_FLAG 0x1c #define CALFC_TIMEZONE_CODE 0x1e // only seems to show up if recurring #define CALFC_CLASS_FLAG 0x28 // private flag from outlook +#define CALFC_CALENDAR_ID 0x2b // Calendar using (new devices have several calendar) #define CALFC_ALLDAYEVENT_FLAG 0xff #define CALFC_END 0xffff @@ -112,6 +113,7 @@ static FieldLink CalendarFieldLinks[] = { }; Calendar::Calendar() + : CalendarID(-1) { Clear(); } @@ -231,6 +233,15 @@ const unsigned char* Calendar::ParseField(const unsigned char *begin, FreeBusyFlag = FreeBusyFlagProto2Rec(field->u.raw[0]); return begin; + case CALFC_CALENDAR_ID: + if( btohs(field->size) == 8 ) { + CalendarID = btohll(field->u.uint64); + } + else { + throw Error("Calendar::ParseField: size data unknown in calendar field"); + } + return begin; + case CALFC_CLASS_FLAG: if( field->u.raw[0] > CR_CLASS_RANGE_HIGH ) { throw Error("Calendar::ParseField: ClassFlag out of range" ); @@ -348,6 +359,11 @@ void Calendar::BuildFields(Data &data, size_t &offset, const IConverter *ic) con BuildField(data, offset, CALFC_FREEBUSY_FLAG, FreeBusyFlagRec2Proto(FreeBusyFlag)); BuildField(data, offset, CALFC_CLASS_FLAG, ClassFlagRec2Proto(ClassFlag)); + // If CalendarID is defined and most of supported ! + // (by default 0xffff ffff ffff ffff) + if( CalendarID != (uint64_t) -1 ) + BuildField(data, offset, CALFC_CALENDAR_ID, CalendarID); + // and finally save unknowns UnknownsType::const_iterator ub = Unknowns.begin(), ue = Unknowns.end(); @@ -365,6 +381,7 @@ void Calendar::Clear() RecType = Calendar::GetDefaultRecType(); AllDayEvent = false; + CalendarID = btohll((uint64_t) -1); Subject.clear(); Notes.clear(); Location.clear(); @@ -390,6 +407,7 @@ void Calendar::Dump(std::ostream &os) const os << "Calendar entry: 0x" << setbase(16) << RecordId << " (" << (unsigned int)RecType << ")\n"; + os << " Calendar ID: 0x" << setbase(16) << CalendarID << "\n"; os << " All Day Event: " << (AllDayEvent ? "yes" : "no") << "\n"; os << " Class: " << ClassTypes[ClassFlag] << "\n"; os << " Free/Busy: " << FreeBusy[FreeBusyFlag] << "\n"; diff --git a/src/r_calendar.h b/src/r_calendar.h index 6d6cb863..bdbd8cf2 100644 --- a/src/r_calendar.h +++ b/src/r_calendar.h @@ -99,6 +99,7 @@ public: ClassFlagType ClassFlag; + uint64_t CalendarID; // Calendar ID (usefull if devices have several calendars) unsigned short TimeZoneCode; // the time zone originally used // for the recurrence data... -- 2.11.4.GIT