Blame SOURCES/evolution-mapi-3.8.5-show-events-owa.patch

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