Contains upstream commits: 2369060328d96211a9dbe1ebaffeff7d5140e6be Recurring events not shown on Exchange 2010 servers ec03f046acabdb440dd44e8ddbe841453adbb55c Fix a copy&paste error, found by a Coverity Scan diff -up evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-recur-utils.c.show-events-owa evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-recur-utils.c --- evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-recur-utils.c.show-events-owa 2012-10-15 10:29:54.000000000 +0200 +++ evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-recur-utils.c 2013-10-17 12:30:35.290075062 +0200 @@ -181,7 +181,7 @@ rp_to_gba(const struct ema_RecurrencePat sizeof (guint32) * rp->DeletedInstanceCount); } GBA_APPEND_LVAL(gba, rp->ModifiedInstanceCount); - if ( rp->DeletedInstanceCount ) { + if ( rp->ModifiedInstanceCount ) { GBA_APPEND (gba, rp->ModifiedInstanceDates, sizeof (guint32) * rp->ModifiedInstanceCount); } @@ -296,6 +296,10 @@ arp_to_gba(const struct ema_AppointmentR for (i = 0; i < arp->ExceptionCount; ++i) { ee_to_gba (&arp->ExtendedException[i], arp, i, gba); } + GBA_APPEND_LVAL (gba, arp->ReservedBlock2Size); + if (arp->ReservedBlock2Size) { + GBA_APPEND (gba, arp->ReservedBlock2, arp->ReservedBlock2Size); + } } static gboolean @@ -501,6 +505,13 @@ gba_to_arp(const GByteArray *gba, ptrdif } } + GBA_DEREF_OFFSET (gba, *off, arp->ReservedBlock2Size, guint32); + if (arp->ReservedBlock2Size) { + arp->ReservedBlock2 = g_new (gchar, arp->ReservedBlock2Size); + GBA_MEMCPY_OFFSET (gba, *off, arp->ReservedBlock2, + arp->ReservedBlock2Size); + } + return TRUE; } diff -up evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-tz-utils.c.show-events-owa evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-tz-utils.c --- evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-tz-utils.c.show-events-owa 2013-03-25 10:17:54.000000000 +0100 +++ evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-tz-utils.c 2013-10-17 12:30:05.858075342 +0200 @@ -374,6 +374,195 @@ e_mapi_cal_tz_util_dump (void) g_rec_mutex_unlock(&mutex); } +static void +write_icaltime_as_systemtime (GByteArray *ba, + struct icaltimetype icaltime) +{ + guint16 flag16; + + /* wYear */ + flag16 = icaltime.year; + g_byte_array_append (ba, (const guint8 *) &flag16, sizeof (guint16)); + + /* wMonth */ + flag16 = icaltime.month; + g_byte_array_append (ba, (const guint8 *) &flag16, sizeof (guint16)); + + /* wDayOfWeek */ + flag16 = icaltime.year == 0 ? 0 : icaltime_day_of_week (icaltime); + g_byte_array_append (ba, (const guint8 *) &flag16, sizeof (guint16)); + + /* wDay */ + flag16 = icaltime.day; + g_byte_array_append (ba, (const guint8 *) &flag16, sizeof (guint16)); + + /* wHour */ + flag16 = icaltime.hour; + g_byte_array_append (ba, (const guint8 *) &flag16, sizeof (guint16)); + + /* wMinute */ + flag16 = icaltime.minute; + g_byte_array_append (ba, (const guint8 *) &flag16, sizeof (guint16)); + + /* wSecond */ + flag16 = icaltime.second; + g_byte_array_append (ba, (const guint8 *) &flag16, sizeof (guint16)); + + /* wMilliseconds */ + flag16 = 0; + g_byte_array_append (ba, (const guint8 *) &flag16, sizeof (guint16)); +} + +static void +write_tz_rule (GByteArray *ba, + gboolean is_recur, + guint32 bias, + guint32 standard_bias, + guint32 daylight_bias, + struct icaltimetype standard_date, + struct icaltimetype daylight_date) +{ + guint8 flag8; + guint16 flag16; + + g_return_if_fail (ba != NULL); + + /* Major version */ + flag8 = 0x02; + g_byte_array_append (ba, (const guint8 *) &flag8, sizeof (guint8)); + + /* Minor version */ + flag8 = 0x01; + g_byte_array_append (ba, (const guint8 *) &flag8, sizeof (guint8)); + + /* Reserved */ + flag16 = 0x003e; + g_byte_array_append (ba, (const guint8 *) &flag16, sizeof (guint16)); + + /* TZRule flags */ + flag16 = 0; + if (is_recur) + flag16 |= 1; + g_byte_array_append (ba, (const guint8 *) &flag16, sizeof (guint16)); + + /* wYear */ + flag16 = standard_date.year; + g_byte_array_append (ba, (const guint8 *) &flag16, sizeof (guint16)); + + /* X - 14 times 0x00 */ + flag8 = 0x00; + for (flag16 = 0; flag16 < 14; flag16++) { + g_byte_array_append (ba, (const guint8 *) &flag8, sizeof (guint8)); + } + + /* lBias */ + g_byte_array_append (ba, (const guint8 *) &bias, sizeof (guint32)); + + /* lStandardBias */ + g_byte_array_append (ba, (const guint8 *) &standard_bias, sizeof (guint32)); + + /* lDaylightBias */ + g_byte_array_append (ba, (const guint8 *) &daylight_bias, sizeof (guint32)); + + /* stStandardDate */ + write_icaltime_as_systemtime (ba, standard_date); + + /* stDaylightDate */ + write_icaltime_as_systemtime (ba, daylight_date); +} + +static void +extract_bias_and_date (icalcomponent *comp, + guint32 *bias, + struct icaltimetype *start) +{ + icalproperty *prop; + gint tzoffset; + + g_return_if_fail (comp != NULL); + g_return_if_fail (bias != NULL); + g_return_if_fail (start != NULL); + + prop = icalcomponent_get_first_property (comp, ICAL_TZOFFSETTO_PROPERTY); + if (prop) + tzoffset = icalproperty_get_tzoffsetto (prop); + else + tzoffset = 0; + + *bias = tzoffset / 60; + *start = icalcomponent_get_dtstart (comp); +} + +static void +write_tz_rule_comps (GByteArray *ba, + gboolean is_recur, + icalcomponent *standardcomp, + icalcomponent *daylightcomp, + icaltimezone *zone) +{ + struct icaltimetype standard_date, daylight_date, current_time; + guint32 bias, standard_bias, daylight_bias; + + g_return_if_fail (ba != NULL); + g_return_if_fail (standardcomp != NULL); + g_return_if_fail (daylightcomp != NULL); + + extract_bias_and_date (standardcomp, &standard_bias, &standard_date); + extract_bias_and_date (daylightcomp, &daylight_bias, &daylight_date); + + current_time = icaltime_current_time_with_zone (zone); + bias = current_time.is_daylight ? daylight_bias : standard_bias; + + write_tz_rule (ba, is_recur, bias, standard_bias, daylight_bias, standard_date, daylight_date); +} + +static void +add_timezone_rules (GByteArray *ba, + gboolean is_recur, + icalcomponent *vtimezone, + icaltimezone *zone) +{ + gboolean any_added = FALSE; + + g_return_if_fail (ba != NULL); + + if (vtimezone) { + icalcomponent *subcomp, *standardcomp = NULL, *daylightcomp = NULL; + + for (subcomp = icalcomponent_get_first_component (vtimezone, ICAL_ANY_COMPONENT); + subcomp; + subcomp = icalcomponent_get_next_component (vtimezone, ICAL_ANY_COMPONENT)) { + if (icalcomponent_isa (subcomp) == ICAL_XSTANDARD_COMPONENT) + standardcomp = subcomp; + if (icalcomponent_isa (subcomp) == ICAL_XDAYLIGHT_COMPONENT) + daylightcomp = subcomp; + if (standardcomp && daylightcomp) { + write_tz_rule_comps (ba, is_recur, standardcomp, daylightcomp, zone); + + any_added = TRUE; + standardcomp = NULL; + daylightcomp = NULL; + } + } + + if (standardcomp || daylightcomp) { + if (!standardcomp) + standardcomp = daylightcomp; + write_tz_rule_comps (ba, is_recur, standardcomp, daylightcomp, zone); + any_added = TRUE; + } + } + + /* at least one should be always added, make it UTC */ + if (!any_added) { + struct icaltimetype fake_utc; + + memset (&fake_utc, 0, sizeof (struct icaltimetype)); + + write_tz_rule (ba, is_recur, 0, 0, 0, fake_utc, fake_utc); + } +} + #define TZDEFINITION_FLAG_VALID_GUID 0x0001 // the guid is valid #define TZDEFINITION_FLAG_VALID_KEYNAME 0x0002 // the keyname is valid #define TZ_MAX_RULES 1024 @@ -383,13 +572,29 @@ e_mapi_cal_tz_util_dump (void) void e_mapi_cal_util_mapi_tz_to_bin (const gchar *mapi_tzid, struct SBinary_short *bin, - TALLOC_CTX *mem_ctx) + TALLOC_CTX *mem_ctx, + gboolean is_recur) { GByteArray *ba; guint8 flag8; guint16 flag16; gunichar2 *buf; glong items_written; + icaltimezone *zone = NULL; + icalcomponent *vtimezone; + gint rules = 0; + const gchar *ical_location = e_mapi_cal_tz_util_get_ical_equivalent (mapi_tzid); + + if (ical_location && *ical_location) + zone = icaltimezone_get_builtin_timezone (ical_location); + if (!zone) + zone = icaltimezone_get_utc_timezone (); + vtimezone = icaltimezone_get_component (zone); + if (vtimezone) + rules = (icalcomponent_count_components (vtimezone, ICAL_XSTANDARD_COMPONENT) + + icalcomponent_count_components (vtimezone, ICAL_XDAYLIGHT_COMPONENT)) / 2; + if (!rules) + rules = 1; ba = g_byte_array_new (); @@ -401,8 +606,8 @@ e_mapi_cal_util_mapi_tz_to_bin (const gc ba = g_byte_array_append (ba, (const guint8 *)buf, (sizeof (gunichar2) * items_written)); g_free (buf); - /* number of rules *//* FIXME: Need to support rules */ - flag16 = 0x0000; + /* number of rules */ + flag16 = rules; ba = g_byte_array_append (ba, (const guint8 *)&flag16, sizeof (guint16)); /* wFlags: we know only keyname based names */ @@ -421,7 +626,8 @@ e_mapi_cal_util_mapi_tz_to_bin (const gc flag8 = TZ_BIN_VERSION_MAJOR; ba = g_byte_array_prepend (ba, (const guint8 *)&flag8, sizeof (guint8)); - /* Rules may now be appended here */ + /* Rules */ + add_timezone_rules (ba, is_recur, vtimezone, zone); bin->cb = ba->len; bin->lpb = talloc_memdup (mem_ctx, ba->data, ba->len); diff -up evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-tz-utils.h.show-events-owa evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-tz-utils.h --- evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-tz-utils.h.show-events-owa 2012-03-26 10:17:12.000000000 +0200 +++ evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-tz-utils.h 2013-10-17 12:30:05.858075342 +0200 @@ -39,7 +39,8 @@ void e_mapi_cal_tz_util_destroy (void) void e_mapi_cal_tz_util_dump (void); void e_mapi_cal_util_mapi_tz_to_bin (const gchar *mapi_tzid, struct SBinary_short *bin, - TALLOC_CTX *mem_ctx); + TALLOC_CTX *mem_ctx, + gboolean is_recur); int e_mapi_cal_util_mapi_tz_pidlidtimezone (icaltimezone *ictz); gchar * e_mapi_cal_util_bin_to_mapi_tz (const guint8 *lpb, guint32 cb); diff -up evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-utils.c.show-events-owa evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-utils.c --- evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-utils.c.show-events-owa 2013-01-15 14:03:36.000000000 +0100 +++ evolution-mapi-3.8.5/src/libexchangemapi/e-mapi-cal-utils.c 2013-10-17 12:30:05.859075342 +0200 @@ -1859,8 +1859,15 @@ e_mapi_cal_utils_comp_to_object (EMapiCo /* Start TZ */ mapi_tzid = e_mapi_cal_tz_util_get_mapi_equivalent ((dtstart_tz_location && *dtstart_tz_location) ? dtstart_tz_location : "UTC"); if (mapi_tzid && *mapi_tzid) { - e_mapi_cal_util_mapi_tz_to_bin (mapi_tzid, &start_tz, object); + e_mapi_cal_util_mapi_tz_to_bin (mapi_tzid, &start_tz, object, FALSE); set_value (PidLidAppointmentTimeZoneDefinitionStartDisplay, &start_tz); + + if (e_cal_component_has_recurrences (comp)) { + struct SBinary_short recur_tz; + + e_mapi_cal_util_mapi_tz_to_bin (mapi_tzid, &recur_tz, object, TRUE); + set_value (PidLidAppointmentTimeZoneDefinitionRecur, &recur_tz); + } } set_value (PidLidTimeZoneDescription, mapi_tzid ? mapi_tzid : ""); @@ -1873,7 +1880,7 @@ e_mapi_cal_utils_comp_to_object (EMapiCo /* End TZ */ mapi_tzid = e_mapi_cal_tz_util_get_mapi_equivalent ((dtend_tz_location && *dtend_tz_location) ? dtend_tz_location : "UTC"); if (mapi_tzid && *mapi_tzid) { - e_mapi_cal_util_mapi_tz_to_bin (mapi_tzid, &end_tz, object); + e_mapi_cal_util_mapi_tz_to_bin (mapi_tzid, &end_tz, object, FALSE); set_value (PidLidAppointmentTimeZoneDefinitionEndDisplay, &end_tz); }