Blame SOURCES/evolution-ews-3.22.6-free-busy-calendar.patch

974103
diff -up evolution-ews-3.22.6/src/calendar/e-cal-backend-ews.c.free-busy-calendar evolution-ews-3.22.6/src/calendar/e-cal-backend-ews.c
974103
--- evolution-ews-3.22.6/src/calendar/e-cal-backend-ews.c.free-busy-calendar	2017-02-06 14:06:19.000000000 +0100
974103
+++ evolution-ews-3.22.6/src/calendar/e-cal-backend-ews.c	2017-05-24 15:38:44.189519188 +0200
974103
@@ -43,6 +43,7 @@
974103
 #include <calendar/gui/itip-utils.h>
974103
 
974103
 #include "server/e-source-ews-folder.h"
974103
+#include "server/e-ews-calendar-utils.h"
974103
 #include "server/e-ews-connection-utils.h"
974103
 
974103
 #include "utils/ews-camel-common.h"
974103
@@ -87,6 +88,7 @@ struct _ECalBackendEwsPrivate {
974103
 
974103
 	guint subscription_key;
974103
 	gboolean listen_notifications;
974103
+	gboolean is_freebusy_calendar;
974103
 };
974103
 
974103
 #define PRIV_LOCK(p)   (g_rec_mutex_lock (&(p)->rec_mutex))
974103
@@ -735,7 +737,7 @@ cbews_listen_notifications_cb (ECalBacke
974103
 		return;
974103
 	}
974103
 
974103
-	cbews->priv->listen_notifications = camel_ews_settings_get_listen_notifications (ews_settings);
974103
+	cbews->priv->listen_notifications = !cbews->priv->is_freebusy_calendar && camel_ews_settings_get_listen_notifications (ews_settings);
974103
 	PRIV_UNLOCK (cbews->priv);
974103
 
974103
 	thread = g_thread_new (NULL, handle_notifications_thread, g_object_ref (cbews));
974103
@@ -819,6 +821,7 @@ e_cal_backend_ews_open (ECalBackend *bac
974103
 		extension_name = E_SOURCE_EXTENSION_EWS_FOLDER;
974103
 		extension = e_source_get_extension (source, extension_name);
974103
 		priv->folder_id = e_source_ews_folder_dup_id (extension);
974103
+		priv->is_freebusy_calendar = g_strcmp0 (priv->folder_id, "freebusy-calendar") == 0;
974103
 
974103
 		priv->storage_path = g_build_filename (cache_dir, priv->folder_id, NULL);
974103
 
974103
@@ -848,11 +851,11 @@ e_cal_backend_ews_open (ECalBackend *bac
974103
 		ret = cal_backend_ews_ensure_connected (cbews, cancellable, &error);
974103
 
974103
 	if (ret) {
974103
-		e_cal_backend_set_writable (backend, TRUE);
974103
+		e_cal_backend_set_writable (backend, !priv->is_freebusy_calendar);
974103
 
974103
 		PRIV_LOCK (priv);
974103
 		if (priv->cnc != NULL) {
974103
-			priv->listen_notifications = camel_ews_settings_get_listen_notifications (ews_settings);
974103
+			priv->listen_notifications = !priv->is_freebusy_calendar && camel_ews_settings_get_listen_notifications (ews_settings);
974103
 
974103
 			if (priv->listen_notifications)
974103
 				cbews_listen_notifications_cb (cbews, NULL, ews_settings);
974103
@@ -3857,6 +3860,34 @@ cbews_forget_all_components (ECalBackend
974103
 	g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
974103
 }
974103
 
974103
+static gboolean
974103
+ews_freebusy_ecomp_changed (ECalComponent *ecomp,
974103
+			    icalcomponent *vevent)
974103
+{
974103
+	icalcomponent *icomp;
974103
+	gboolean changed = FALSE;
974103
+
974103
+	g_return_val_if_fail (vevent != NULL, FALSE);
974103
+
974103
+	if (!ecomp)
974103
+		return TRUE;
974103
+
974103
+	icomp = e_cal_component_get_icalcomponent (ecomp);
974103
+	if (!icomp)
974103
+		return TRUE;
974103
+
974103
+	if (!changed)
974103
+		changed = g_strcmp0 (icalcomponent_get_summary (icomp), icalcomponent_get_summary (vevent)) != 0;
974103
+	if (!changed)
974103
+		changed = g_strcmp0 (icalcomponent_get_location (icomp), icalcomponent_get_location (vevent)) != 0;
974103
+	if (!changed)
974103
+		changed = icaltime_compare (icalcomponent_get_dtstart (icomp), icalcomponent_get_dtstart (vevent)) != 0;
974103
+	if (!changed)
974103
+		changed = icaltime_compare (icalcomponent_get_dtend (icomp), icalcomponent_get_dtend (vevent)) != 0;
974103
+
974103
+	return changed;
974103
+}
974103
+
974103
 static gpointer
974103
 ews_start_sync_thread (gpointer data)
974103
 {
974103
@@ -3877,95 +3908,288 @@ ews_start_sync_thread (gpointer data)
974103
 
974103
 	cancellable = cal_backend_ews_ref_cancellable (cbews);
974103
 
974103
-	old_sync_state = g_strdup (e_cal_backend_store_get_key_value (priv->store, SYNC_KEY));
974103
-	do {
974103
-		EEwsAdditionalProps *add_props;
974103
-		GCancellable *cancellable;
974103
+	if (priv->is_freebusy_calendar) {
974103
+		ESourceEwsFolder *ews_folder;
974103
+		EEWSFreeBusyData fbdata;
974103
+		GSList *free_busy = NULL, *link;
974103
+		gboolean success;
974103
+		time_t today;
974103
+
974103
+		ews_folder = e_source_get_extension (e_backend_get_source (E_BACKEND (cbews)), E_SOURCE_EXTENSION_EWS_FOLDER);
974103
+
974103
+		today = time_day_begin (time (NULL));
974103
+
974103
+		fbdata.period_start = time_add_week (today, -e_source_ews_folder_get_freebusy_weeks_before (ews_folder));
974103
+		fbdata.period_end = time_day_end (time_add_week (today, e_source_ews_folder_get_freebusy_weeks_after (ews_folder)));
974103
+		fbdata.user_mails = g_slist_prepend (NULL, e_source_ews_folder_dup_foreign_mail (ews_folder));
974103
+
974103
+		success = e_ews_connection_get_free_busy_sync (priv->cnc, G_PRIORITY_DEFAULT,
974103
+			e_ews_cal_utils_prepare_free_busy_request, &fbdata,
974103
+			&free_busy, cancellable, &error);
974103
+
974103
+		if (success) {
974103
+			icaltimezone *utc_zone = icaltimezone_get_utc_timezone ();
974103
+			GSList *ids;
974103
+			GHashTable *known;
974103
+			GHashTableIter iter;
974103
+			gpointer key;
974103
+
974103
+			known = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
974103
+
974103
+			ids = e_cal_backend_store_get_component_ids (priv->store);
974103
+			for (link = ids; link; link = g_slist_next (link)) {
974103
+				ECalComponentId *id = link->data;
974103
 
974103
-		includes_last_item = TRUE;
974103
+				if (id && id->uid && *id->uid)
974103
+					g_hash_table_insert (known, g_strdup (id->uid), NULL);
974103
+			}
974103
+			g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
974103
 
974103
-		add_props = e_ews_additional_props_new ();
974103
-		add_props->field_uri = g_strdup ("item:ItemClass");
974103
+			for (link = free_busy; link; link = g_slist_next (link)) {
974103
+				icalcomponent *fbcomp = link->data;
974103
+				icalproperty *fbprop;
974103
+				icalparameter *param;
974103
+				struct icalperiodtype fb;
974103
+				icalparameter_fbtype fbtype;
974103
+
974103
+				if (!fbcomp || icalcomponent_isa (fbcomp) != ICAL_VFREEBUSY_COMPONENT)
974103
+					continue;
974103
+
974103
+				for (fbprop = icalcomponent_get_first_property (fbcomp, ICAL_FREEBUSY_PROPERTY);
974103
+				     fbprop;
974103
+				     fbprop = icalcomponent_get_next_property (fbcomp, ICAL_FREEBUSY_PROPERTY)) {
974103
+					icalcomponent *vevent;
974103
+					const gchar *id, *summary, *location;
974103
+
974103
+					param = icalproperty_get_first_parameter (fbprop, ICAL_FBTYPE_PARAMETER);
974103
+					if (!param)
974103
+						continue;
974103
+
974103
+					fbtype = icalparameter_get_fbtype (param);
974103
+
974103
+					if (fbtype != ICAL_FBTYPE_FREE &&
974103
+					    fbtype != ICAL_FBTYPE_BUSY &&
974103
+					    fbtype != ICAL_FBTYPE_BUSYUNAVAILABLE &&
974103
+					    fbtype != ICAL_FBTYPE_BUSYTENTATIVE)
974103
+						continue;
974103
+
974103
+					fb = icalproperty_get_freebusy (fbprop);
974103
+					id = icalproperty_get_parameter_as_string (fbprop, "X-EWS-ID");
974103
+					summary = icalproperty_get_parameter_as_string (fbprop, "X-SUMMARY");
974103
+					location = icalproperty_get_parameter_as_string (fbprop, "X-LOCATION");
974103
 
974103
-		cancellable = cal_backend_ews_ref_cancellable (cbews);
974103
+					vevent = icalcomponent_new_vevent ();
974103
 
974103
-		ret = e_ews_connection_sync_folder_items_sync (
974103
-			priv->cnc,
974103
-			EWS_PRIORITY_MEDIUM,
974103
-			old_sync_state,
974103
-			priv->folder_id,
974103
-			"IdOnly",
974103
-			add_props,
974103
-			EWS_MAX_FETCH_COUNT,
974103
-			&new_sync_state,
974103
-			&includes_last_item,
974103
-			&items_created,
974103
-			&items_updated,
974103
-			&items_deleted,
974103
-			cancellable,
974103
-			&error);
974103
+					if (id && *id) {
974103
+						icalcomponent_set_uid (vevent, id);
974103
+					} else {
974103
+						gchar *uid;
974103
 
974103
-		e_ews_additional_props_free (add_props);
974103
-		g_clear_object (&cancellable);
974103
-		g_free (old_sync_state);
974103
-		old_sync_state = NULL;
974103
+						uid = g_strdup_printf ("%s-%s-%d",
974103
+							icaltime_as_ical_string (fb.start),
974103
+							icaltime_as_ical_string (fb.end),
974103
+							(gint) fbtype);
974103
+
974103
+						icalcomponent_set_uid (vevent, uid);
974103
+
974103
+						g_free (uid);
974103
+					}
974103
 
974103
-		if (!ret) {
974103
-			if (g_error_matches (error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_INVALIDSYNCSTATEDATA)) {
974103
-				g_clear_error (&error);
974103
-				e_cal_backend_store_put_key_value (priv->store, SYNC_KEY, NULL);
974103
-				cbews_forget_all_components (cbews);
974103
-
974103
-				if (!e_ews_connection_sync_folder_items_sync (
974103
-							priv->cnc,
974103
-							EWS_PRIORITY_MEDIUM,
974103
-							NULL,
974103
-							priv->folder_id,
974103
-							"IdOnly",
974103
-							NULL,
974103
-							EWS_MAX_FETCH_COUNT,
974103
-							&new_sync_state,
974103
-							&includes_last_item,
974103
-							&items_created,
974103
-							&items_updated,
974103
-							&items_deleted,
974103
-							cancellable,
974103
-							&error)) {
974103
-					if (!g_error_matches (
974103
-							error,
974103
-							EWS_CONNECTION_ERROR,
974103
-							EWS_CONNECTION_ERROR_AUTHENTICATION_FAILED)) {
974103
-						e_cal_backend_set_writable (E_CAL_BACKEND (cbews), TRUE);
974103
-						break;
974103
+					fb.start.zone = utc_zone;
974103
+					fb.start.is_utc = 1;
974103
+					fb.end.zone = utc_zone;
974103
+					fb.end.is_utc = 1;
974103
+
974103
+					icalcomponent_set_dtstart (vevent, fb.start);
974103
+					icalcomponent_set_dtend (vevent, fb.end);
974103
+
974103
+					icalcomponent_add_property (vevent, icalproperty_new_created (icaltime_current_time_with_zone (utc_zone)));
974103
+
974103
+					if (fbtype == ICAL_FBTYPE_FREE) {
974103
+						icalcomponent_set_summary (vevent, C_("FreeBusyType", "Free"));
974103
+						icalcomponent_add_property (vevent, icalproperty_new_transp (ICAL_TRANSP_TRANSPARENT));
974103
+					} else if (fbtype == ICAL_FBTYPE_BUSY) {
974103
+						icalcomponent_set_summary (vevent, C_("FreeBusyType", "Busy"));
974103
+					} else if (fbtype == ICAL_FBTYPE_BUSYUNAVAILABLE) {
974103
+						icalcomponent_set_summary (vevent, C_("FreeBusyType", "Out of Office"));
974103
+					} else if (fbtype == ICAL_FBTYPE_BUSYTENTATIVE) {
974103
+						icalcomponent_set_summary (vevent, C_("FreeBusyType", "Tentative"));
974103
+					}
974103
+
974103
+					if (summary && *summary)
974103
+						icalcomponent_set_summary (vevent, summary);
974103
+
974103
+					if (location && *location)
974103
+						icalcomponent_set_location (vevent, location);
974103
+
974103
+					PRIV_LOCK (priv);
974103
+					if (g_hash_table_remove (known, icalcomponent_get_uid (vevent))) {
974103
+						ECalComponent *ecomp = g_hash_table_lookup (priv->item_id_hash, icalcomponent_get_uid (vevent));
974103
+
974103
+						g_object_ref (ecomp);
974103
+
974103
+						PRIV_UNLOCK (priv);
974103
+
974103
+						if (ews_freebusy_ecomp_changed (ecomp, vevent)) {
974103
+							ECalComponent *new_ecomp;
974103
+							gchar *uid = g_strdup (icalcomponent_get_uid (vevent));
974103
+
974103
+							new_ecomp = e_cal_component_new_from_icalcomponent (vevent);
974103
+							if (new_ecomp) {
974103
+								PRIV_LOCK (priv);
974103
+								g_hash_table_insert (priv->item_id_hash, uid, g_object_ref (new_ecomp));
974103
+								PRIV_UNLOCK (priv);
974103
+
974103
+								put_component_to_store (cbews, new_ecomp);
974103
+								e_cal_backend_notify_component_modified (E_CAL_BACKEND (cbews), ecomp, new_ecomp);
974103
+
974103
+								g_object_unref (new_ecomp);
974103
+							} else {
974103
+								g_free (uid);
974103
+							}
974103
+						} else {
974103
+							icalcomponent_free (vevent);
974103
+						}
974103
+
974103
+						g_clear_object (&ecomp);
974103
+					} else {
974103
+						ECalComponent *ecomp;
974103
+						gchar *uid = g_strdup (icalcomponent_get_uid (vevent));
974103
+
974103
+						ecomp = e_cal_component_new_from_icalcomponent (vevent);
974103
+						if (ecomp)
974103
+							g_hash_table_insert (priv->item_id_hash, uid, g_object_ref (ecomp));
974103
+						else
974103
+							g_free (uid);
974103
+
974103
+						PRIV_UNLOCK (priv);
974103
+
974103
+						if (ecomp) {
974103
+							put_component_to_store (cbews, ecomp);
974103
+							e_cal_backend_notify_component_created (E_CAL_BACKEND (cbews), ecomp);
974103
+						}
974103
+
974103
+						g_clear_object (&ecomp);
974103
 					}
974103
 				}
974103
-			} else {
974103
-				break;
974103
 			}
974103
+
974103
+			g_hash_table_iter_init (&iter, known);
974103
+			while (g_hash_table_iter_next (&iter, &key, NULL)) {
974103
+				ECalComponentId id = { 0 };
974103
+
974103
+				id.uid = key;
974103
+				id.rid = NULL;
974103
+
974103
+				if (e_cal_backend_store_remove_component (priv->store, id.uid, id.rid)) {
974103
+					e_cal_backend_notify_component_removed (E_CAL_BACKEND (cbews), &id, NULL, NULL);
974103
+
974103
+					PRIV_LOCK (priv);
974103
+					g_hash_table_remove (priv->item_id_hash, id.uid);
974103
+					PRIV_UNLOCK (priv);
974103
+				}
974103
+			}
974103
+
974103
+			g_hash_table_destroy (known);
974103
+		} else if (g_error_matches (error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_NOFREEBUSYACCESS)) {
974103
+			cbews_forget_all_components (cbews);
974103
+			e_cal_backend_notify_error (E_CAL_BACKEND (cbews), error->message);
974103
+			g_clear_error (&error);
974103
 		}
974103
 
974103
-		ret = cal_backend_ews_process_folder_items (
974103
-				cbews,
974103
-				new_sync_state,
974103
-				items_created,
974103
-				items_updated,
974103
-				items_deleted);
974103
+		g_slist_free_full (free_busy, (GDestroyNotify) icalcomponent_free);
974103
+		g_slist_free_full (fbdata.user_mails, g_free);
974103
+	} else {
974103
+		old_sync_state = g_strdup (e_cal_backend_store_get_key_value (priv->store, SYNC_KEY));
974103
+		do {
974103
+			EEwsAdditionalProps *add_props;
974103
+			GCancellable *cancellable;
974103
+
974103
+			includes_last_item = TRUE;
974103
 
974103
-		if (!ret)
974103
-			break;
974103
+			add_props = e_ews_additional_props_new ();
974103
+			add_props->field_uri = g_strdup ("item:ItemClass");
974103
 
974103
-		g_slist_free_full (items_created, g_object_unref);
974103
-		g_slist_free_full (items_updated, g_object_unref);
974103
-		g_slist_free_full (items_deleted, g_free);
974103
-		items_created = NULL;
974103
-		items_updated = NULL;
974103
-		items_deleted = NULL;
974103
-
974103
-		e_cal_backend_store_put_key_value (priv->store, SYNC_KEY, new_sync_state);
974103
-
974103
-		old_sync_state = new_sync_state;
974103
-		new_sync_state = NULL;
974103
-	} while (!includes_last_item);
974103
+			cancellable = cal_backend_ews_ref_cancellable (cbews);
974103
+
974103
+			ret = e_ews_connection_sync_folder_items_sync (
974103
+				priv->cnc,
974103
+				EWS_PRIORITY_MEDIUM,
974103
+				old_sync_state,
974103
+				priv->folder_id,
974103
+				"IdOnly",
974103
+				add_props,
974103
+				EWS_MAX_FETCH_COUNT,
974103
+				&new_sync_state,
974103
+				&includes_last_item,
974103
+				&items_created,
974103
+				&items_updated,
974103
+				&items_deleted,
974103
+				cancellable,
974103
+				&error);
974103
+
974103
+			e_ews_additional_props_free (add_props);
974103
+			g_clear_object (&cancellable);
974103
+			g_free (old_sync_state);
974103
+			old_sync_state = NULL;
974103
+
974103
+			if (!ret) {
974103
+				if (g_error_matches (error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_INVALIDSYNCSTATEDATA)) {
974103
+					g_clear_error (&error);
974103
+					e_cal_backend_store_put_key_value (priv->store, SYNC_KEY, NULL);
974103
+					cbews_forget_all_components (cbews);
974103
+
974103
+					if (!e_ews_connection_sync_folder_items_sync (
974103
+								priv->cnc,
974103
+								EWS_PRIORITY_MEDIUM,
974103
+								NULL,
974103
+								priv->folder_id,
974103
+								"IdOnly",
974103
+								NULL,
974103
+								EWS_MAX_FETCH_COUNT,
974103
+								&new_sync_state,
974103
+								&includes_last_item,
974103
+								&items_created,
974103
+								&items_updated,
974103
+								&items_deleted,
974103
+								cancellable,
974103
+								&error)) {
974103
+						if (!g_error_matches (
974103
+								error,
974103
+								EWS_CONNECTION_ERROR,
974103
+								EWS_CONNECTION_ERROR_AUTHENTICATION_FAILED)) {
974103
+							e_cal_backend_set_writable (E_CAL_BACKEND (cbews), TRUE);
974103
+							break;
974103
+						}
974103
+					}
974103
+				} else {
974103
+					break;
974103
+				}
974103
+			}
974103
+
974103
+			ret = cal_backend_ews_process_folder_items (
974103
+					cbews,
974103
+					new_sync_state,
974103
+					items_created,
974103
+					items_updated,
974103
+					items_deleted);
974103
+
974103
+			if (!ret)
974103
+				break;
974103
+
974103
+			g_slist_free_full (items_created, g_object_unref);
974103
+			g_slist_free_full (items_updated, g_object_unref);
974103
+			g_slist_free_full (items_deleted, g_free);
974103
+			items_created = NULL;
974103
+			items_updated = NULL;
974103
+			items_deleted = NULL;
974103
+
974103
+			e_cal_backend_store_put_key_value (priv->store, SYNC_KEY, new_sync_state);
974103
+
974103
+			old_sync_state = new_sync_state;
974103
+			new_sync_state = NULL;
974103
+		} while (!includes_last_item);
974103
+	}
974103
 
974103
 	ews_refreshing_dec (cbews);
974103
 
974103
@@ -4163,7 +4387,7 @@ e_cal_backend_ews_get_free_busy (ECalBac
974103
 	ECalBackendEwsPrivate *priv = cbews->priv;
974103
 	GError *error = NULL;
974103
 	EwsCalendarAsyncData *free_busy_data;
974103
-	EwsCalendarConvertData convert_data = { 0 };
974103
+	EEWSFreeBusyData fbdata = { 0 };
974103
 	GSList *users_copy = NULL;
974103
 
974103
 	/* make sure we're not offline */
974103
@@ -4193,15 +4417,15 @@ e_cal_backend_ews_get_free_busy (ECalBac
974103
 	free_busy_data->context = context;
974103
 	free_busy_data->users = users_copy;
974103
 
974103
-	convert_data.users = users_copy;
974103
-	convert_data.start = start;
974103
-	convert_data.end = end;
974103
+	fbdata.period_start = start;
974103
+	fbdata.period_end = end;
974103
+	fbdata.user_mails = users_copy;
974103
 
974103
 	e_ews_connection_get_free_busy (
974103
 		priv->cnc,
974103
 		EWS_PRIORITY_MEDIUM,
974103
-		e_cal_backend_ews_prepare_free_busy_request,
974103
-		&convert_data,
974103
+		e_ews_cal_utils_prepare_free_busy_request,
974103
+		&fbdata,
974103
 		cancellable,
974103
 		ews_cal_get_free_busy_cb,
974103
 		free_busy_data);
974103
diff -up evolution-ews-3.22.6/src/calendar/e-cal-backend-ews-utils.c.free-busy-calendar evolution-ews-3.22.6/src/calendar/e-cal-backend-ews-utils.c
974103
--- evolution-ews-3.22.6/src/calendar/e-cal-backend-ews-utils.c.free-busy-calendar	2016-12-16 12:36:06.000000000 +0100
974103
+++ evolution-ews-3.22.6/src/calendar/e-cal-backend-ews-utils.c	2017-05-24 15:38:44.189519188 +0200
974103
@@ -42,6 +42,7 @@
974103
 #include <libecal/libecal.h>
974103
 #include <libsoup/soup-misc.h>
974103
 
974103
+#include "server/e-ews-calendar-utils.h"
974103
 #include "server/e-ews-connection.h"
974103
 #include "server/e-ews-message.h"
974103
 #include "server/e-ews-item-change.h"
974103
@@ -338,49 +339,6 @@ ews_set_alarm (ESoapMessage *msg,
974103
 
974103
 }
974103
 
974103
-void
974103
-ewscal_set_time (ESoapMessage *msg,
974103
-                 const gchar *name,
974103
-                 icaltimetype *t,
974103
-                 gboolean with_timezone)
974103
-{
974103
-	gchar *str;
974103
-	gchar *tz_ident = NULL;
974103
-
974103
-	if (with_timezone) {
974103
-		if (t->is_utc || !t->zone || t->zone == icaltimezone_get_utc_timezone ()) {
974103
-			tz_ident = g_strdup ("Z");
974103
-		} else {
974103
-			gint offset, is_daylight, hrs, mins;
974103
-
974103
-			offset = icaltimezone_get_utc_offset (
974103
-				icaltimezone_get_utc_timezone (), t, &is_daylight);
974103
-
974103
-			offset = offset * (-1);
974103
-			hrs = offset / 60;
974103
-			mins = offset % 60;
974103
-
974103
-			if (hrs < 0)
974103
-				hrs *= -1;
974103
-			if (mins < 0)
974103
-				mins *= -1;
974103
-
974103
-			tz_ident = g_strdup_printf ("%s%02d:%02d", offset > 0 ? "+" : "-", hrs, mins);
974103
-		}
974103
-	}
974103
-
974103
-	str = g_strdup_printf (
974103
-		"%04d-%02d-%02dT%02d:%02d:%02d%s",
974103
-		t->year, t->month, t->day,
974103
-		t->hour, t->minute, t->second,
974103
-		tz_ident ? tz_ident : "");
974103
-
974103
-	e_ews_message_write_string_parameter (msg, name, NULL, str);
974103
-
974103
-	g_free (tz_ident);
974103
-	g_free (str);
974103
-}
974103
-
974103
 static void
974103
 ewscal_set_date (ESoapMessage *msg,
974103
                  const gchar *name,
974103
@@ -713,136 +671,6 @@ ewscal_set_meeting_timezone (ESoapMessag
974103
 	e_soap_message_end_element (msg); /* "MeetingTimeZone" */
974103
 }
974103
 
974103
-static void
974103
-ewscal_add_availability_rrule (ESoapMessage *msg,
974103
-                               icalproperty *prop)
974103
-{
974103
-	struct icalrecurrencetype recur = icalproperty_get_rrule (prop);
974103
-	gchar buffer[16];
974103
-	gint dayorder;
974103
-
974103
-	dayorder = icalrecurrencetype_day_position (recur.by_day[0]);
974103
-	dayorder = dayorder % 5;
974103
-	if (dayorder < 0)
974103
-		dayorder += 5;
974103
-	dayorder += 1;
974103
-
974103
-	/* expected value is 1..5, inclusive */
974103
-	snprintf (buffer, 16, "%d", dayorder);
974103
-	e_ews_message_write_string_parameter (msg, "DayOrder", NULL, buffer);
974103
-
974103
-	snprintf (buffer, 16, "%d", recur.by_month[0]);
974103
-	e_ews_message_write_string_parameter (msg, "Month", NULL, buffer);
974103
-
974103
-	e_ews_message_write_string_parameter (msg, "DayOfWeek", NULL, number_to_weekday (icalrecurrencetype_day_day_of_week (recur.by_day[0])));
974103
-}
974103
-
974103
-static void
974103
-ewscal_add_availability_default_timechange (ESoapMessage *msg)
974103
-{
974103
-
974103
-	e_soap_message_start_element (msg, "StandardTime", NULL, NULL);
974103
-	e_ews_message_write_string_parameter (msg, "Bias", NULL, "0");
974103
-	e_ews_message_write_string_parameter (msg, "Time", NULL, "00:00:00");
974103
-	e_ews_message_write_string_parameter (msg, "DayOrder", NULL, "0");
974103
-	e_ews_message_write_string_parameter (msg, "Month", NULL, "0");
974103
-	e_ews_message_write_string_parameter (msg, "DayOfWeek", NULL, "Sunday");
974103
-	e_soap_message_end_element (msg);
974103
-
974103
-	e_soap_message_start_element (msg, "DaylightTime", NULL, NULL);
974103
-	e_ews_message_write_string_parameter (msg, "Bias", NULL, "0");
974103
-	e_ews_message_write_string_parameter (msg, "Time", NULL, "00:00:00");
974103
-	e_ews_message_write_string_parameter (msg, "DayOrder", NULL, "0");
974103
-	e_ews_message_write_string_parameter (msg, "Month", NULL, "0");
974103
-	e_ews_message_write_string_parameter (msg, "DayOfWeek", NULL, "Sunday");
974103
-	e_soap_message_end_element (msg);
974103
-}
974103
-
974103
-static void
974103
-ewscal_add_availability_timechange (ESoapMessage *msg,
974103
-                                    icalcomponent *comp,
974103
-                                    gint baseoffs)
974103
-{
974103
-	gchar buffer[16];
974103
-	icalproperty *prop;
974103
-	struct icaltimetype dtstart;
974103
-	gint utcoffs;
974103
-
974103
-	/* Calculate zone Offset from BaseOffset */
974103
-	prop = icalcomponent_get_first_property (comp, ICAL_TZOFFSETTO_PROPERTY);
974103
-	if (prop) {
974103
-		utcoffs = -icalproperty_get_tzoffsetto (prop) / 60;
974103
-		utcoffs -= baseoffs;
974103
-		snprintf (buffer, 16, "%d", utcoffs);
974103
-		e_ews_message_write_string_parameter (msg, "Bias", NULL, buffer);
974103
-	}
974103
-
974103
-	prop = icalcomponent_get_first_property (comp, ICAL_DTSTART_PROPERTY);
974103
-	if (prop) {
974103
-		dtstart = icalproperty_get_dtstart (prop);
974103
-		snprintf (buffer, 16, "%02d:%02d:%02d", dtstart.hour, dtstart.minute, dtstart.second);
974103
-		e_ews_message_write_string_parameter (msg, "Time", NULL, buffer);
974103
-	}
974103
-
974103
-	prop = icalcomponent_get_first_property (comp, ICAL_RRULE_PROPERTY);
974103
-	if (prop)
974103
-		ewscal_add_availability_rrule (msg, prop);
974103
-}
974103
-
974103
-void
974103
-ewscal_set_availability_timezone (ESoapMessage *msg,
974103
-                                  icaltimezone *icaltz)
974103
-{
974103
-	icalcomponent *comp;
974103
-	icalproperty *prop;
974103
-	icalcomponent *xstd, *xdaylight;
974103
-	gint std_utcoffs;
974103
-	gchar *offset;
974103
-
974103
-	if (!icaltz)
974103
-		return;
974103
-
974103
-	comp = icaltimezone_get_component (icaltz);
974103
-
974103
-	xstd = icalcomponent_get_first_component (comp, ICAL_XSTANDARD_COMPONENT);
974103
-	xdaylight = icalcomponent_get_first_component (comp, ICAL_XDAYLIGHT_COMPONENT);
974103
-
974103
-	/*TimeZone is the root element of GetUserAvailabilityRequest*/
974103
-	e_soap_message_start_element (msg, "TimeZone", NULL, NULL);
974103
-
974103
-	/* Fetch the timezone offsets for the standard (or only) zone.
974103
-	 * Negate it, because Exchange does it backwards */
974103
-	if (xstd) {
974103
-		prop = icalcomponent_get_first_property (xstd, ICAL_TZOFFSETTO_PROPERTY);
974103
-		std_utcoffs = -icalproperty_get_tzoffsetto (prop) / 60;
974103
-	} else
974103
-		std_utcoffs = 0;
974103
-
974103
-	/* This is the overall BaseOffset tag, which the Standard and Daylight
974103
-	 * zones are offset from. It's redundant, but Exchange always sets it
974103
-	 * to the offset of the Standard zone, and the Offset in the Standard
974103
-	 * zone to zero. So try to avoid problems by doing the same. */
974103
-	offset = g_strdup_printf ("%d", std_utcoffs);
974103
-	e_ews_message_write_string_parameter (msg, "Bias", NULL, offset);
974103
-	g_free (offset);
974103
-
974103
-	if (xdaylight) {
974103
-		/* Standard */
974103
-		e_soap_message_start_element (msg, "StandardTime", NULL, NULL);
974103
-		ewscal_add_availability_timechange (msg, xstd, std_utcoffs);
974103
-		e_soap_message_end_element (msg); /* "StandardTime" */
974103
-
974103
-		/* DayLight */
974103
-		e_soap_message_start_element (msg, "DaylightTime", NULL, NULL);
974103
-		ewscal_add_availability_timechange (msg, xdaylight, std_utcoffs);
974103
-		e_soap_message_end_element (msg); /* "DaylightTime" */
974103
-	} else
974103
-		/* Set default values*/
974103
-		ewscal_add_availability_default_timechange (msg);
974103
-
974103
-	e_soap_message_end_element (msg); /* "TimeZone" */
974103
-}
974103
-
974103
 void
974103
 ewscal_set_reccurence (ESoapMessage *msg,
974103
                        icalproperty *rrule,
974103
@@ -1321,8 +1149,8 @@ convert_vevent_calcomp_to_xml (ESoapMess
974103
 			ical_location_end);
974103
 	}
974103
 
974103
-	ewscal_set_time (msg, "Start", &dtstart, FALSE);
974103
-	ewscal_set_time (msg, "End", &dtend, FALSE);
974103
+	e_ews_cal_utils_set_time (msg, "Start", &dtstart, FALSE);
974103
+	e_ews_cal_utils_set_time (msg, "End", &dtend, FALSE);
974103
 	/* We have to do the time zone(s) later, or the server rejects the request */
974103
 
974103
 	/* All day event ? */
974103
@@ -1424,7 +1252,7 @@ convert_vtodo_calcomp_to_xml (ESoapMessa
974103
 	prop = icalcomponent_get_first_property (icalcomp, ICAL_DUE_PROPERTY);
974103
 	if (prop) {
974103
 		dt = icalproperty_get_due (prop);
974103
-		ewscal_set_time (msg, "DueDate", &dt, TRUE);
974103
+		e_ews_cal_utils_set_time (msg, "DueDate", &dt, TRUE);
974103
 	}
974103
 
974103
 	prop = icalcomponent_get_first_property (icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
974103
@@ -1437,7 +1265,7 @@ convert_vtodo_calcomp_to_xml (ESoapMessa
974103
 	prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
974103
 	if (prop) {
974103
 		dt = icalproperty_get_dtstart (prop);
974103
-		ewscal_set_time (msg, "StartDate", &dt, TRUE);
974103
+		e_ews_cal_utils_set_time (msg, "StartDate", &dt, TRUE);
974103
 	}
974103
 
974103
 	prop = icalcomponent_get_first_property (icalcomp, ICAL_STATUS_PROPERTY);
974103
@@ -1751,13 +1579,13 @@ convert_vevent_component_to_updatexml (E
974103
 
974103
 	if (dt_start_changed) {
974103
 		e_ews_message_start_set_item_field (msg, "Start", "calendar","CalendarItem");
974103
-		ewscal_set_time (msg, "Start", &dtstart, FALSE);
974103
+		e_ews_cal_utils_set_time (msg, "Start", &dtstart, FALSE);
974103
 		e_ews_message_end_set_item_field (msg);
974103
 	}
974103
 
974103
 	if (dt_end_changed) {
974103
 		e_ews_message_start_set_item_field (msg, "End", "calendar", "CalendarItem");
974103
-		ewscal_set_time (msg, "End", &dtend, FALSE);
974103
+		e_ews_cal_utils_set_time (msg, "End", &dtend, FALSE);
974103
 		e_ews_message_end_set_item_field (msg);
974103
 	}
974103
 
974103
@@ -1915,7 +1743,7 @@ convert_vtodo_component_to_updatexml (ES
974103
 	if (prop) {
974103
 		dt = icalproperty_get_due (prop);
974103
 		e_ews_message_start_set_item_field (msg, "DueDate", "task", "Task");
974103
-		ewscal_set_time (msg, "DueDate", &dt, TRUE);
974103
+		e_ews_cal_utils_set_time (msg, "DueDate", &dt, TRUE);
974103
 		e_ews_message_end_set_item_field (msg);
974103
 	} else {
974103
 		e_ews_message_add_delete_item_field (msg, "DueDate", "task");
974103
@@ -1934,7 +1762,7 @@ convert_vtodo_component_to_updatexml (ES
974103
 	if (prop) {
974103
 		dt = icalproperty_get_dtstart (prop);
974103
 		e_ews_message_start_set_item_field (msg, "StartDate", "task", "Task");
974103
-		ewscal_set_time (msg, "StartDate", &dt, TRUE);
974103
+		e_ews_cal_utils_set_time (msg, "StartDate", &dt, TRUE);
974103
 		e_ews_message_end_set_item_field (msg);
974103
 	} else {
974103
 		e_ews_message_add_delete_item_field (msg, "StartDate", "task");
974103
@@ -2100,49 +1928,6 @@ e_cal_backend_ews_clear_reminder_is_set
974103
 }
974103
 
974103
 void
974103
-e_cal_backend_ews_prepare_free_busy_request (ESoapMessage *msg,
974103
-					     gpointer user_data)
974103
-{
974103
-	EwsCalendarConvertData *convert_data = user_data;
974103
-	GSList *addr;
974103
-	icaltimetype t_start, t_end;
974103
-	icaltimezone *utc_zone = icaltimezone_get_utc_timezone ();
974103
-
974103
-	ewscal_set_availability_timezone (msg, utc_zone);
974103
-
974103
-	e_soap_message_start_element (msg, "MailboxDataArray", "messages", NULL);
974103
-
974103
-	for (addr = convert_data->users; addr; addr = addr->next) {
974103
-		e_soap_message_start_element (msg, "MailboxData", NULL, NULL);
974103
-
974103
-		e_soap_message_start_element (msg, "Email", NULL, NULL);
974103
-		e_ews_message_write_string_parameter (msg, "Address", NULL, addr->data);
974103
-		e_soap_message_end_element (msg); /* "Email" */
974103
-
974103
-		e_ews_message_write_string_parameter (msg, "AttendeeType", NULL, "Required");
974103
-		e_ews_message_write_string_parameter (msg, "ExcludeConflicts", NULL, "false");
974103
-
974103
-		e_soap_message_end_element (msg); /* "MailboxData" */
974103
-	}
974103
-
974103
-	e_soap_message_end_element (msg); /* "MailboxDataArray" */
974103
-
974103
-	e_soap_message_start_element (msg, "FreeBusyViewOptions", NULL, NULL);
974103
-
974103
-	e_soap_message_start_element (msg, "TimeWindow", NULL, NULL);
974103
-	t_start = icaltime_from_timet_with_zone (convert_data->start, 0, utc_zone);
974103
-	t_end = icaltime_from_timet_with_zone (convert_data->end, 0, utc_zone);
974103
-	ewscal_set_time (msg, "StartTime", &t_start, FALSE);
974103
-	ewscal_set_time (msg, "EndTime", &t_end, FALSE);
974103
-	e_soap_message_end_element (msg); /* "TimeWindow" */
974103
-
974103
-	e_ews_message_write_string_parameter (msg, "MergedFreeBusyIntervalInMinutes", NULL, "60");
974103
-	e_ews_message_write_string_parameter (msg, "RequestedView", NULL, "DetailedMerged");
974103
-
974103
-	e_soap_message_end_element (msg); /* "FreeBusyViewOptions" */
974103
-}
974103
-
974103
-void
974103
 e_cal_backend_ews_prepare_set_free_busy_status (ESoapMessage *msg,
974103
 						gpointer user_data)
974103
 {
974103
diff -up evolution-ews-3.22.6/src/calendar/e-cal-backend-ews-utils.h.free-busy-calendar evolution-ews-3.22.6/src/calendar/e-cal-backend-ews-utils.h
974103
--- evolution-ews-3.22.6/src/calendar/e-cal-backend-ews-utils.h.free-busy-calendar	2014-05-28 13:24:49.000000000 +0200
974103
+++ evolution-ews-3.22.6/src/calendar/e-cal-backend-ews-utils.h	2017-05-24 15:38:44.189519188 +0200
974103
@@ -57,10 +57,8 @@ typedef struct {
974103
 const gchar *e_ews_collect_organizer (icalcomponent *comp);
974103
 void e_ews_collect_attendees (icalcomponent *comp, GSList **required, GSList **optional, GSList **resource);
974103
 
974103
-void ewscal_set_time (ESoapMessage *msg, const gchar *name, icaltimetype *t, gboolean with_timezone);
974103
 void ewscal_set_timezone (ESoapMessage *msg, const gchar *name, EEwsCalendarTimeZoneDefinition *tzd);
974103
 void ewscal_set_meeting_timezone (ESoapMessage *msg, icaltimezone *icaltz);
974103
-void ewscal_set_availability_timezone (ESoapMessage *msg, icaltimezone *icaltz);
974103
 void ewscal_set_reccurence (ESoapMessage *msg, icalproperty *rrule, icaltimetype *dtstart);
974103
 void ewscal_set_reccurence_exceptions (ESoapMessage *msg, icalcomponent *comp);
974103
 void ewscal_get_attach_differences (const GSList *original, const GSList *modified, GSList **removed, GSList **added);
974103
@@ -77,7 +75,6 @@ void e_cal_backend_ews_unref_windows_zon
974103
 void e_cal_backend_ews_convert_calcomp_to_xml (ESoapMessage *msg, gpointer user_data);
974103
 void e_cal_backend_ews_convert_component_to_updatexml (ESoapMessage *msg, gpointer user_data);
974103
 void e_cal_backend_ews_clear_reminder_is_set (ESoapMessage *msg, gpointer user_data);
974103
-void e_cal_backend_ews_prepare_free_busy_request (ESoapMessage *msg, gpointer user_data);
974103
 void e_cal_backend_ews_prepare_set_free_busy_status (ESoapMessage *msg,gpointer user_data);
974103
 void e_cal_backend_ews_prepare_accept_item_request (ESoapMessage *msg, gpointer user_data);
974103
 
974103
diff -up evolution-ews-3.22.6/src/configuration/e-ews-subscribe-foreign-folder.c.free-busy-calendar evolution-ews-3.22.6/src/configuration/e-ews-subscribe-foreign-folder.c
974103
--- evolution-ews-3.22.6/src/configuration/e-ews-subscribe-foreign-folder.c.free-busy-calendar	2014-11-19 19:06:36.000000000 +0100
974103
+++ evolution-ews-3.22.6/src/configuration/e-ews-subscribe-foreign-folder.c	2017-05-24 15:38:44.190519183 +0200
974103
@@ -34,6 +34,8 @@
974103
 #include "camel/camel-ews-store-summary.h"
974103
 #include "camel/camel-ews-utils.h"
974103
 
974103
+#include "server/e-ews-calendar-utils.h"
974103
+
974103
 #include "e-ews-config-utils.h"
974103
 #include "e-ews-search-user.h"
974103
 #include "e-ews-subscribe-foreign-folder.h"
974103
@@ -344,24 +346,53 @@ check_foreign_folder_thread (GObject *wi
974103
 		return;
974103
 	}
974103
 
974103
-	fid.id = (gchar *) (cffd->use_foldername ? cffd->use_foldername : cffd->orig_foldername);
974103
-	fid.change_key = NULL;
974103
-	fid.is_distinguished_id = cffd->use_foldername != NULL;
974103
-
974103
-	if (!e_ews_connection_get_folder_info_sync (conn, G_PRIORITY_DEFAULT,
974103
-		cffd->email, &fid, &folder, cancellable, &local_error)) {
974103
-		if (g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_ITEMNOTFOUND) ||
974103
-		    g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_FOLDERNOTFOUND)) {
974103
-			g_clear_error (&local_error);
974103
-			local_error = g_error_new (
974103
-				EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_FOLDERNOTFOUND,
974103
-				_("Folder '%s' not found. Either it does not exist or you do not have permission to access it."),
974103
-				cffd->orig_foldername);
974103
+	if (g_strcmp0 (cffd->use_foldername, "freebusy-calendar") == 0) {
974103
+		EEWSFreeBusyData fbdata;
974103
+		GSList *free_busy = NULL;
974103
+		gboolean success;
974103
+
974103
+		fbdata.period_start = time (NULL);
974103
+		fbdata.period_end = fbdata.period_start + (60 * 60);
974103
+		fbdata.user_mails = g_slist_prepend (NULL, cffd->email);
974103
+
974103
+		success = e_ews_connection_get_free_busy_sync (conn, G_PRIORITY_DEFAULT,
974103
+			e_ews_cal_utils_prepare_free_busy_request, &fbdata,
974103
+			&free_busy, cancellable, perror);
974103
+
974103
+		g_slist_free_full (free_busy, (GDestroyNotify) icalcomponent_free);
974103
+		g_slist_free (fbdata.user_mails);
974103
+
974103
+		if (!success) {
974103
+			g_object_unref (conn);
974103
+			return;
974103
 		}
974103
 
974103
-		g_propagate_error (perror, local_error);
974103
-		g_object_unref (conn);
974103
-		return;
974103
+		folder = g_object_new (E_TYPE_EWS_FOLDER, NULL);
974103
+		e_ews_folder_set_id (folder, e_ews_folder_id_new (cffd->use_foldername, NULL, FALSE));
974103
+		/* Translators: This is used as a calendar name; it constructs "User Name - Availability" string shown in UI */
974103
+		e_ews_folder_set_name (folder, _("Availability"));
974103
+		e_ews_folder_set_folder_type (folder, E_EWS_FOLDER_TYPE_CALENDAR);
974103
+		e_ews_folder_set_foreign_mail (folder, cffd->email);
974103
+	} else {
974103
+		fid.id = (gchar *) (cffd->use_foldername ? cffd->use_foldername : cffd->orig_foldername);
974103
+		fid.change_key = NULL;
974103
+		fid.is_distinguished_id = cffd->use_foldername != NULL;
974103
+
974103
+		if (!e_ews_connection_get_folder_info_sync (conn, G_PRIORITY_DEFAULT,
974103
+			cffd->email, &fid, &folder, cancellable, &local_error)) {
974103
+			if (g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_ITEMNOTFOUND) ||
974103
+			    g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_FOLDERNOTFOUND)) {
974103
+				g_clear_error (&local_error);
974103
+				local_error = g_error_new (
974103
+					EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_FOLDERNOTFOUND,
974103
+					_("Folder '%s' not found. Either it does not exist or you do not have permission to access it."),
974103
+					cffd->orig_foldername);
974103
+			}
974103
+
974103
+			g_propagate_error (perror, local_error);
974103
+			g_object_unref (conn);
974103
+			return;
974103
+		}
974103
 	}
974103
 
974103
 	if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
974103
@@ -518,6 +549,8 @@ subscribe_foreign_response_cb (GObject *
974103
 		use_foldername = g_strdup ("contacts");
974103
 	} else if (g_strcmp0 (orig_foldername, _("Calendar")) == 0) {
974103
 		use_foldername = g_strdup ("calendar");
974103
+	} else if (g_strcmp0 (orig_foldername, _("Free/Busy as Calendar")) == 0) {
974103
+		use_foldername = g_strdup ("freebusy-calendar");
974103
 	} else if (g_strcmp0 (orig_foldername, _("Memos")) == 0) {
974103
 		use_foldername = g_strdup ("notes");
974103
 	} else if (g_strcmp0 (orig_foldername, _("Tasks")) == 0) {
974103
@@ -723,6 +756,7 @@ e_ews_subscribe_foreign_folder (GtkWindo
974103
 	gtk_combo_box_text_append_text (combo_text, _("Inbox"));
974103
 	gtk_combo_box_text_append_text (combo_text, _("Contacts"));
974103
 	gtk_combo_box_text_append_text (combo_text, _("Calendar"));
974103
+	gtk_combo_box_text_append_text (combo_text, _("Free/Busy as Calendar"));
974103
 	gtk_combo_box_text_append_text (combo_text, _("Memos"));
974103
 	gtk_combo_box_text_append_text (combo_text, _("Tasks"));
974103
 	gtk_combo_box_set_active (GTK_COMBO_BOX (combo_text), 0);
974103
diff -up evolution-ews-3.22.6/src/server/e-ews-calendar-utils.c.free-busy-calendar evolution-ews-3.22.6/src/server/e-ews-calendar-utils.c
974103
--- evolution-ews-3.22.6/src/server/e-ews-calendar-utils.c.free-busy-calendar	2017-05-24 15:38:44.190519183 +0200
974103
+++ evolution-ews-3.22.6/src/server/e-ews-calendar-utils.c	2017-05-24 15:38:44.190519183 +0200
974103
@@ -0,0 +1,260 @@
974103
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
974103
+/*
974103
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
974103
+ *
974103
+ * This program is free software; you can redistribute it and/or
974103
+ * modify it under the terms of version 2 of the GNU Lesser General Public
974103
+ * License as published by the Free Software Foundation.
974103
+ *
974103
+ * This program is distributed in the hope that it will be useful,
974103
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
974103
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
974103
+ * GNU Lesser General Public License for more details.
974103
+ *
974103
+ * You should have received a copy of the GNU Lesser General Public License
974103
+ * along with this program; if not, write to the Free Software
974103
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
974103
+ * USA
974103
+ */
974103
+
974103
+#ifdef HAVE_CONFIG_H
974103
+#include <config.h>
974103
+#endif
974103
+
974103
+#include "e-ews-message.h"
974103
+
974103
+#include "e-ews-calendar-utils.h"
974103
+
974103
+static const gchar *
974103
+number_to_weekday (gint num)
974103
+{
974103
+	static const gchar *days[] = {
974103
+		"Sunday", "Monday", "Tuesday", "Wednesday",
974103
+		"Thursday", "Friday", "Saturday",
974103
+		"Day", "Weekday", "WeekendDay"
974103
+	};
974103
+
974103
+	return days[num - 1];
974103
+}
974103
+
974103
+static void
974103
+ewscal_add_availability_rrule (ESoapMessage *msg,
974103
+                               icalproperty *prop)
974103
+{
974103
+	struct icalrecurrencetype recur = icalproperty_get_rrule (prop);
974103
+	gchar buffer[16];
974103
+	gint dayorder;
974103
+
974103
+	dayorder = icalrecurrencetype_day_position (recur.by_day[0]);
974103
+	dayorder = dayorder % 5;
974103
+	if (dayorder < 0)
974103
+		dayorder += 5;
974103
+	dayorder += 1;
974103
+
974103
+	/* expected value is 1..5, inclusive */
974103
+	snprintf (buffer, 16, "%d", dayorder);
974103
+	e_ews_message_write_string_parameter (msg, "DayOrder", NULL, buffer);
974103
+
974103
+	snprintf (buffer, 16, "%d", recur.by_month[0]);
974103
+	e_ews_message_write_string_parameter (msg, "Month", NULL, buffer);
974103
+
974103
+	e_ews_message_write_string_parameter (msg, "DayOfWeek", NULL, number_to_weekday (icalrecurrencetype_day_day_of_week (recur.by_day[0])));
974103
+}
974103
+
974103
+static void
974103
+ewscal_add_availability_default_timechange (ESoapMessage *msg)
974103
+{
974103
+
974103
+	e_soap_message_start_element (msg, "StandardTime", NULL, NULL);
974103
+	e_ews_message_write_string_parameter (msg, "Bias", NULL, "0");
974103
+	e_ews_message_write_string_parameter (msg, "Time", NULL, "00:00:00");
974103
+	e_ews_message_write_string_parameter (msg, "DayOrder", NULL, "0");
974103
+	e_ews_message_write_string_parameter (msg, "Month", NULL, "0");
974103
+	e_ews_message_write_string_parameter (msg, "DayOfWeek", NULL, "Sunday");
974103
+	e_soap_message_end_element (msg);
974103
+
974103
+	e_soap_message_start_element (msg, "DaylightTime", NULL, NULL);
974103
+	e_ews_message_write_string_parameter (msg, "Bias", NULL, "0");
974103
+	e_ews_message_write_string_parameter (msg, "Time", NULL, "00:00:00");
974103
+	e_ews_message_write_string_parameter (msg, "DayOrder", NULL, "0");
974103
+	e_ews_message_write_string_parameter (msg, "Month", NULL, "0");
974103
+	e_ews_message_write_string_parameter (msg, "DayOfWeek", NULL, "Sunday");
974103
+	e_soap_message_end_element (msg);
974103
+}
974103
+
974103
+static void
974103
+ewscal_add_availability_timechange (ESoapMessage *msg,
974103
+                                    icalcomponent *comp,
974103
+                                    gint baseoffs)
974103
+{
974103
+	gchar buffer[16];
974103
+	icalproperty *prop;
974103
+	struct icaltimetype dtstart;
974103
+	gint utcoffs;
974103
+
974103
+	/* Calculate zone Offset from BaseOffset */
974103
+	prop = icalcomponent_get_first_property (comp, ICAL_TZOFFSETTO_PROPERTY);
974103
+	if (prop) {
974103
+		utcoffs = -icalproperty_get_tzoffsetto (prop) / 60;
974103
+		utcoffs -= baseoffs;
974103
+		snprintf (buffer, 16, "%d", utcoffs);
974103
+		e_ews_message_write_string_parameter (msg, "Bias", NULL, buffer);
974103
+	}
974103
+
974103
+	prop = icalcomponent_get_first_property (comp, ICAL_DTSTART_PROPERTY);
974103
+	if (prop) {
974103
+		dtstart = icalproperty_get_dtstart (prop);
974103
+		snprintf (buffer, 16, "%02d:%02d:%02d", dtstart.hour, dtstart.minute, dtstart.second);
974103
+		e_ews_message_write_string_parameter (msg, "Time", NULL, buffer);
974103
+	}
974103
+
974103
+	prop = icalcomponent_get_first_property (comp, ICAL_RRULE_PROPERTY);
974103
+	if (prop)
974103
+		ewscal_add_availability_rrule (msg, prop);
974103
+}
974103
+
974103
+static void
974103
+ewscal_set_availability_timezone (ESoapMessage *msg,
974103
+                                  icaltimezone *icaltz)
974103
+{
974103
+	icalcomponent *comp;
974103
+	icalproperty *prop;
974103
+	icalcomponent *xstd, *xdaylight;
974103
+	gint std_utcoffs;
974103
+	gchar *offset;
974103
+
974103
+	if (!icaltz)
974103
+		return;
974103
+
974103
+	comp = icaltimezone_get_component (icaltz);
974103
+
974103
+	xstd = icalcomponent_get_first_component (comp, ICAL_XSTANDARD_COMPONENT);
974103
+	xdaylight = icalcomponent_get_first_component (comp, ICAL_XDAYLIGHT_COMPONENT);
974103
+
974103
+	/*TimeZone is the root element of GetUserAvailabilityRequest*/
974103
+	e_soap_message_start_element (msg, "TimeZone", NULL, NULL);
974103
+
974103
+	/* Fetch the timezone offsets for the standard (or only) zone.
974103
+	 * Negate it, because Exchange does it backwards */
974103
+	if (xstd) {
974103
+		prop = icalcomponent_get_first_property (xstd, ICAL_TZOFFSETTO_PROPERTY);
974103
+		std_utcoffs = -icalproperty_get_tzoffsetto (prop) / 60;
974103
+	} else
974103
+		std_utcoffs = 0;
974103
+
974103
+	/* This is the overall BaseOffset tag, which the Standard and Daylight
974103
+	 * zones are offset from. It's redundant, but Exchange always sets it
974103
+	 * to the offset of the Standard zone, and the Offset in the Standard
974103
+	 * zone to zero. So try to avoid problems by doing the same. */
974103
+	offset = g_strdup_printf ("%d", std_utcoffs);
974103
+	e_ews_message_write_string_parameter (msg, "Bias", NULL, offset);
974103
+	g_free (offset);
974103
+
974103
+	if (xdaylight) {
974103
+		/* Standard */
974103
+		e_soap_message_start_element (msg, "StandardTime", NULL, NULL);
974103
+		ewscal_add_availability_timechange (msg, xstd, std_utcoffs);
974103
+		e_soap_message_end_element (msg); /* "StandardTime" */
974103
+
974103
+		/* DayLight */
974103
+		e_soap_message_start_element (msg, "DaylightTime", NULL, NULL);
974103
+		ewscal_add_availability_timechange (msg, xdaylight, std_utcoffs);
974103
+		e_soap_message_end_element (msg); /* "DaylightTime" */
974103
+	} else
974103
+		/* Set default values*/
974103
+		ewscal_add_availability_default_timechange (msg);
974103
+
974103
+	e_soap_message_end_element (msg); /* "TimeZone" */
974103
+}
974103
+
974103
+void
974103
+e_ews_cal_utils_prepare_free_busy_request (ESoapMessage *msg,
974103
+					   gpointer user_data)
974103
+{
974103
+	const EEWSFreeBusyData *fbdata = user_data;
974103
+	icaltimetype t_start, t_end;
974103
+	icaltimezone *utc_zone = icaltimezone_get_utc_timezone ();
974103
+	GSList *link;
974103
+
974103
+	g_return_if_fail (fbdata != NULL);
974103
+
974103
+	ewscal_set_availability_timezone (msg, utc_zone);
974103
+
974103
+	e_soap_message_start_element (msg, "MailboxDataArray", "messages", NULL);
974103
+
974103
+	for (link = (GSList *) fbdata->user_mails; link; link = g_slist_next (link)) {
974103
+		const gchar *mail = link->data;
974103
+
974103
+		e_soap_message_start_element (msg, "MailboxData", NULL, NULL);
974103
+
974103
+		e_soap_message_start_element (msg, "Email", NULL, NULL);
974103
+		e_ews_message_write_string_parameter (msg, "Address", NULL, mail);
974103
+		e_soap_message_end_element (msg); /* "Email" */
974103
+
974103
+		e_ews_message_write_string_parameter (msg, "AttendeeType", NULL, "Required");
974103
+		e_ews_message_write_string_parameter (msg, "ExcludeConflicts", NULL, "false");
974103
+
974103
+		e_soap_message_end_element (msg); /* "MailboxData" */
974103
+	}
974103
+
974103
+	e_soap_message_end_element (msg); /* "MailboxDataArray" */
974103
+
974103
+	e_soap_message_start_element (msg, "FreeBusyViewOptions", NULL, NULL);
974103
+
974103
+	e_soap_message_start_element (msg, "TimeWindow", NULL, NULL);
974103
+	t_start = icaltime_from_timet_with_zone (fbdata->period_start, 0, utc_zone);
974103
+	t_end = icaltime_from_timet_with_zone (fbdata->period_end, 0, utc_zone);
974103
+	e_ews_cal_utils_set_time (msg, "StartTime", &t_start, FALSE);
974103
+	e_ews_cal_utils_set_time (msg, "EndTime", &t_end, FALSE);
974103
+	e_soap_message_end_element (msg); /* "TimeWindow" */
974103
+
974103
+	e_ews_message_write_string_parameter (msg, "MergedFreeBusyIntervalInMinutes", NULL, "60");
974103
+	e_ews_message_write_string_parameter (msg, "RequestedView", NULL, "DetailedMerged");
974103
+
974103
+	e_soap_message_end_element (msg); /* "FreeBusyViewOptions" */
974103
+}
974103
+
974103
+void
974103
+e_ews_cal_utils_set_time (ESoapMessage *msg,
974103
+			  const gchar *name,
974103
+			  icaltimetype *tt,
974103
+			  gboolean with_timezone)
974103
+{
974103
+	gchar *str;
974103
+	gchar *tz_ident = NULL;
974103
+
974103
+	g_return_if_fail (tt != NULL);
974103
+
974103
+	if (with_timezone) {
974103
+		if (tt->is_utc || !tt->zone || tt->zone == icaltimezone_get_utc_timezone ()) {
974103
+			tz_ident = g_strdup ("Z");
974103
+		} else {
974103
+			gint offset, is_daylight, hrs, mins;
974103
+
974103
+			offset = icaltimezone_get_utc_offset (
974103
+				icaltimezone_get_utc_timezone (), tt, &is_daylight);
974103
+
974103
+			offset = offset * (-1);
974103
+			hrs = offset / 60;
974103
+			mins = offset % 60;
974103
+
974103
+			if (hrs < 0)
974103
+				hrs *= -1;
974103
+			if (mins < 0)
974103
+				mins *= -1;
974103
+
974103
+			tz_ident = g_strdup_printf ("%s%02d:%02d", offset > 0 ? "+" : "-", hrs, mins);
974103
+		}
974103
+	}
974103
+
974103
+	str = g_strdup_printf (
974103
+		"%04d-%02d-%02dT%02d:%02d:%02d%s",
974103
+		tt->year, tt->month, tt->day,
974103
+		tt->hour, tt->minute, tt->second,
974103
+		tz_ident ? tz_ident : "");
974103
+
974103
+	e_ews_message_write_string_parameter (msg, name, NULL, str);
974103
+
974103
+	g_free (tz_ident);
974103
+	g_free (str);
974103
+}
974103
diff -up evolution-ews-3.22.6/src/server/e-ews-calendar-utils.h.free-busy-calendar evolution-ews-3.22.6/src/server/e-ews-calendar-utils.h
974103
--- evolution-ews-3.22.6/src/server/e-ews-calendar-utils.h.free-busy-calendar	2017-05-24 15:38:44.190519183 +0200
974103
+++ evolution-ews-3.22.6/src/server/e-ews-calendar-utils.h	2017-05-24 15:38:44.190519183 +0200
974103
@@ -0,0 +1,46 @@
974103
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
974103
+/*
974103
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
974103
+ *
974103
+ * This program is free software; you can redistribute it and/or
974103
+ * modify it under the terms of version 2 of the GNU Lesser General Public
974103
+ * License as published by the Free Software Foundation.
974103
+ *
974103
+ * This program is distributed in the hope that it will be useful,
974103
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
974103
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
974103
+ * GNU Lesser General Public License for more details.
974103
+ *
974103
+ * You should have received a copy of the GNU Lesser General Public License
974103
+ * along with this program; if not, write to the Free Software
974103
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
974103
+ * USA
974103
+ */
974103
+
974103
+#ifndef E_EWS_CALENDAR_UTILS_H
974103
+#define E_EWS_CALENDAR_UTILS_H
974103
+
974103
+#include <time.h>
974103
+#include <libical/ical.h>
974103
+
974103
+#include "server/e-soap-message.h"
974103
+
974103
+G_BEGIN_DECLS
974103
+
974103
+typedef struct _EEWSFreeBusyData {
974103
+	time_t period_start;
974103
+	time_t period_end;
974103
+	GSList *user_mails; /* gchar * */
974103
+} EEWSFreeBusyData;
974103
+
974103
+void		e_ews_cal_utils_prepare_free_busy_request
974103
+						(ESoapMessage *msg,
974103
+						 gpointer user_data); /* EEWSFreeBusyData * */
974103
+void		e_ews_cal_utils_set_time	(ESoapMessage *msg,
974103
+						 const gchar *name,
974103
+						 icaltimetype *tt,
974103
+						 gboolean with_timezone);
974103
+
974103
+G_END_DECLS
974103
+
974103
+#endif /* E_EWS_CALENDAR_UTILS_H */
974103
diff -up evolution-ews-3.22.6/src/server/e-ews-connection.c.free-busy-calendar evolution-ews-3.22.6/src/server/e-ews-connection.c
974103
--- evolution-ews-3.22.6/src/server/e-ews-connection.c.free-busy-calendar	2017-05-24 15:38:44.183519217 +0200
974103
+++ evolution-ews-3.22.6/src/server/e-ews-connection.c	2017-05-24 15:38:44.191519178 +0200
974103
@@ -7316,13 +7316,15 @@ ews_handle_free_busy_view (ESoapParamete
974103
 	ESoapParameter *viewparam, *eventarray, *event_param, *subparam;
974103
 	GTimeVal t_val;
974103
 	const gchar *name;
974103
-	gchar *value, *new_val = NULL, *summary = NULL, *location = NULL;
974103
+	gchar *value, *new_val = NULL, *summary = NULL, *location = NULL, *id = NULL;
974103
 
974103
 	viewparam = e_soap_parameter_get_first_child_by_name (param, "FreeBusyView");
974103
 	if (!viewparam) return;
974103
 	vfb = icalcomponent_new_vfreebusy ();
974103
 	eventarray = e_soap_parameter_get_first_child_by_name (viewparam, "CalendarEventArray");
974103
-	for (event_param = e_soap_parameter_get_first_child (eventarray); event_param != NULL; event_param = e_soap_parameter_get_next_child (event_param), icalprop = NULL) {
974103
+	for (event_param = eventarray ? e_soap_parameter_get_first_child (eventarray) : NULL;
974103
+	     event_param != NULL;
974103
+	     event_param = e_soap_parameter_get_next_child (event_param), icalprop = NULL) {
974103
 		for (subparam = e_soap_parameter_get_first_child (event_param); subparam != NULL; subparam = e_soap_parameter_get_next_child (subparam)) {
974103
 			name = e_soap_parameter_get_name (subparam);
974103
 
974103
@@ -7379,6 +7381,10 @@ ews_handle_free_busy_view (ESoapParamete
974103
 			} else if (!g_ascii_strcasecmp (name, "CalendarEventDetails")) {
974103
 				ESoapParameter *dparam;
974103
 
974103
+				dparam = e_soap_parameter_get_first_child_by_name (subparam, "ID");
974103
+				if (dparam)
974103
+					id = e_soap_parameter_get_string_value (dparam);
974103
+
974103
 				dparam = e_soap_parameter_get_first_child_by_name (subparam, "Subject");
974103
 				if (dparam)
974103
 					summary = e_soap_parameter_get_string_value (dparam);
974103
@@ -7389,6 +7395,8 @@ ews_handle_free_busy_view (ESoapParamete
974103
 			}
974103
 		}
974103
 		if (icalprop != NULL) {
974103
+			if (id)
974103
+				icalproperty_set_parameter_from_string (icalprop, "X-EWS-ID", id);
974103
 			if (summary)
974103
 				icalproperty_set_parameter_from_string (icalprop, "X-SUMMARY", summary);
974103
 			if (location)
974103
@@ -7396,10 +7404,9 @@ ews_handle_free_busy_view (ESoapParamete
974103
 			icalcomponent_add_property (vfb, icalprop);
974103
 		}
974103
 
974103
-		g_free (summary);
974103
-		g_free (location);
974103
-		summary = NULL;
974103
-		location = NULL;
974103
+		g_clear_pointer (&summary, g_free);
974103
+		g_clear_pointer (&location, g_free);
974103
+		g_clear_pointer (&id, g_free);
974103
 	}
974103
 
974103
 	async_data->items = g_slist_append (async_data->items, vfb);
974103
diff -up evolution-ews-3.22.6/src/server/e-ews-folder.c.free-busy-calendar evolution-ews-3.22.6/src/server/e-ews-folder.c
974103
--- evolution-ews-3.22.6/src/server/e-ews-folder.c.free-busy-calendar	2015-05-22 13:47:17.000000000 +0200
974103
+++ evolution-ews-3.22.6/src/server/e-ews-folder.c	2017-05-24 15:38:44.192519174 +0200
974103
@@ -47,6 +47,7 @@ struct _EEwsFolderPrivate {
974103
 	guint32 child_count;
974103
 	guint64 size;
974103
 	gboolean foreign;
974103
+	gchar *foreign_mail;
974103
 };
974103
 
974103
 static void
974103
@@ -70,14 +71,9 @@ e_ews_folder_finalize (GObject *object)
974103
 	priv = folder->priv;
974103
 
974103
 	g_clear_error (&priv->error);
974103
-
974103
-	if (priv->name) {
974103
-		g_free (priv->name);
974103
-		priv->name = NULL;
974103
-	}
974103
-
974103
-	g_free (priv->escaped_name);
974103
-	priv->escaped_name = NULL;
974103
+	g_clear_pointer (&priv->name, g_free);
974103
+	g_clear_pointer (&priv->escaped_name, g_free);
974103
+	g_clear_pointer (&priv->foreign_mail, g_free);
974103
 
974103
 	if (priv->fid) {
974103
 		g_free (priv->fid->id);
974103
@@ -409,6 +405,16 @@ e_ews_folder_get_id (const EEwsFolder *f
974103
 	return (const EwsFolderId *) folder->priv->fid;
974103
 }
974103
 
974103
+void
974103
+e_ews_folder_set_id (EEwsFolder *folder,
974103
+		     EwsFolderId *fid)
974103
+{
974103
+	g_return_if_fail (E_IS_EWS_FOLDER (folder));
974103
+
974103
+	e_ews_folder_id_free (folder->priv->fid);
974103
+	folder->priv->fid = fid;
974103
+}
974103
+
974103
 const EwsFolderId *
974103
 e_ews_folder_get_parent_id (const EEwsFolder *folder)
974103
 {
974103
@@ -503,6 +509,24 @@ e_ews_folder_set_foreign (EEwsFolder *fo
974103
 	folder->priv->foreign = is_foreign;
974103
 }
974103
 
974103
+const gchar *
974103
+e_ews_folder_get_foreign_mail (const EEwsFolder *folder)
974103
+{
974103
+	g_return_val_if_fail (E_IS_EWS_FOLDER (folder), NULL);
974103
+
974103
+	return folder->priv->foreign_mail;
974103
+}
974103
+
974103
+void
974103
+e_ews_folder_set_foreign_mail (EEwsFolder *folder,
974103
+			       const gchar *foreign_mail)
974103
+{
974103
+	g_return_if_fail (E_IS_EWS_FOLDER (folder));
974103
+
974103
+	g_free (folder->priv->foreign_mail);
974103
+	folder->priv->foreign_mail = g_strdup (foreign_mail);
974103
+}
974103
+
974103
 /* escapes backslashes with \5C and forward slashes with \2F */
974103
 gchar *
974103
 e_ews_folder_utils_escape_name (const gchar *folder_name)
974103
@@ -678,6 +702,7 @@ e_ews_folder_utils_populate_esource (ESo
974103
 			e_source_ews_folder_set_change_key (folder_ext, NULL);
974103
 			e_source_ews_folder_set_foreign (folder_ext, e_ews_folder_get_foreign (folder));
974103
 			e_source_ews_folder_set_foreign_subfolders (folder_ext, (flags & E_EWS_ESOURCE_FLAG_INCLUDE_SUBFOLDERS) != 0);
974103
+			e_source_ews_folder_set_foreign_mail (folder_ext, e_ews_folder_get_foreign_mail (folder));
974103
 			e_source_ews_folder_set_public (folder_ext, (flags & E_EWS_ESOURCE_FLAG_PUBLIC_FOLDER) != 0);
974103
 
974103
 			offline_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_OFFLINE);
974103
diff -up evolution-ews-3.22.6/src/server/e-ews-folder.h.free-busy-calendar evolution-ews-3.22.6/src/server/e-ews-folder.h
974103
--- evolution-ews-3.22.6/src/server/e-ews-folder.h.free-busy-calendar	2014-11-19 19:06:36.000000000 +0100
974103
+++ evolution-ews-3.22.6/src/server/e-ews-folder.h	2017-05-24 15:38:44.192519174 +0200
974103
@@ -69,6 +69,7 @@ const EwsFolderId *
974103
 		e_ews_folder_get_parent_id (const EEwsFolder *folder);
974103
 const EwsFolderId *
974103
 		e_ews_folder_get_id (const EEwsFolder *folder);
974103
+void		e_ews_folder_set_id (EEwsFolder *folder, EwsFolderId *fid);
974103
 guint32		e_ews_folder_get_total_count (const EEwsFolder *folder);
974103
 guint32		e_ews_folder_get_unread_count (const EEwsFolder *folder);
974103
 guint32		e_ews_folder_get_child_count (const EEwsFolder *folder);
974103
@@ -79,6 +80,8 @@ EEwsFolderType	e_ews_folder_get_folder_t
974103
 void		e_ews_folder_set_folder_type (EEwsFolder *folder, EEwsFolderType folder_type);
974103
 gboolean	e_ews_folder_get_foreign (const EEwsFolder *folder);
974103
 void		e_ews_folder_set_foreign (EEwsFolder *folder, gboolean is_foreign);
974103
+const gchar *	e_ews_folder_get_foreign_mail (const EEwsFolder *folder);
974103
+void		e_ews_folder_set_foreign_mail (EEwsFolder *folder, const gchar *foreign_mail);
974103
 
974103
 EwsFolderId *	e_ews_folder_id_new (const gchar *id,
974103
 				     const gchar *change_key,
974103
diff -up evolution-ews-3.22.6/src/server/e-source-ews-folder.c.free-busy-calendar evolution-ews-3.22.6/src/server/e-source-ews-folder.c
974103
--- evolution-ews-3.22.6/src/server/e-source-ews-folder.c.free-busy-calendar	2015-09-21 11:59:31.000000000 +0200
974103
+++ evolution-ews-3.22.6/src/server/e-source-ews-folder.c	2017-05-24 15:38:44.192519174 +0200
974103
@@ -31,7 +31,10 @@ struct _ESourceEwsFolderPrivate {
974103
 	gchar *id;
974103
 	gboolean foreign;
974103
 	gboolean foreign_subfolders;
974103
+	gchar *foreign_mail;
974103
 	gboolean is_public;
974103
+	guint freebusy_weeks_before;
974103
+	guint freebusy_weeks_after;
974103
 };
974103
 
974103
 enum {
974103
@@ -40,6 +43,9 @@ enum {
974103
 	PROP_ID,
974103
 	PROP_FOREIGN,
974103
 	PROP_FOREIGN_SUBFOLDERS,
974103
+	PROP_FOREIGN_MAIL,
974103
+	PROP_FREEBUSY_WEEKS_BEFORE,
974103
+	PROP_FREEBUSY_WEEKS_AFTER,
974103
 	PROP_PUBLIC
974103
 };
974103
 
974103
@@ -79,6 +85,24 @@ source_ews_folder_set_property (GObject
974103
 				g_value_get_boolean (value));
974103
 			return;
974103
 
974103
+		case PROP_FOREIGN_MAIL:
974103
+			e_source_ews_folder_set_foreign_mail (
974103
+				E_SOURCE_EWS_FOLDER (object),
974103
+				g_value_get_string (value));
974103
+			return;
974103
+
974103
+		case PROP_FREEBUSY_WEEKS_BEFORE:
974103
+			e_source_ews_folder_set_freebusy_weeks_before (
974103
+				E_SOURCE_EWS_FOLDER (object),
974103
+				g_value_get_uint (value));
974103
+			return;
974103
+
974103
+		case PROP_FREEBUSY_WEEKS_AFTER:
974103
+			e_source_ews_folder_set_freebusy_weeks_after (
974103
+				E_SOURCE_EWS_FOLDER (object),
974103
+				g_value_get_uint (value));
974103
+			return;
974103
+
974103
 		case PROP_PUBLIC:
974103
 			e_source_ews_folder_set_public (
974103
 				E_SOURCE_EWS_FOLDER (object),
974103
@@ -124,6 +148,27 @@ source_ews_folder_get_property (GObject
974103
 				E_SOURCE_EWS_FOLDER (object)));
974103
 			return;
974103
 
974103
+		case PROP_FOREIGN_MAIL:
974103
+			g_value_take_string (
974103
+				value,
974103
+				e_source_ews_folder_dup_foreign_mail (
974103
+				E_SOURCE_EWS_FOLDER (object)));
974103
+			return;
974103
+
974103
+		case PROP_FREEBUSY_WEEKS_BEFORE:
974103
+			g_value_set_uint (
974103
+				value,
974103
+				e_source_ews_folder_get_freebusy_weeks_before (
974103
+				E_SOURCE_EWS_FOLDER (object)));
974103
+			return;
974103
+
974103
+		case PROP_FREEBUSY_WEEKS_AFTER:
974103
+			g_value_set_uint (
974103
+				value,
974103
+				e_source_ews_folder_get_freebusy_weeks_after (
974103
+				E_SOURCE_EWS_FOLDER (object)));
974103
+			return;
974103
+
974103
 		case PROP_PUBLIC:
974103
 			g_value_set_boolean (
974103
 				value,
974103
@@ -144,6 +189,7 @@ source_ews_folder_finalize (GObject *obj
974103
 
974103
 	g_free (priv->change_key);
974103
 	g_free (priv->id);
974103
+	g_free (priv->foreign_mail);
974103
 
974103
 	/* Chain up to parent's finalize() method. */
974103
 	G_OBJECT_CLASS (e_source_ews_folder_parent_class)->finalize (object);
974103
@@ -220,6 +266,45 @@ e_source_ews_folder_class_init (ESourceE
974103
 
974103
 	g_object_class_install_property (
974103
 		object_class,
974103
+		PROP_FOREIGN_MAIL,
974103
+		g_param_spec_string (
974103
+			"foreign-mail",
974103
+			"ForeignMail",
974103
+			"Other user's mail address",
974103
+			NULL,
974103
+			G_PARAM_READWRITE |
974103
+			G_PARAM_CONSTRUCT |
974103
+			G_PARAM_STATIC_STRINGS |
974103
+			E_SOURCE_PARAM_SETTING));
974103
+
974103
+	g_object_class_install_property (
974103
+		object_class,
974103
+		PROP_FREEBUSY_WEEKS_BEFORE,
974103
+		g_param_spec_uint (
974103
+			"freebusy-weeks-before",
974103
+			"FreeBusyWeeksBefore",
974103
+			"How many weeks to read Free/Busy before today",
974103
+			0, 5, 1,
974103
+			G_PARAM_READWRITE |
974103
+			G_PARAM_CONSTRUCT |
974103
+			G_PARAM_STATIC_STRINGS |
974103
+			E_SOURCE_PARAM_SETTING));
974103
+
974103
+	g_object_class_install_property (
974103
+		object_class,
974103
+		PROP_FREEBUSY_WEEKS_AFTER,
974103
+		g_param_spec_uint (
974103
+			"freebusy-weeks-after",
974103
+			"FreeBusyWeeksAfter",
974103
+			"How many weeks to read Free/Busy after today",
974103
+			1, 54, 5,
974103
+			G_PARAM_READWRITE |
974103
+			G_PARAM_CONSTRUCT |
974103
+			G_PARAM_STATIC_STRINGS |
974103
+			E_SOURCE_PARAM_SETTING));
974103
+
974103
+	g_object_class_install_property (
974103
+		object_class,
974103
 		PROP_PUBLIC,
974103
 		g_param_spec_boolean (
974103
 			"public",
974103
@@ -402,6 +487,97 @@ e_source_ews_folder_set_foreign_subfolde
974103
 	g_object_notify (G_OBJECT (extension), "foreign-subfolders");
974103
 }
974103
 
974103
+const gchar *
974103
+e_source_ews_folder_get_foreign_mail (ESourceEwsFolder *extension)
974103
+{
974103
+	g_return_val_if_fail (E_IS_SOURCE_EWS_FOLDER (extension), NULL);
974103
+
974103
+	return extension->priv->foreign_mail;
974103
+}
974103
+
974103
+gchar *
974103
+e_source_ews_folder_dup_foreign_mail (ESourceEwsFolder *extension)
974103
+{
974103
+	const gchar *protected;
974103
+	gchar *duplicate;
974103
+
974103
+	g_return_val_if_fail (E_IS_SOURCE_EWS_FOLDER (extension), NULL);
974103
+
974103
+	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
974103
+
974103
+	protected = e_source_ews_folder_get_foreign_mail (extension);
974103
+	duplicate = g_strdup (protected);
974103
+
974103
+	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
974103
+
974103
+	return duplicate;
974103
+}
974103
+
974103
+void
974103
+e_source_ews_folder_set_foreign_mail (ESourceEwsFolder *extension,
974103
+				      const gchar *foreign_mail)
974103
+{
974103
+	g_return_if_fail (E_IS_SOURCE_EWS_FOLDER (extension));
974103
+
974103
+	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
974103
+
974103
+	if (g_strcmp0 (extension->priv->foreign_mail, foreign_mail) == 0) {
974103
+		e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
974103
+		return;
974103
+	}
974103
+
974103
+	g_free (extension->priv->foreign_mail);
974103
+	extension->priv->foreign_mail = g_strdup (foreign_mail);
974103
+
974103
+	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
974103
+
974103
+	g_object_notify (G_OBJECT (extension), "foreign-mail");
974103
+}
974103
+
974103
+guint
974103
+e_source_ews_folder_get_freebusy_weeks_before (ESourceEwsFolder *extension)
974103
+{
974103
+	g_return_val_if_fail (E_IS_SOURCE_EWS_FOLDER (extension), 0);
974103
+
974103
+	return extension->priv->freebusy_weeks_before;
974103
+}
974103
+
974103
+void
974103
+e_source_ews_folder_set_freebusy_weeks_before (ESourceEwsFolder *extension,
974103
+					       guint freebusy_weeks_before)
974103
+{
974103
+	g_return_if_fail (E_IS_SOURCE_EWS_FOLDER (extension));
974103
+
974103
+	if (extension->priv->freebusy_weeks_before == freebusy_weeks_before)
974103
+		return;
974103
+
974103
+	extension->priv->freebusy_weeks_before = freebusy_weeks_before;
974103
+
974103
+	g_object_notify (G_OBJECT (extension), "freebusy-weeks-before");
974103
+}
974103
+
974103
+guint
974103
+e_source_ews_folder_get_freebusy_weeks_after (ESourceEwsFolder *extension)
974103
+{
974103
+	g_return_val_if_fail (E_IS_SOURCE_EWS_FOLDER (extension), 0);
974103
+
974103
+	return extension->priv->freebusy_weeks_after;
974103
+}
974103
+
974103
+void
974103
+e_source_ews_folder_set_freebusy_weeks_after (ESourceEwsFolder *extension,
974103
+					      guint freebusy_weeks_after)
974103
+{
974103
+	g_return_if_fail (E_IS_SOURCE_EWS_FOLDER (extension));
974103
+
974103
+	if (extension->priv->freebusy_weeks_after == freebusy_weeks_after)
974103
+		return;
974103
+
974103
+	extension->priv->freebusy_weeks_after = freebusy_weeks_after;
974103
+
974103
+	g_object_notify (G_OBJECT (extension), "freebusy-weeks-after");
974103
+}
974103
+
974103
 gboolean
974103
 e_source_ews_folder_get_public (ESourceEwsFolder *extension)
974103
 {
974103
diff -up evolution-ews-3.22.6/src/server/e-source-ews-folder.h.free-busy-calendar evolution-ews-3.22.6/src/server/e-source-ews-folder.h
974103
--- evolution-ews-3.22.6/src/server/e-source-ews-folder.h.free-busy-calendar	2014-03-24 10:28:36.000000000 +0100
974103
+++ evolution-ews-3.22.6/src/server/e-source-ews-folder.h	2017-05-24 15:38:44.192519174 +0200
974103
@@ -84,6 +84,23 @@ gboolean	e_source_ews_folder_get_foreign
974103
 void		e_source_ews_folder_set_foreign_subfolders
974103
 						(ESourceEwsFolder *extension,
974103
 						 gboolean foreign_subfolders);
974103
+const gchar *	e_source_ews_folder_get_foreign_mail
974103
+						(ESourceEwsFolder *extension);
974103
+gchar *		e_source_ews_folder_dup_foreign_mail
974103
+						(ESourceEwsFolder *extension);
974103
+void		e_source_ews_folder_set_foreign_mail
974103
+						(ESourceEwsFolder *extension,
974103
+						 const gchar *foreign_mail);
974103
+guint		e_source_ews_folder_get_freebusy_weeks_before
974103
+						(ESourceEwsFolder *extension);
974103
+void		e_source_ews_folder_set_freebusy_weeks_before
974103
+						(ESourceEwsFolder *extension,
974103
+						 guint freebusy_weeks_before);
974103
+guint		e_source_ews_folder_get_freebusy_weeks_after
974103
+						(ESourceEwsFolder *extension);
974103
+void		e_source_ews_folder_set_freebusy_weeks_after
974103
+						(ESourceEwsFolder *extension,
974103
+						 guint freebusy_weeks_after);
974103
 gboolean	e_source_ews_folder_get_public	(ESourceEwsFolder *extension);
974103
 void		e_source_ews_folder_set_public	(ESourceEwsFolder *extension,
974103
 						 gboolean is_public);
974103
diff -up evolution-ews-3.22.6/src/server/Makefile.am.free-busy-calendar evolution-ews-3.22.6/src/server/Makefile.am
974103
--- evolution-ews-3.22.6/src/server/Makefile.am.free-busy-calendar	2016-09-26 23:54:19.000000000 +0200
974103
+++ evolution-ews-3.22.6/src/server/Makefile.am	2017-05-24 15:38:44.190519183 +0200
974103
@@ -41,6 +41,8 @@ libeews_1_2_la_SOURCES = \
974103
 	camel-ews-settings.c \
974103
 	ews-errors.h \
974103
 	ews-errors.c \
974103
+	e-ews-calendar-utils.c \
974103
+	e-ews-calendar-utils.h \
974103
 	e-ews-connection.c \
974103
 	e-ews-connection.h \
974103
 	e-ews-connection-utils.c \