[evolution-ews/wip/get_server_time_zones: 4/6] Move functions from e-cal-backend.c to ews-cal-backend-utils.[ch]



commit ff322e5dae1ccb5aa97c05d23cabff657a6c3e0c
Author: Fabiano Fidêncio <fidencio redhat com>
Date:   Mon Jan 6 15:02:29 2014 +0100

    Move functions from e-cal-backend.c to ews-cal-backend-utils.[ch]
    
    This code refactoring has the motivation we can re-use a lot of
    internal code in our tests, avoiding duplication.

 src/calendar/e-cal-backend-ews-utils.c |  980 +++++++++++++++++++
 src/calendar/e-cal-backend-ews-utils.h |   33 +
 src/calendar/e-cal-backend-ews.c       | 1641 +++++++-------------------------
 src/calendar/e-cal-backend-ews.h       |    9 +
 4 files changed, 1392 insertions(+), 1271 deletions(-)
---
diff --git a/src/calendar/e-cal-backend-ews-utils.c b/src/calendar/e-cal-backend-ews-utils.c
index 601c73c..5469119 100644
--- a/src/calendar/e-cal-backend-ews-utils.c
+++ b/src/calendar/e-cal-backend-ews-utils.c
@@ -39,6 +39,7 @@
 
 #include "server/e-ews-connection.h"
 #include "server/e-ews-message.h"
+#include "server/e-ews-item-change.h"
 
 #include "e-cal-backend-ews-utils.h"
 
@@ -670,6 +671,37 @@ e_cal_backend_ews_unref_tz_msdn_to_ical (void)
        g_rec_mutex_unlock (&tz_mutex);
 }
 
+EwsCalendarConvertData *
+ews_calendar_convert_data_new (void)
+{
+       return g_new0 (EwsCalendarConvertData, 1);
+}
+
+void
+ews_calendar_convert_data_free (EwsCalendarConvertData *convert_data)
+{
+       if (convert_data != NULL) {
+               if (convert_data->connection != NULL)
+                       g_object_unref (convert_data->connection);
+               if (convert_data->comp != NULL)
+                       g_object_unref (convert_data->comp);
+               if (convert_data->old_comp != NULL)
+                       g_object_unref (convert_data->old_comp);
+               if (convert_data->default_zone != NULL)
+                       icaltimezone_free (convert_data->default_zone, TRUE);
+               if (convert_data->icalcomp != NULL)
+                       icalcomponent_free (convert_data->icalcomp);
+
+               g_free (convert_data->item_id);
+               g_free (convert_data->change_key);
+               g_free (convert_data->user_email);
+               g_free (convert_data->response_type);
+               g_slist_free_full (convert_data->users, g_free);
+
+               g_free (convert_data);
+       }
+}
+
 /*
  * Iterate over the icalcomponent properties and collect attendees
  */
@@ -1587,3 +1619,951 @@ e_ews_clean_icalcomponent (icalcomponent *icalcomp)
        if (changekey_prop != NULL)
                icalcomponent_remove_property (icalcomp, changekey_prop);
 }
+
+static void
+add_attendees_list_to_message (ESoapMessage *msg,
+                               const gchar *listname,
+                               GSList *list)
+{
+       GSList *item;
+
+       e_soap_message_start_element (msg, listname, NULL, NULL);
+
+       for (item = list; item != NULL; item = item->next) {
+               e_soap_message_start_element (msg, "Attendee", NULL, NULL);
+               e_soap_message_start_element (msg, "Mailbox", NULL, NULL);
+
+               e_ews_message_write_string_parameter (msg, "EmailAddress", NULL, item->data);
+
+               e_soap_message_end_element (msg); /* "Mailbox" */
+               e_soap_message_end_element (msg); /* "Attendee" */
+       }
+
+       e_soap_message_end_element (msg);
+}
+
+static void
+convert_sensitivity_calcomp_to_xml (ESoapMessage *msg,
+                                   icalcomponent *icalcomp)
+{
+       icalproperty *prop;
+
+       g_return_if_fail (msg != NULL);
+       g_return_if_fail (icalcomp != NULL);
+
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
+       if (prop) {
+               icalproperty_class classify = icalproperty_get_class (prop);
+               if (classify == ICAL_CLASS_PUBLIC) {
+                       e_ews_message_write_string_parameter (msg, "Sensitivity", NULL, "Normal");
+               } else if (classify == ICAL_CLASS_PRIVATE) {
+                       e_ews_message_write_string_parameter (msg, "Sensitivity", NULL, "Private");
+               } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
+                       e_ews_message_write_string_parameter (msg, "Sensitivity", NULL, "Personal");
+               }
+       }
+}
+
+static void
+convert_categories_calcomp_to_xml (ESoapMessage *msg,
+                                  ECalComponent *comp,
+                                  icalcomponent *icalcomp)
+{
+       GSList *categ_list, *citer;
+
+       g_return_if_fail (msg != NULL);
+       g_return_if_fail (icalcomp != NULL);
+
+       if (comp) {
+               g_object_ref (comp);
+       } else {
+               icalcomponent *clone = icalcomponent_new_clone (icalcomp);
+
+               comp = e_cal_component_new ();
+               if (!e_cal_component_set_icalcomponent (comp, clone)) {
+                       icalcomponent_free (clone);
+                       g_object_unref (comp);
+
+                       return;
+               }
+       }
+
+       e_cal_component_get_categories_list (comp, &categ_list);
+
+       g_object_unref (comp);
+
+       if (!categ_list)
+               return;
+
+       e_soap_message_start_element (msg, "Categories", NULL, NULL);
+
+       for (citer = categ_list; citer;  citer = g_slist_next (citer)) {
+               const gchar *category = citer->data;
+
+               if (!category || !*category)
+                       continue;
+
+               e_ews_message_write_string_parameter (msg, "String", NULL, category);
+       }
+
+       e_soap_message_end_element (msg); /* Categories */
+
+       e_cal_component_free_categories_list (categ_list);
+}
+
+static void
+convert_vevent_calcomp_to_xml (ESoapMessage *msg,
+                               gpointer user_data)
+{
+       EwsCalendarConvertData *convert_data = user_data;
+       icalcomponent *icalcomp = convert_data->icalcomp;
+       ECalComponent *comp = e_cal_component_new ();
+       GSList *required = NULL, *optional = NULL, *resource = NULL;
+       icaltimetype dtstart, dtend;
+       icalproperty *prop;
+       gboolean has_alarms;
+       const gchar *value;
+
+       e_cal_component_set_icalcomponent (comp, icalcomp);
+
+       /* FORMAT OF A SAMPLE SOAP MESSAGE: http://msdn.microsoft.com/en-us/library/aa564690.aspx */
+
+       /* Prepare CalendarItem node in the SOAP message */
+       e_soap_message_start_element (msg, "CalendarItem", NULL, NULL);
+
+       /* subject */
+       value = icalcomponent_get_summary (icalcomp);
+       if (value)
+               e_ews_message_write_string_parameter (msg, "Subject", NULL, value);
+
+       convert_sensitivity_calcomp_to_xml (msg, icalcomp);
+
+       /* description */
+       value = icalcomponent_get_description (icalcomp);
+       if (value)
+               e_ews_message_write_string_parameter_with_attribute (msg, "Body", NULL, value, "BodyType", 
"Text");
+
+       convert_categories_calcomp_to_xml (msg, comp, icalcomp);
+
+       /* set alarms */
+       has_alarms = e_cal_component_has_alarms (comp);
+       if (has_alarms)
+               ews_set_alarm (msg, comp);
+       else
+               e_ews_message_write_string_parameter (msg, "ReminderIsSet", NULL, "false");
+
+       /* start time, end time and meeting time zone */
+       dtstart = icalcomponent_get_dtstart (icalcomp);
+       dtend = icalcomponent_get_dtend (icalcomp);
+
+       ewscal_set_time (msg, "Start", &dtstart, FALSE);
+       ewscal_set_time (msg, "End", &dtend, FALSE);
+       /* We have to do the time zone(s) later, or the server rejects the request */
+
+       /* All day event ? */
+       if (icaltime_is_date (dtstart))
+               e_ews_message_write_string_parameter (msg, "IsAllDayEvent", NULL, "true");
+
+       /*freebusy*/
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_TRANSP_PROPERTY);
+       if (!g_strcmp0 (icalproperty_get_value_as_string (prop), "TRANSPARENT"))
+               e_ews_message_write_string_parameter (msg, "LegacyFreeBusyStatus",NULL,"Free");
+       else
+               e_ews_message_write_string_parameter (msg, "LegacyFreeBusyStatus",NULL,"Busy");
+
+       /* location */
+       value = icalcomponent_get_location (icalcomp);
+       if (value)
+               e_ews_message_write_string_parameter (msg, "Location", NULL, value);
+
+       /* collect attendees */
+       e_ews_collect_attendees (icalcomp, &required, &optional, &resource);
+
+       if (required != NULL) {
+               add_attendees_list_to_message (msg, "RequiredAttendees", required);
+               g_slist_free (required);
+       }
+       if (optional != NULL) {
+               add_attendees_list_to_message (msg, "OptionalAttendees", optional);
+               g_slist_free (optional);
+       }
+       if (resource != NULL) {
+               add_attendees_list_to_message (msg, "Resources", resource);
+               g_slist_free (resource);
+       }
+       /* end of attendees */
+
+       /* Recurrence */
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
+       if (prop != NULL) {
+               ewscal_set_reccurence (msg, prop, &dtstart);
+       }
+
+       /* We have to cast these because libical puts a const pointer into the
+        * icaltimetype, but its basic read-only icaltimezone_foo() functions
+        * take a non-const pointer! */
+       if (e_ews_connection_satisfies_server_version (convert_data->connection, E_EWS_EXCHANGE_2010)) {
+               const gchar *ical_location;
+               const gchar *msdn_location;
+               icaltimezone *tzid;
+               GSList *msdn_locations = NULL;
+               GSList *tzds = NULL;
+
+               tzid = (icaltimezone *) (dtstart.zone ? dtstart.zone : convert_data->default_zone);
+               ical_location = icaltimezone_get_location (tzid);
+               msdn_location = e_cal_backend_ews_tz_util_get_msdn_equivalent (ical_location);
+
+               msdn_locations = g_slist_prepend (msdn_locations, (gchar *) msdn_location);
+
+               tzid = (icaltimezone *)
+                       (dtend.zone ? dtend.zone : convert_data->default_zone);
+               ical_location = icaltimezone_get_location (tzid);
+               msdn_location = e_cal_backend_ews_tz_util_get_msdn_equivalent (ical_location);
+
+               msdn_locations = g_slist_prepend (msdn_locations, (gchar *) msdn_location);
+
+               msdn_locations = g_slist_reverse (msdn_locations);
+
+               if (e_ews_connection_get_server_time_zones_sync (
+                               convert_data->connection,
+                               EWS_PRIORITY_MEDIUM,
+                               msdn_locations,
+                               &tzds,
+                               NULL,
+                               NULL)) {
+                       ewscal_set_timezone (msg, "StartTimeZone", tzds->data);
+                       ewscal_set_timezone (msg, "EndTimeZone", tzds->data);
+               }
+
+               g_slist_free (msdn_locations);
+               g_slist_free_full (tzds, (GDestroyNotify) e_ews_calendar_time_zone_definition_free);
+       } else {
+               ewscal_set_meeting_timezone (
+                       msg,
+                       (icaltimezone *) (dtstart.zone ? dtstart.zone : convert_data->default_zone));
+       }
+
+       // end of "CalendarItem"
+       e_soap_message_end_element (msg);
+}
+
+static void
+convert_vtodo_calcomp_to_xml (ESoapMessage *msg,
+                              gpointer user_data)
+{
+       EwsCalendarConvertData *convert_data = user_data;
+       icalcomponent *icalcomp = convert_data->icalcomp;
+       icalproperty *prop;
+       icaltimetype dt;
+       gint value;
+       gchar buffer[16];
+
+       e_soap_message_start_element (msg, "Task", NULL, NULL);
+
+       e_ews_message_write_string_parameter (msg, "Subject", NULL, icalcomponent_get_summary (icalcomp));
+
+       convert_sensitivity_calcomp_to_xml (msg, icalcomp);
+
+       e_ews_message_write_string_parameter_with_attribute (msg, "Body", NULL, icalcomponent_get_description 
(icalcomp), "BodyType", "Text");
+
+       convert_categories_calcomp_to_xml (msg, NULL, icalcomp);
+
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_DUE_PROPERTY);
+       if (prop) {
+               dt = icalproperty_get_due (prop);
+               ewscal_set_time (msg, "DueDate", &dt, TRUE);
+       }
+
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
+       if (prop) {
+               value = icalproperty_get_percentcomplete (prop);
+               snprintf (buffer, 16, "%d", value);
+               e_ews_message_write_string_parameter (msg, "PercentComplete", NULL, buffer);
+       }
+
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
+       if (prop) {
+               dt = icalproperty_get_dtstart (prop);
+               ewscal_set_time (msg, "StartDate", &dt, TRUE);
+       }
+
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_STATUS_PROPERTY);
+       if (prop) {
+               switch (icalproperty_get_status (prop)) {
+               case ICAL_STATUS_INPROCESS:
+                       e_ews_message_write_string_parameter (msg, "Status", NULL, "InProgress");
+                       break;
+               case ICAL_STATUS_COMPLETED:
+                       e_ews_message_write_string_parameter (msg, "Status", NULL, "Completed");
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       e_soap_message_end_element (msg); // "Task"
+}
+
+static void
+convert_vjournal_calcomp_to_xml (ESoapMessage *msg,
+                                gpointer user_data)
+{
+       EwsCalendarConvertData *convert_data = user_data;
+       icalcomponent *icalcomp = convert_data->icalcomp;
+       const gchar *text;
+
+       e_soap_message_start_element (msg, "Message", NULL, NULL);
+       e_ews_message_write_string_parameter (msg, "ItemClass", NULL, "IPM.StickyNote");
+
+       e_ews_message_write_string_parameter (msg, "Subject", NULL, icalcomponent_get_summary (icalcomp));
+
+       convert_sensitivity_calcomp_to_xml (msg, icalcomp);
+
+       text = icalcomponent_get_description (icalcomp);
+       if (!text || !*text)
+               text = icalcomponent_get_summary (icalcomp);
+       e_ews_message_write_string_parameter_with_attribute (msg, "Body", NULL, text, "BodyType", "Text");
+
+       convert_categories_calcomp_to_xml (msg, NULL, icalcomp);
+
+       e_soap_message_end_element (msg); /* Message */
+}
+
+void
+e_cal_backend_ews_convert_calcomp_to_xml (ESoapMessage *msg,
+                                         gpointer user_data)
+{
+       EwsCalendarConvertData *convert_data = user_data;
+
+       switch (icalcomponent_isa (convert_data->icalcomp)) {
+       case ICAL_VEVENT_COMPONENT:
+               convert_vevent_calcomp_to_xml (msg, convert_data);
+               break;
+       case ICAL_VTODO_COMPONENT:
+               convert_vtodo_calcomp_to_xml (msg, convert_data);
+               break;
+       case ICAL_VJOURNAL_COMPONENT:
+               convert_vjournal_calcomp_to_xml (msg, convert_data);
+               break;
+       default:
+               g_warn_if_reached ();
+               break;
+       }
+}
+
+static void
+convert_component_categories_to_updatexml (ECalComponent *comp,
+                                          ESoapMessage *msg,
+                                          const gchar *base_elem_name)
+{
+       GSList *categ_list = NULL, *citer;
+
+       g_return_if_fail (comp != NULL);
+       g_return_if_fail (msg != NULL);
+       g_return_if_fail (base_elem_name != NULL);
+
+       e_cal_component_get_categories_list (comp, &categ_list);
+       e_ews_message_start_set_item_field (msg, "Categories", "item", base_elem_name);
+       e_soap_message_start_element (msg, "Categories", NULL, NULL);
+
+       for (citer = categ_list; citer;  citer = g_slist_next (citer)) {
+               const gchar *category = citer->data;
+
+               if (!category || !*category)
+                       continue;
+
+               e_ews_message_write_string_parameter (msg, "String", NULL, category);
+       }
+
+       e_soap_message_end_element (msg); /* Categories */
+       e_ews_message_end_set_item_field (msg);
+
+       e_cal_component_free_categories_list (categ_list);
+}
+
+static void
+convert_vevent_property_to_updatexml (ESoapMessage *msg,
+                                      const gchar *name,
+                                      const gchar *value,
+                                      const gchar *prefix,
+                                      const gchar *attr_name,
+                                      const gchar *attr_value)
+{
+       e_ews_message_start_set_item_field (msg, name, prefix, "CalendarItem");
+       e_ews_message_write_string_parameter_with_attribute (msg, name, NULL, value, attr_name, attr_value);
+       e_ews_message_end_set_item_field (msg);
+}
+
+static void
+convert_vevent_component_to_updatexml (ESoapMessage *msg,
+                                       gpointer user_data)
+{
+       EwsCalendarConvertData *convert_data = user_data;
+       icalcomponent *icalcomp = e_cal_component_get_icalcomponent (convert_data->comp);
+       icalcomponent *icalcomp_old = e_cal_component_get_icalcomponent (convert_data->old_comp);
+       GSList *required = NULL, *optional = NULL, *resource = NULL;
+       icaltimetype dtstart, dtend, dtstart_old, dtend_old;
+       icalproperty *prop, *transp;
+       const gchar *org_email_address = NULL, *value = NULL, *old_value = NULL;
+       gboolean has_alarms, has_alarms_old, dt_changed = FALSE;
+       gint alarm = 0, alarm_old = 0;
+       gchar *recid;
+       GError *error = NULL;
+
+       /* Modifying a recurring meeting ? */
+       if (icalcomponent_get_first_property (icalcomp_old, ICAL_RRULE_PROPERTY) != NULL) {
+               /* A single occurrence ? */
+               prop = icalcomponent_get_first_property (icalcomp, ICAL_RECURRENCEID_PROPERTY);
+               if (prop != NULL) {
+                       recid = icalproperty_get_value_as_string_r (prop);
+                       e_ews_message_start_item_change (
+                               msg,
+                               E_EWS_ITEMCHANGE_TYPE_OCCURRENCEITEM,
+                               convert_data->item_id,
+                               convert_data->change_key,
+                               e_cal_backend_ews_rid_to_index (
+                                       convert_data->default_zone,
+                                       recid,
+                                       icalcomp_old,
+                                       &error));
+                       free (recid);
+               } else {
+                       e_ews_message_start_item_change (
+                               msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
+                               convert_data->item_id, convert_data->change_key, 0);
+               }
+       } else e_ews_message_start_item_change (msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
+               convert_data->item_id, convert_data->change_key, 0);
+
+       /* subject */
+       value = icalcomponent_get_summary (icalcomp);
+       old_value = icalcomponent_get_summary (icalcomp_old);
+       if ((value && old_value && g_ascii_strcasecmp (value, old_value)) ||
+        (value && old_value == NULL)) {
+               convert_vevent_property_to_updatexml (msg, "Subject", value, "item", NULL, NULL);
+       } else if (!value && old_value)
+               convert_vevent_property_to_updatexml (msg, "Subject", "", "item", NULL, NULL);
+
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
+       if (prop) {
+               icalproperty_class classify = icalproperty_get_class (prop);
+               if (classify == ICAL_CLASS_PUBLIC) {
+                       convert_vevent_property_to_updatexml (msg, "Sensitivity", "Normal", "item", NULL, 
NULL);
+               } else if (classify == ICAL_CLASS_PRIVATE) {
+                       convert_vevent_property_to_updatexml (msg, "Sensitivity", "Private", "item", NULL, 
NULL);
+               } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
+                       convert_vevent_property_to_updatexml (msg, "Sensitivity", "Personal", "item", NULL, 
NULL);
+               }
+       }
+
+       /*description*/
+       value = icalcomponent_get_description (icalcomp);
+       old_value = icalcomponent_get_description (icalcomp_old);
+       if ((value && old_value && g_ascii_strcasecmp (value, old_value)) ||
+        (value && old_value == NULL)) {
+               convert_vevent_property_to_updatexml (msg, "Body", value, "item", "BodyType", "Text");
+       } else if (!value && old_value)
+               convert_vevent_property_to_updatexml (msg, "Body", "", "item", "BodyType", "Text");
+
+       /*update alarm items*/
+       has_alarms = e_cal_component_has_alarms (convert_data->comp);
+       if (has_alarms) {
+               alarm = ews_get_alarm (convert_data->comp);
+               has_alarms_old = e_cal_component_has_alarms (convert_data->old_comp);
+               if (has_alarms_old)
+                       alarm_old = ews_get_alarm (convert_data->old_comp);
+               if (!(alarm == alarm_old)) {
+                       gchar buf[20];
+                       snprintf (buf, 20, "%d", alarm);
+                       convert_vevent_property_to_updatexml (msg, "ReminderIsSet", "true", "item", NULL, 
NULL);
+                       convert_vevent_property_to_updatexml (msg, "ReminderMinutesBeforeStart", buf, "item", 
NULL, NULL);
+               }
+       }
+       else convert_vevent_property_to_updatexml (msg, "ReminderIsSet", "false", "item", NULL, NULL);
+
+       /* Categories */
+       convert_component_categories_to_updatexml (convert_data->comp, msg, "CalendarItem");
+
+       /*location*/
+       value = icalcomponent_get_location (icalcomp);
+       old_value = icalcomponent_get_location (icalcomp_old);
+       if ((value && old_value && g_ascii_strcasecmp (value, old_value)) ||
+        (value && old_value == NULL)) {
+               convert_vevent_property_to_updatexml (msg, "Location", value, "calendar", NULL, NULL);
+       } else if (!value && old_value)
+               convert_vevent_property_to_updatexml (msg, "Location", "", "calendar", NULL, NULL);
+
+       /*freebusy*/
+       transp = icalcomponent_get_first_property (icalcomp, ICAL_TRANSP_PROPERTY);
+       value = icalproperty_get_value_as_string (transp);
+       transp = icalcomponent_get_first_property (icalcomp_old, ICAL_TRANSP_PROPERTY);
+       old_value = icalproperty_get_value_as_string (transp);
+       if (g_strcmp0 (value, old_value)) {
+               if (!g_strcmp0 (value, "TRANSPARENT"))
+                       convert_vevent_property_to_updatexml (msg, "LegacyFreeBusyStatus","Free" , 
"calendar", NULL, NULL);
+               else
+                       convert_vevent_property_to_updatexml (msg, "LegacyFreeBusyStatus","Busy" , 
"calendar", NULL, NULL);
+       }
+
+       org_email_address = e_ews_collect_organizer (icalcomp);
+       if (org_email_address && g_ascii_strcasecmp (org_email_address, convert_data->user_email)) {
+               e_ews_message_end_item_change (msg);
+               return;
+       }
+       /* Update other properties allowed only for meeting organizers*/
+       /*meeting dates*/
+       dtstart = icalcomponent_get_dtstart (icalcomp);
+       dtend = icalcomponent_get_dtend (icalcomp);
+       dtstart_old = icalcomponent_get_dtstart (icalcomp_old);
+       dtend_old = icalcomponent_get_dtend (icalcomp_old);
+       if (icaltime_compare (dtstart, dtstart_old) != 0) {
+               e_ews_message_start_set_item_field (msg, "Start", "calendar","CalendarItem");
+               ewscal_set_time (msg, "Start", &dtstart, FALSE);
+               e_ews_message_end_set_item_field (msg);
+               dt_changed = TRUE;
+       }
+
+       if (icaltime_compare (dtend, dtend_old) != 0) {
+               e_ews_message_start_set_item_field (msg, "End", "calendar", "CalendarItem");
+               ewscal_set_time (msg, "End", &dtend, FALSE);
+               e_ews_message_end_set_item_field (msg);
+               dt_changed = TRUE;
+       }
+
+       /*Check for All Day Event*/
+       if (dt_changed) {
+               if (icaltime_is_date (dtstart))
+                       convert_vevent_property_to_updatexml (msg, "IsAllDayEvent", "true", "calendar", NULL, 
NULL);
+               else
+                       convert_vevent_property_to_updatexml (msg, "IsAllDayEvent", "false", "calendar", 
NULL, NULL);
+       }
+
+       /*need to test it*/
+       e_ews_collect_attendees (icalcomp, &required, &optional, &resource);
+       if (required != NULL) {
+               e_ews_message_start_set_item_field (msg, "RequiredAttendees", "calendar", "CalendarItem");
+
+               add_attendees_list_to_message (msg, "RequiredAttendees", required);
+               g_slist_free (required);
+
+               e_ews_message_end_set_item_field (msg);
+       }
+       if (optional != NULL) {
+               e_ews_message_start_set_item_field (msg, "OptionalAttendees", "calendar", "CalendarItem");
+
+               add_attendees_list_to_message (msg, "OptionalAttendees", optional);
+               g_slist_free (optional);
+
+               e_ews_message_end_set_item_field (msg);
+       }
+       if (resource != NULL) {
+               e_ews_message_start_set_item_field (msg, "Resources", "calendar", "CalendarItem");
+
+               add_attendees_list_to_message (msg, "Resources", resource);
+               g_slist_free (resource);
+
+               e_ews_message_end_set_item_field (msg);
+       }
+
+       /* Recurrence */
+       value = NULL; old_value = NULL;
+       prop = icalcomponent_get_first_property (icalcomp_old, ICAL_RRULE_PROPERTY);
+       if (prop != NULL)
+               old_value = icalproperty_get_value_as_string (prop);
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
+       if (prop != NULL)
+               value = icalproperty_get_value_as_string (prop);
+
+       if (prop != NULL && g_strcmp0 (value, old_value)) {
+               e_ews_message_start_set_item_field (msg, "Recurrence", "calendar", "CalendarItem");
+               ewscal_set_reccurence (msg, prop, &dtstart);
+               e_ews_message_end_set_item_field (msg);
+       }
+
+       /* We have to cast these because libical puts a const pointer into the
+        * icaltimetype, but its basic read-only icaltimezone_foo() functions
+        * take a non-const pointer! */
+       if (e_ews_connection_satisfies_server_version (convert_data->connection, E_EWS_EXCHANGE_2010)) {
+               const gchar *ical_location;
+               const gchar *msdn_location;
+               icaltimezone *tzid;
+               GSList *msdn_locations = NULL;
+               GSList *tzds = NULL;
+
+               if (dtstart.zone != NULL) {
+                       tzid = (icaltimezone *) dtstart.zone;
+                       ical_location = icaltimezone_get_location (tzid);
+                       msdn_location = e_cal_backend_ews_tz_util_get_msdn_equivalent (ical_location);
+                       msdn_locations = g_slist_append (msdn_locations, (gchar *) msdn_location);
+               }
+
+               if (dtend.zone != NULL) {
+                       tzid = (icaltimezone *) dtend.zone;
+                       ical_location = icaltimezone_get_location (tzid);
+                       msdn_location = e_cal_backend_ews_tz_util_get_msdn_equivalent (ical_location);
+                       msdn_locations = g_slist_append (msdn_locations, (gchar *) msdn_location);
+               }
+
+               if (e_ews_connection_get_server_time_zones_sync (
+                       convert_data->connection,
+                       EWS_PRIORITY_MEDIUM,
+                       msdn_locations,
+                       &tzds,
+                       NULL,
+                       NULL)) {
+                       GSList *tmp;
+
+                       tmp = tzds;
+                       if (dtstart.zone != NULL) {
+                               e_ews_message_start_set_item_field (msg, "StartTimeZone", "calendar", 
"CalendarItem");
+                               ewscal_set_timezone (msg, "StartTimeZone", tmp->data);
+                               e_ews_message_end_set_item_field (msg);
+
+                               /*
+                                * Exchange server is smart enough to return the list of
+                                * ServerTimeZone without repeated elements
+                                */
+                               if (tmp->next != NULL)
+                                       tmp = tmp->next;
+                       }
+
+                       if (dtend.zone != NULL) {
+                               e_ews_message_start_set_item_field (msg, "EndTimeZone", "calendar", 
"CalendarItem");
+                               ewscal_set_timezone (msg, "EndTimeZone", tmp->data);
+                               e_ews_message_end_set_item_field (msg);
+                       }
+               }
+
+               g_slist_free (msdn_locations);
+               g_slist_free_full (tzds, (GDestroyNotify) e_ews_calendar_time_zone_definition_free);
+       } else {
+               e_ews_message_start_set_item_field (msg, "MeetingTimeZone", "calendar", "CalendarItem");
+               ewscal_set_meeting_timezone (
+                       msg,
+                       (icaltimezone *) (dtstart.zone ? dtstart.zone : convert_data->default_zone));
+               e_ews_message_end_set_item_field (msg);
+       }
+
+       e_ews_message_end_item_change (msg);
+}
+
+static void
+convert_vtodo_property_to_updatexml (ESoapMessage *msg,
+                                     const gchar *name,
+                                     const gchar *value,
+                                     const gchar *prefix,
+                                     const gchar *attr_name,
+                                     const gchar *attr_value)
+{
+       e_ews_message_start_set_item_field (msg, name, prefix, "Task");
+       e_ews_message_write_string_parameter_with_attribute (msg, name, NULL, value, attr_name, attr_value);
+       e_ews_message_end_set_item_field (msg);
+}
+
+static void
+convert_vtodo_component_to_updatexml (ESoapMessage *msg,
+                                      gpointer user_data)
+{
+       EwsCalendarConvertData *convert_data = user_data;
+       icalcomponent *icalcomp = e_cal_component_get_icalcomponent (convert_data->comp);
+       icalproperty *prop;
+       icaltimetype dt;
+       gint value;
+       gchar buffer[16];
+
+       e_ews_message_start_item_change (
+               msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
+               convert_data->item_id, convert_data->change_key, 0);
+
+       convert_vtodo_property_to_updatexml (msg, "Subject", icalcomponent_get_summary (icalcomp), "item", 
NULL, NULL);
+
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
+       if (prop) {
+               icalproperty_class classify = icalproperty_get_class (prop);
+               if (classify == ICAL_CLASS_PUBLIC) {
+                       convert_vtodo_property_to_updatexml (msg, "Sensitivity", "Normal", "item", NULL, 
NULL);
+               } else if (classify == ICAL_CLASS_PRIVATE) {
+                       convert_vtodo_property_to_updatexml (msg, "Sensitivity", "Private", "item", NULL, 
NULL);
+               } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
+                       convert_vtodo_property_to_updatexml (msg, "Sensitivity", "Personal", "item", NULL, 
NULL);
+               }
+       }
+
+       convert_vtodo_property_to_updatexml (msg, "Body", icalcomponent_get_description (icalcomp), "item", 
"BodyType", "Text");
+
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_DUE_PROPERTY);
+       if (prop) {
+               dt = icalproperty_get_due (prop);
+               e_ews_message_start_set_item_field (msg, "DueDate", "task", "Task");
+               ewscal_set_time (msg, "DueDate", &dt, TRUE);
+               e_ews_message_end_set_item_field (msg);
+       } else {
+               e_ews_message_add_delete_item_field (msg, "DueDate", "task");
+       }
+
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
+       if (prop) {
+               value = icalproperty_get_percentcomplete (prop);
+               snprintf (buffer, 16, "%d", value);
+               e_ews_message_start_set_item_field (msg, "PercentComplete", "task", "Task");
+               e_ews_message_write_string_parameter (msg, "PercentComplete", NULL, buffer);
+               e_ews_message_end_set_item_field (msg);
+       }
+
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
+       if (prop) {
+               dt = icalproperty_get_dtstart (prop);
+               e_ews_message_start_set_item_field (msg, "StartDate", "task", "Task");
+               ewscal_set_time (msg, "StartDate", &dt, TRUE);
+               e_ews_message_end_set_item_field (msg);
+       } else {
+               e_ews_message_add_delete_item_field (msg, "StartDate", "task");
+       }
+
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_STATUS_PROPERTY);
+       if (prop) {
+               switch (icalproperty_get_status (prop)) {
+               case ICAL_STATUS_INPROCESS:
+                       convert_vtodo_property_to_updatexml (msg, "Status", "InProgress", "task", NULL, NULL);
+                       break;
+               case ICAL_STATUS_COMPLETED:
+                       convert_vtodo_property_to_updatexml (msg, "Status", "Completed", "task", NULL, NULL);
+                       break;
+               case ICAL_STATUS_NONE:
+               case ICAL_STATUS_NEEDSACTION:
+                       convert_vtodo_property_to_updatexml (msg, "Status", "NotStarted", "task", NULL, NULL);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       /* Categories */
+       convert_component_categories_to_updatexml (convert_data->comp, msg, "Task");
+
+       e_ews_message_end_item_change (msg);
+}
+
+static void
+convert_vjournal_property_to_updatexml (ESoapMessage *msg,
+                                     const gchar *name,
+                                     const gchar *value,
+                                     const gchar *prefix,
+                                     const gchar *attr_name,
+                                     const gchar *attr_value)
+{
+       e_ews_message_start_set_item_field (msg, name, prefix, "Message");
+       e_ews_message_write_string_parameter_with_attribute (msg, name, NULL, value, attr_name, attr_value);
+       e_ews_message_end_set_item_field (msg);
+}
+
+static void
+convert_vjournal_component_to_updatexml (ESoapMessage *msg,
+                                        gpointer user_data)
+{
+       EwsCalendarConvertData *convert_data = user_data;
+       icalcomponent *icalcomp = e_cal_component_get_icalcomponent (convert_data->comp);
+       icalproperty *prop;
+       const gchar *text;
+
+       e_ews_message_start_item_change (
+               msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
+               convert_data->item_id, convert_data->change_key, 0);
+
+       convert_vjournal_property_to_updatexml (msg, "ItemClass", "IPM.StickyNote", "item", NULL, NULL);
+       convert_vjournal_property_to_updatexml (msg, "Subject", icalcomponent_get_summary (icalcomp), "item", 
NULL, NULL);
+
+       prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
+       if (prop) {
+               icalproperty_class classify = icalproperty_get_class (prop);
+               if (classify == ICAL_CLASS_PUBLIC) {
+                       convert_vjournal_property_to_updatexml (msg, "Sensitivity", "Normal", "item", NULL, 
NULL);
+               } else if (classify == ICAL_CLASS_PRIVATE) {
+                       convert_vjournal_property_to_updatexml (msg, "Sensitivity", "Private", "item", NULL, 
NULL);
+               } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
+                       convert_vjournal_property_to_updatexml (msg, "Sensitivity", "Personal", "item", NULL, 
NULL);
+               }
+       }
+
+       text = icalcomponent_get_description (icalcomp);
+       if (!text || !*text)
+               text = icalcomponent_get_summary (icalcomp);
+
+       convert_vjournal_property_to_updatexml (msg, "Body", text, "item", "BodyType", "Text");
+
+       /* Categories */
+       convert_component_categories_to_updatexml (convert_data->comp, msg, "Message");
+
+       e_ews_message_end_item_change (msg);
+}
+
+void
+e_cal_backend_ews_convert_component_to_updatexml (ESoapMessage *msg,
+                                                 gpointer user_data)
+{
+       EwsCalendarConvertData *convert_data = user_data;
+       icalcomponent *icalcomp = e_cal_component_get_icalcomponent (convert_data->comp);
+
+       switch (icalcomponent_isa (icalcomp)) {
+       case ICAL_VEVENT_COMPONENT:
+               convert_vevent_component_to_updatexml (msg, user_data);
+               break;
+       case ICAL_VTODO_COMPONENT:
+               convert_vtodo_component_to_updatexml (msg, user_data);
+               break;
+       case ICAL_VJOURNAL_COMPONENT:
+               convert_vjournal_component_to_updatexml (msg, user_data);
+               break;
+       default:
+               break;
+       }
+}
+
+guint
+e_cal_backend_ews_rid_to_index (icaltimezone *timezone,
+                               const gchar *rid,
+                               icalcomponent *comp,
+                               GError **error)
+{
+       guint index = 1;
+       icalproperty *prop = icalcomponent_get_first_property (comp, ICAL_RRULE_PROPERTY);
+       struct icalrecurrencetype rule = icalproperty_get_rrule (prop);
+       struct icaltimetype dtstart = icalcomponent_get_dtstart (comp);
+       icalrecur_iterator * ritr;
+       icaltimetype next, o_time;
+
+       /* icalcomponent_get_datetime needs a fix to initialize ret.zone to NULL. If a timezone is not
+        * found in libical, it remains uninitialized in that function causing invalid read or crash. so
+        * we set the timezone as we cannot identify if it has a valid timezone or not */
+       dtstart.zone = timezone;
+       ritr = icalrecur_iterator_new (rule, dtstart);
+       next = icalrecur_iterator_next (ritr);
+       o_time = icaltime_from_string (rid);
+       o_time.zone = dtstart.zone;
+
+       for (; !icaltime_is_null_time (next); next = icalrecur_iterator_next (ritr), index++) {
+               if (icaltime_compare_date_only (o_time, next) == 0)
+                       break;
+       }
+
+       icalrecur_iterator_free (ritr);
+
+       if (icaltime_is_null_time (next)) {
+               g_propagate_error (
+                       error, EDC_ERROR_EX (OtherError,
+                       "Invalid occurrence ID"));
+       }
+
+       return index;
+}
+
+void
+e_cal_backend_ews_clear_reminder_is_set (ESoapMessage *msg,
+                                        gpointer user_data)
+{
+       EwsCalendarConvertData *convert_data = user_data;
+
+       e_ews_message_start_item_change (
+               msg,
+               convert_data->change_type,
+               convert_data->item_id,
+               convert_data->change_key,
+               convert_data->index);
+
+       e_ews_message_start_set_item_field (msg, "ReminderIsSet","item", "CalendarItem");
+
+       e_ews_message_write_string_parameter (msg, "ReminderIsSet", NULL, "false");
+
+       e_ews_message_end_set_item_field (msg);
+
+       e_ews_message_end_item_change (msg);
+}
+
+void
+e_cal_backend_ews_prepare_free_busy_request (ESoapMessage *msg,
+                                            gpointer user_data)
+{
+       EwsCalendarConvertData *convert_data = user_data;
+       GSList *addr;
+       icaltimetype t_start, t_end;
+       icaltimezone *utc_zone = icaltimezone_get_utc_timezone ();
+
+       ewscal_set_availability_timezone (msg, utc_zone);
+
+       e_soap_message_start_element (msg, "MailboxDataArray", "messages", NULL);
+
+       for (addr = convert_data->users; addr; addr = addr->next) {
+               e_soap_message_start_element (msg, "MailboxData", NULL, NULL);
+
+               e_soap_message_start_element (msg, "Email", NULL, NULL);
+               e_ews_message_write_string_parameter (msg, "Address", NULL, addr->data);
+               e_soap_message_end_element (msg); /* "Email" */
+
+               e_ews_message_write_string_parameter (msg, "AttendeeType", NULL, "Required");
+               e_ews_message_write_string_parameter (msg, "ExcludeConflicts", NULL, "false");
+
+               e_soap_message_end_element (msg); /* "MailboxData" */
+       }
+
+       e_soap_message_end_element (msg); /* "MailboxDataArray" */
+
+       e_soap_message_start_element (msg, "FreeBusyViewOptions", NULL, NULL);
+
+       e_soap_message_start_element (msg, "TimeWindow", NULL, NULL);
+       t_start = icaltime_from_timet_with_zone (convert_data->start, 0, utc_zone);
+       t_end = icaltime_from_timet_with_zone (convert_data->end, 0, utc_zone);
+       ewscal_set_time (msg, "StartTime", &t_start, FALSE);
+       ewscal_set_time (msg, "EndTime", &t_end, FALSE);
+       e_soap_message_end_element (msg); /* "TimeWindow" */
+
+       e_ews_message_write_string_parameter (msg, "MergedFreeBusyIntervalInMinutes", NULL, "60");
+       e_ews_message_write_string_parameter (msg, "RequestedView", NULL, "DetailedMerged");
+
+       e_soap_message_end_element (msg); /* "FreeBusyViewOptions" */
+}
+
+void
+e_cal_backend_ews_prepare_set_free_busy_status (ESoapMessage *msg,
+                                               gpointer user_data)
+{
+       EwsCalendarConvertData *data = user_data;
+
+       e_ews_message_start_item_change (msg, E_EWS_ITEMCHANGE_TYPE_ITEM, data->item_id, data->change_key, 0);
+
+       e_ews_message_start_set_item_field (msg, "LegacyFreeBusyStatus", "calendar", "CalendarItem");
+
+       e_ews_message_write_string_parameter (msg, "LegacyFreeBusyStatus", NULL, "Free");
+
+       e_ews_message_end_set_item_field (msg);
+
+       e_ews_message_end_item_change (msg);
+}
+
+void
+e_cal_backend_ews_prepare_accept_item_request (ESoapMessage *msg,
+                                              gpointer user_data)
+{
+       EwsCalendarConvertData *data = user_data;
+       const gchar *response_type = data->response_type;
+
+       /* FORMAT OF A SAMPLE SOAP MESSAGE: 
http://msdn.microsoft.com/en-us/library/aa566464%28v=exchg.140%29.aspx
+        * Accept and Decline meeting have same method code (10032)
+        * The real status is reflected at Attendee property PARTSTAT
+        * need to find current user as attendee and make a decision what to do.
+        * Prepare AcceptItem node in the SOAP message */
+
+       if (response_type && !g_ascii_strcasecmp (response_type, "ACCEPTED"))
+               e_soap_message_start_element (msg, "AcceptItem", NULL, NULL);
+       else if (response_type && !g_ascii_strcasecmp (response_type, "DECLINED"))
+               e_soap_message_start_element (msg, "DeclineItem", NULL, NULL);
+       else
+               e_soap_message_start_element (msg, "TentativelyAcceptItem", NULL, NULL);
+
+       e_soap_message_start_element (msg, "ReferenceItemId", NULL, NULL);
+       e_soap_message_add_attribute (msg, "Id", data->item_id, NULL, NULL);
+       e_soap_message_add_attribute (msg, "ChangeKey", data->change_key, NULL, NULL);
+       e_soap_message_end_element (msg); // "ReferenceItemId"
+
+       /* end of "AcceptItem" */
+       e_soap_message_end_element (msg);
+}
diff --git a/src/calendar/e-cal-backend-ews-utils.h b/src/calendar/e-cal-backend-ews-utils.h
index 8563749..d7b654d 100644
--- a/src/calendar/e-cal-backend-ews-utils.h
+++ b/src/calendar/e-cal-backend-ews-utils.h
@@ -26,13 +26,37 @@
 #include <libical/icaltimezone.h>
 
 #include "server/e-ews-connection.h"
+#include "server/e-ews-item-change.h"
 
 #include "e-cal-backend-ews.h"
 
 G_BEGIN_DECLS
+#define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
+#define EDC_ERROR_EX(_code, _msg) e_data_cal_create_error (_code, _msg)
+
 #define MINUTES_IN_HOUR 60
 #define SECS_IN_MINUTE 60
 
+typedef struct {
+       EEwsConnection *connection;
+       icaltimezone *default_zone;
+       gchar *user_email;
+       gchar *response_type; /* Accept */
+       GSList *users;
+       ECalComponent *comp;
+       ECalComponent *old_comp;
+       icalcomponent *icalcomp;
+       gchar *item_id;
+       gchar *change_key;
+       EEwsItemChangeType change_type;
+       gint index;
+       time_t start;
+       time_t end;
+} EwsCalendarConvertData;
+
+EwsCalendarConvertData *ews_calendar_convert_data_new (void);
+void ews_calendar_convert_data_free (EwsCalendarConvertData *convert_data);
+
 const gchar *e_ews_collect_organizer (icalcomponent *comp);
 void e_ews_collect_attendees (icalcomponent *comp, GSList **required, GSList **optional, GSList **resource);
 
@@ -55,6 +79,15 @@ void e_cal_backend_ews_populate_tz_msdn_to_ical (void);
 void e_cal_backend_ews_unref_tz_ical_to_msdn (void);
 void e_cal_backend_ews_unref_tz_msdn_to_ical (void);
 
+void e_cal_backend_ews_convert_calcomp_to_xml (ESoapMessage *msg, gpointer user_data);
+void e_cal_backend_ews_convert_component_to_updatexml (ESoapMessage *msg, gpointer user_data);
+void e_cal_backend_ews_clear_reminder_is_set (ESoapMessage *msg, gpointer user_data);
+void e_cal_backend_ews_prepare_free_busy_request (ESoapMessage *msg, gpointer user_data);
+void e_cal_backend_ews_prepare_set_free_busy_status (ESoapMessage *msg,gpointer user_data);
+void e_cal_backend_ews_prepare_accept_item_request (ESoapMessage *msg, gpointer user_data);
+
+guint e_cal_backend_ews_rid_to_index (icaltimezone *timezone, const gchar *rid, icalcomponent *comp, GError 
**error);
+
 G_END_DECLS
 
 #endif
diff --git a/src/calendar/e-cal-backend-ews.c b/src/calendar/e-cal-backend-ews.c
index 47abae6..120cab9 100644
--- a/src/calendar/e-cal-backend-ews.c
+++ b/src/calendar/e-cal-backend-ews.c
@@ -40,9 +40,6 @@
 #include <libical/icalproperty.h>
 #include <libical/icalparameter.h>
 
-#include "server/e-ews-item-change.h"
-#include "server/e-ews-message.h"
-#include "server/e-soap-response.h"
 #include "server/e-source-ews-folder.h"
 
 #include "utils/ews-camel-common.h"
@@ -91,9 +88,6 @@ struct _ECalBackendEwsPrivate {
 #define PRIV_LOCK(p)   (g_rec_mutex_lock (&(p)->rec_mutex))
 #define PRIV_UNLOCK(p) (g_rec_mutex_unlock (&(p)->rec_mutex))
 
-#define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
-#define EDC_ERROR_EX(_code, _msg) e_data_cal_create_error (_code, _msg)
-
 #define SYNC_KEY "sync-state"
 #define EWS_MAX_FETCH_COUNT 100
 #define REFRESH_INTERVAL 600
@@ -136,7 +130,6 @@ struct _ECalBackendEwsPrivate {
 /* Forward Declarations */
 static void ews_cal_component_get_item_id (ECalComponent *comp, gchar **itemid, gchar **changekey);
 static gboolean ews_start_sync (gpointer data);
-static icaltimezone * e_cal_get_timezone_from_ical_component (ECalBackend *backend, icalcomponent *comp);
 static gpointer ews_start_sync_thread (gpointer data);
 static void    e_cal_backend_ews_authenticator_init
                                (ESourceAuthenticatorInterface *interface);
@@ -310,37 +303,47 @@ exit:
        e_data_cal_respond_add_timezone (cal, context, error);
 }
 
+typedef enum {
+       E_EWS_ATTACHMENT_TYPE_NOTHING = 0,
+       E_EWS_ATTACHMENT_TYPE_CREATE,
+       E_EWS_ATTACHMENT_TYPE_UPDATE
+} EEwsAttachmentType;
+
 typedef struct {
-       ECalBackendEws *cbews;
-       EDataCal *cal;
-       guint32 context;
-       gchar *itemid;
-       gchar *changekey;
-       gboolean is_occurrence;
-       gint instance_index;
-} EwsDiscardAlarmData;
-
-static void clear_reminder_is_set (ESoapMessage *msg, gpointer user_data)
-{
-       EwsDiscardAlarmData *edad = user_data;
-       EEwsItemChangeType change_type;
+       ECalBackendEws *cbews; /* Create, Remove, Modify, FreeBusy, Attachments, DiscardAlarm */
+       ECalComponent *comp; /* Create, Remove, Modify, FreeBusy, Attachments */
+       ECalComponent *extra_comp; /* Modify, Attachments: used as old_comp. Remove: used as parent_comp */
+       EDataCal *cal; /* Create, Remove, Modify, FreeBusy, Attachments, DiscardAlarm */
+       GSList *users; /* FreeBusy */
+       gchar *item_id; /* Accept, Remove, Modify, Attachments, DiscardAlarm */
+       gchar *rid; /* Remove */
+       EEwsAttachmentType cb_type; /* Attachments */
+       ECalObjModType mod; /* Remove */
+       guint32 context; /* Create, Remove, Modify, FreeBusy, Attachments, DiscardAlarm */
+} EwsCalendarAsyncData;
 
-       if (edad->is_occurrence)
-               change_type = E_EWS_ITEMCHANGE_TYPE_OCCURRENCEITEM;
-       else
-               change_type = E_EWS_ITEMCHANGE_TYPE_ITEM;
+static void
+e_cal_backend_ews_async_data_free (EwsCalendarAsyncData *async_data)
+{
+       if (async_data != NULL) {
+               if (async_data->cbews != NULL)
+                       g_object_unref (async_data->cbews);
 
-       e_ews_message_start_item_change (
-               msg, change_type,
-               edad->itemid, edad->changekey, edad->instance_index);
+               if (async_data->comp != NULL)
+                       g_object_unref (async_data->comp);
 
-       e_ews_message_start_set_item_field (msg, "ReminderIsSet","item", "CalendarItem");
+               if (async_data->extra_comp != NULL)
+                       g_object_unref (async_data->extra_comp);
 
-       e_ews_message_write_string_parameter (msg, "ReminderIsSet", NULL, "false");
+               if (async_data->cal != NULL)
+                       g_object_unref (async_data->cal);
 
-       e_ews_message_end_set_item_field (msg);
+               g_slist_free_full (async_data->users, g_free);
+               g_free (async_data->item_id);
+               g_free (async_data->rid);
 
-       e_ews_message_end_item_change (msg);
+               g_free (async_data);
+       }
 }
 
 static void
@@ -349,7 +352,7 @@ ews_cal_discard_alarm_cb (GObject *object,
                           gpointer user_data)
 {
        EEwsConnection *cnc = E_EWS_CONNECTION (object);
-       EwsDiscardAlarmData *edad = user_data;
+       EwsCalendarAsyncData *edad = user_data;
        GError *error = NULL;
 
        if (!e_ews_connection_update_items_finish (cnc, res, NULL, &error)) {
@@ -359,11 +362,7 @@ ews_cal_discard_alarm_cb (GObject *object,
        convert_error_to_edc_error (&error);
        e_data_cal_respond_discard_alarm (edad->cal, edad->context, error);
 
-       g_free (edad->itemid);
-       g_free (edad->changekey);
-       g_object_unref (edad->cbews);
-       g_object_unref (edad->cal);
-       g_free (edad);
+       e_cal_backend_ews_async_data_free (edad);
 }
 
 static void
@@ -377,7 +376,8 @@ e_cal_backend_ews_discard_alarm (ECalBackend *backend,
 {
        ECalBackendEws *cbews = (ECalBackendEws *) backend;
        ECalBackendEwsPrivate *priv;
-       EwsDiscardAlarmData *edad;
+       EwsCalendarAsyncData *edad;
+       EwsCalendarConvertData convert_data;
        ECalComponent *comp;
        GError *local_error = NULL;
 
@@ -404,7 +404,7 @@ e_cal_backend_ews_discard_alarm (ECalBackend *backend,
 
        /* FIXME: Can't there be multiple alarms for each event? Or does
         * Exchange not support that? */
-       edad = g_new0 (EwsDiscardAlarmData, 1);
+       edad = g_new0 (EwsCalendarAsyncData, 1);
        edad->cbews = g_object_ref (cbews);
        edad->cal = g_object_ref (cal);
        edad->context = context;
@@ -412,31 +412,31 @@ e_cal_backend_ews_discard_alarm (ECalBackend *backend,
        if (e_cal_component_has_recurrences (comp)) {
                gint *index;
 
-               edad->is_occurrence = TRUE;
+               convert_data.change_type = E_EWS_ITEMCHANGE_TYPE_OCCURRENCEITEM;
                e_cal_component_get_sequence (comp, &index);
 
                if (index != NULL) {
                        /*Microsoft is counting the occurrences starting from 1
                         where EcalComponent is starting from zerro */
-                       edad->instance_index = *index + 1;
+                       convert_data.index = *index + 1;
                        e_cal_component_free_sequence (index);
                } else {
-                       edad->is_occurrence = FALSE;
-                       edad->instance_index = -1;
+                       convert_data.change_type = E_EWS_ITEMCHANGE_TYPE_ITEM;
+                       convert_data.index = -1;
                }
-       }
-       else {
-               edad->is_occurrence = FALSE;
-               edad->instance_index = -1;
+       } else {
+               convert_data.change_type = E_EWS_ITEMCHANGE_TYPE_ITEM;
+               convert_data.index = -1;
        }
 
-       ews_cal_component_get_item_id (comp, &edad->itemid, &edad->changekey);
+       ews_cal_component_get_item_id (comp, &convert_data.item_id, &convert_data.change_key);
 
        e_ews_connection_update_items (
                priv->cnc, EWS_PRIORITY_MEDIUM,
                "AlwaysOverwrite", NULL,
                "SendToNone", NULL,
-               clear_reminder_is_set, edad,
+               e_cal_backend_ews_clear_reminder_is_set,
+               &convert_data,
                priv->cancellable,
                ews_cal_discard_alarm_cb,
                edad);
@@ -1012,24 +1012,40 @@ ews_cal_append_exdate (ECalBackendEws *cbews,
        g_object_unref (old_comp);
 }
 
-typedef struct {
-       ECalBackendEws *cbews;
-       EDataCal *cal;
-       ECalComponent *comp, *parent;
-       guint32 context;
-       EwsId item_id;
-       guint index;
-       gchar *rid;
-       gboolean modified;
-       ECalObjModType mod;
-} EwsRemoveData;
+static icaltimezone *
+e_cal_backend_ews_get_timezone_from_ical_component (ECalBackend *backend,
+                                                   icalcomponent *comp)
+{
+       ETimezoneCache *timezone_cache;
+       icalproperty *prop;
+       icalparameter *param;
+
+       timezone_cache = E_TIMEZONE_CACHE (backend);
+
+       prop = icalcomponent_get_first_property (
+               comp, ICAL_DTSTART_PROPERTY);
+       param = icalproperty_get_first_parameter (
+               prop, ICAL_TZID_PARAMETER);
+
+       if (param != NULL) {
+               const gchar *tzid;
+
+               tzid = icalparameter_get_tzid (param);
+
+               return e_timezone_cache_get_timezone (timezone_cache, tzid);
+       }
+
+       g_warning ("EEE Cant figure the relevant timezone of the component\n");
+
+       return NULL;
+}
 
 static void
 ews_cal_remove_object_cb (GObject *object,
                           GAsyncResult *res,
                           gpointer user_data)
 {
-       EwsRemoveData *remove_data = user_data;
+       EwsCalendarAsyncData *remove_data = user_data;
        GSimpleAsyncResult *simple;
        GError *error = NULL;
 
@@ -1038,8 +1054,11 @@ ews_cal_remove_object_cb (GObject *object,
        if (!g_simple_async_result_propagate_error (simple, &error) || error->code == 
EWS_CONNECTION_ERROR_ITEMNOTFOUND) {
                /* FIXME: This is horrid. Will bite us when we start to delete
                 * more than one item at a time... */
-               if (remove_data->comp) ews_cal_delete_comp (remove_data->cbews, remove_data->comp, 
remove_data->item_id.id);
-               if (remove_data->parent) ews_cal_append_exdate (remove_data->cbews, remove_data->parent, 
remove_data->rid, remove_data->mod);
+               if (remove_data->comp != NULL)
+                       ews_cal_delete_comp (remove_data->cbews, remove_data->comp, remove_data->item_id);
+               if (remove_data->extra_comp != NULL)
+                       ews_cal_append_exdate (
+                               remove_data->cbews, remove_data->extra_comp, remove_data->rid, 
remove_data->mod);
        }
 
        convert_error_to_edc_error (&error);
@@ -1051,51 +1070,7 @@ ews_cal_remove_object_cb (GObject *object,
                g_clear_error (&error);
        }
 
-       g_free (remove_data->item_id.id);
-       g_free (remove_data->item_id.change_key);
-       g_object_unref (remove_data->cbews);
-       if (remove_data->comp) g_object_unref (remove_data->comp);
-       if (remove_data->parent) g_object_unref (remove_data->parent);
-       g_object_unref (remove_data->cal);
-       if (remove_data->rid) g_free (remove_data->rid);
-       g_free (remove_data);
-}
-
-static guint
-e_cal_rid_to_index (ECalBackend *backend,
-                    const gchar *rid,
-                    icalcomponent *comp,
-                    GError **error)
-{
-       guint index = 1;
-       icalproperty *prop = icalcomponent_get_first_property (comp, ICAL_RRULE_PROPERTY);
-       struct icalrecurrencetype rule = icalproperty_get_rrule (prop);
-       struct icaltimetype dtstart = icalcomponent_get_dtstart (comp);
-       icalrecur_iterator * ritr;
-       icaltimetype next, o_time;
-
-       /* icalcomponent_get_datetime needs a fix to initialize ret.zone to NULL. If a timezone is not
-        * found in libical, it remains uninitialized in that function causing invalid read or crash. so
-        * we set the timezone as we cannot identify if it has a valid timezone or not */
-       dtstart.zone = e_cal_get_timezone_from_ical_component (backend, comp);
-       ritr = icalrecur_iterator_new (rule, dtstart);
-       next = icalrecur_iterator_next (ritr);
-       o_time = icaltime_from_string (rid);
-       o_time.zone = dtstart.zone;
-
-       for (; !icaltime_is_null_time (next); next = icalrecur_iterator_next (ritr), index++) {
-               if (icaltime_compare_date_only (o_time, next) == 0) break;
-       }
-
-       icalrecur_iterator_free (ritr);
-
-       if (icaltime_is_null_time (next)) {
-               g_propagate_error (
-                       error, EDC_ERROR_EX (OtherError,
-                       "Invalid occurrence ID"));
-       }
-
-       return index;
+       e_cal_backend_ews_async_data_free (remove_data);
 }
 
 static void
@@ -1107,7 +1082,7 @@ e_cal_backend_ews_remove_object (ECalBackend *backend,
                                  const gchar *rid,
                                  ECalObjModType mod)
 {
-       EwsRemoveData *remove_data;
+       EwsCalendarAsyncData *remove_data;
        ECalBackendEws *cbews = (ECalBackendEws *) backend;
        ECalBackendEwsPrivate *priv;
        ECalComponent *comp, *parent = NULL;
@@ -1152,7 +1127,7 @@ e_cal_backend_ews_remove_object (ECalBackend *backend,
                g_warning ("EEE Cant find component with uid:%s & rid:%s\n", uid, rid);
                g_propagate_error (&error, EDC_ERROR (ObjectNotFound));
                PRIV_UNLOCK (priv);
-               goto errorlvl1;
+               goto exit;
        }
 
        ews_cal_component_get_item_id ((comp ? comp : parent), &item_id.id, &item_id.change_key);
@@ -1163,45 +1138,54 @@ e_cal_backend_ews_remove_object (ECalBackend *backend,
                g_propagate_error (
                        &error, EDC_ERROR_EX (OtherError,
                        "Cannot determine EWS ItemId"));
-               goto errorlvl2;
+               goto exit;
        }
 
        if (parent && !comp) {
-               index = e_cal_rid_to_index (backend, rid, e_cal_component_get_icalcomponent (parent), &error);
-               if (error) goto errorlvl2;
+               index = e_cal_backend_ews_rid_to_index (
+                       e_cal_backend_ews_get_timezone_from_ical_component (
+                               backend,
+                               e_cal_component_get_icalcomponent (comp)),
+                       rid,
+                       e_cal_component_get_icalcomponent (parent),
+                       &error);
+
+               if (error != NULL)
+                       goto exit;
        }
 
-       remove_data = g_new0 (EwsRemoveData, 1);
+       remove_data = g_new0 (EwsCalendarAsyncData, 1);
        remove_data->cbews = g_object_ref (cbews);
        remove_data->comp = comp;
-       remove_data->parent = parent;
+       remove_data->extra_comp = parent;
        remove_data->cal = g_object_ref (cal);
        remove_data->context = context;
-       remove_data->index = index;
-       remove_data->item_id.id = item_id.id;
-       remove_data->item_id.change_key = item_id.change_key;
+       remove_data->item_id = g_strdup (item_id.id);
        remove_data->rid = (rid ? g_strdup (rid) : NULL);
        remove_data->mod = mod;
 
        e_ews_connection_delete_item (
-               priv->cnc, EWS_PRIORITY_MEDIUM, &remove_data->item_id, index,
+               priv->cnc, EWS_PRIORITY_MEDIUM, &item_id, index,
                EWS_HARD_DELETE, EWS_SEND_TO_NONE, EWS_ALL_OCCURRENCES,
                priv->cancellable,
                ews_cal_remove_object_cb,
                remove_data);
+
        return;
 
-errorlvl2:
-       if (comp) g_object_unref (comp);
+exit:
+       if (comp != NULL)
+               g_object_unref (comp);
 
-errorlvl1:
-       if (parent) g_object_unref (parent);
+       if (parent != NULL)
+               g_object_unref (parent);
 
-exit:
        convert_error_to_edc_error (&error);
+
        if (context)
                e_data_cal_respond_remove_objects (cal, context, error, NULL, NULL, NULL);
-       else if (error) {
+
+       if (error != NULL) {
                g_warning ("Remove object error :  %s\n", error->message);
                g_clear_error (&error);
        }
@@ -1249,376 +1233,6 @@ e_cal_backend_ews_remove_objects (ECalBackend *backend,
 static icaltimezone * resolve_tzid (const gchar *tzid, gpointer user_data);
 static void put_component_to_store (ECalBackendEws *cbews,ECalComponent *comp);
 
-typedef struct {
-       ECalBackendEws *cbews;
-       EDataCal *cal;
-       ECalComponent *comp;
-       guint32 context;
-} EwsCreateData;
-
-typedef struct {
-       ECalBackendEws *cbews;
-       icalcomponent *icalcomp;
-} EwsConvertData;
-
-static void
-add_attendees_list_to_message (ESoapMessage *msg,
-                               const gchar *listname,
-                               GSList *list)
-{
-       GSList *item;
-
-       e_soap_message_start_element (msg, listname, NULL, NULL);
-
-       for (item = list; item != NULL; item = item->next) {
-               e_soap_message_start_element (msg, "Attendee", NULL, NULL);
-               e_soap_message_start_element (msg, "Mailbox", NULL, NULL);
-
-               e_ews_message_write_string_parameter (msg, "EmailAddress", NULL, item->data);
-
-               e_soap_message_end_element (msg); /* "Mailbox" */
-               e_soap_message_end_element (msg); /* "Attendee" */
-       }
-
-       e_soap_message_end_element (msg);
-}
-
-static void
-convert_sensitivity_calcomp_to_xml (ESoapMessage *msg,
-                                   icalcomponent *icalcomp)
-{
-       icalproperty *prop;
-
-       g_return_if_fail (msg != NULL);
-       g_return_if_fail (icalcomp != NULL);
-
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
-       if (prop) {
-               icalproperty_class classify = icalproperty_get_class (prop);
-               if (classify == ICAL_CLASS_PUBLIC) {
-                       e_ews_message_write_string_parameter (msg, "Sensitivity", NULL, "Normal");
-               } else if (classify == ICAL_CLASS_PRIVATE) {
-                       e_ews_message_write_string_parameter (msg, "Sensitivity", NULL, "Private");
-               } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
-                       e_ews_message_write_string_parameter (msg, "Sensitivity", NULL, "Personal");
-               }
-       }
-}
-
-static void
-convert_categories_calcomp_to_xml (ESoapMessage *msg,
-                                  ECalComponent *comp,
-                                  icalcomponent *icalcomp)
-{
-       GSList *categ_list, *citer;
-
-       g_return_if_fail (msg != NULL);
-       g_return_if_fail (icalcomp != NULL);
-
-       if (comp) {
-               g_object_ref (comp);
-       } else {
-               icalcomponent *clone = icalcomponent_new_clone (icalcomp);
-
-               comp = e_cal_component_new ();
-               if (!e_cal_component_set_icalcomponent (comp, clone)) {
-                       icalcomponent_free (clone);
-                       g_object_unref (comp);
-
-                       return;
-               }
-       }
-
-       e_cal_component_get_categories_list (comp, &categ_list);
-
-       g_object_unref (comp);
-
-       if (!categ_list)
-               return;
-
-       e_soap_message_start_element (msg, "Categories", NULL, NULL);
-
-       for (citer = categ_list; citer;  citer = g_slist_next (citer)) {
-               const gchar *category = citer->data;
-
-               if (!category || !*category)
-                       continue;
-
-               e_ews_message_write_string_parameter (msg, "String", NULL, category);
-       }
-
-       e_soap_message_end_element (msg); /* Categories */
-
-       e_cal_component_free_categories_list (categ_list);
-}
-
-static void
-convert_vevent_calcomp_to_xml (ESoapMessage *msg,
-                               gpointer user_data)
-{
-       EwsConvertData *convert_data = user_data;
-       icalcomponent *icalcomp = convert_data->icalcomp;
-       ECalComponent *comp = e_cal_component_new ();
-       GSList *required = NULL, *optional = NULL, *resource = NULL;
-       icaltimetype dtstart, dtend;
-       icalproperty *prop;
-       gboolean has_alarms;
-       const gchar *value;
-
-       e_cal_component_set_icalcomponent (comp, icalcomp);
-
-       /* FORMAT OF A SAMPLE SOAP MESSAGE: http://msdn.microsoft.com/en-us/library/aa564690.aspx */
-
-       /* Prepare CalendarItem node in the SOAP message */
-       e_soap_message_start_element (msg, "CalendarItem", NULL, NULL);
-
-       /* subject */
-       value = icalcomponent_get_summary (icalcomp);
-       if (value)
-               e_ews_message_write_string_parameter (msg, "Subject", NULL, value);
-
-       convert_sensitivity_calcomp_to_xml (msg, icalcomp);
-
-       /* description */
-       value = icalcomponent_get_description (icalcomp);
-       if (value)
-               e_ews_message_write_string_parameter_with_attribute (msg, "Body", NULL, value, "BodyType", 
"Text");
-
-       convert_categories_calcomp_to_xml (msg, comp, icalcomp);
-
-       /* set alarms */
-       has_alarms = e_cal_component_has_alarms (comp);
-       if (has_alarms)
-               ews_set_alarm (msg, comp);
-       else
-               e_ews_message_write_string_parameter (msg, "ReminderIsSet", NULL, "false");
-
-       /* start time, end time and meeting time zone */
-       dtstart = icalcomponent_get_dtstart (icalcomp);
-       dtend = icalcomponent_get_dtend (icalcomp);
-
-       ewscal_set_time (msg, "Start", &dtstart, FALSE);
-       ewscal_set_time (msg, "End", &dtend, FALSE);
-       /* We have to do the time zone(s) later, or the server rejects the request */
-
-       /* All day event ? */
-       if (icaltime_is_date (dtstart))
-               e_ews_message_write_string_parameter (msg, "IsAllDayEvent", NULL, "true");
-
-       /*freebusy*/
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_TRANSP_PROPERTY);
-       if (!g_strcmp0 (icalproperty_get_value_as_string (prop), "TRANSPARENT"))
-               e_ews_message_write_string_parameter (msg, "LegacyFreeBusyStatus",NULL,"Free");
-       else
-               e_ews_message_write_string_parameter (msg, "LegacyFreeBusyStatus",NULL,"Busy");
-
-       /* location */
-       value = icalcomponent_get_location (icalcomp);
-       if (value)
-               e_ews_message_write_string_parameter (msg, "Location", NULL, value);
-
-       /* collect attendees */
-       e_ews_collect_attendees (icalcomp, &required, &optional, &resource);
-
-       if (required != NULL) {
-               add_attendees_list_to_message (msg, "RequiredAttendees", required);
-               g_slist_free (required);
-       }
-       if (optional != NULL) {
-               add_attendees_list_to_message (msg, "OptionalAttendees", optional);
-               g_slist_free (optional);
-       }
-       if (resource != NULL) {
-               add_attendees_list_to_message (msg, "Resources", resource);
-               g_slist_free (resource);
-       }
-       /* end of attendees */
-
-       /* Recurrence */
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
-       if (prop != NULL) {
-               ewscal_set_reccurence (msg, prop, &dtstart);
-       }
-
-       /* We have to cast these because libical puts a const pointer into the
-        * icaltimetype, but its basic read-only icaltimezone_foo() functions
-        * take a non-const pointer! */
-       if (e_ews_connection_satisfies_server_version (convert_data->cbews->priv->cnc, E_EWS_EXCHANGE_2010)) {
-               const gchar *ical_location;
-               const gchar *msdn_location;
-               icaltimezone *tzid;
-               GSList *msdn_locations = NULL;
-               GSList *tzds = NULL;
-
-               tzid = (icaltimezone *)(dtstart.zone ? dtstart.zone : 
convert_data->cbews->priv->default_zone);
-               ical_location = icaltimezone_get_location (tzid);
-               msdn_location = e_cal_backend_ews_tz_util_get_msdn_equivalent (ical_location);
-
-               msdn_locations = g_slist_prepend (msdn_locations, (gchar *) msdn_location);
-
-               tzid = (icaltimezone *)(dtend.zone ? dtend.zone : convert_data->cbews->priv->default_zone);
-               ical_location = icaltimezone_get_location (tzid);
-               msdn_location = e_cal_backend_ews_tz_util_get_msdn_equivalent (ical_location);
-
-               msdn_locations = g_slist_prepend (msdn_locations, (gchar *) msdn_location);
-
-               msdn_locations = g_slist_reverse (msdn_locations);
-
-               if (e_ews_connection_get_server_time_zones_sync (
-                               convert_data->cbews->priv->cnc,
-                               EWS_PRIORITY_MEDIUM,
-                               msdn_locations,
-                               &tzds,
-                               NULL,
-                               NULL)) {
-                       ewscal_set_timezone (msg, "StartTimeZone", tzds->data);
-                       ewscal_set_timezone (msg, "EndTimeZone", tzds->data);
-               }
-
-               g_slist_free (msdn_locations);
-               g_slist_free_full (tzds, (GDestroyNotify) e_ews_calendar_time_zone_definition_free);
-       } else {
-               ewscal_set_meeting_timezone (
-                       msg,
-                       (icaltimezone *)(dtstart.zone ? dtstart.zone : 
convert_data->cbews->priv->default_zone));
-       }
-
-       // end of "CalendarItem"
-       e_soap_message_end_element (msg);
-}
-
-static void
-convert_vtodo_calcomp_to_xml (ESoapMessage *msg,
-                              gpointer user_data)
-{
-       EwsConvertData *convert_data = user_data;
-       icalcomponent *icalcomp = convert_data->icalcomp;
-       icalproperty *prop;
-       icaltimetype dt;
-       gint value;
-       gchar buffer[16];
-
-       e_soap_message_start_element (msg, "Task", NULL, NULL);
-
-       e_ews_message_write_string_parameter (msg, "Subject", NULL, icalcomponent_get_summary (icalcomp));
-
-       convert_sensitivity_calcomp_to_xml (msg, icalcomp);
-
-       e_ews_message_write_string_parameter_with_attribute (msg, "Body", NULL, icalcomponent_get_description 
(icalcomp), "BodyType", "Text");
-
-       convert_categories_calcomp_to_xml (msg, NULL, icalcomp);
-
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_DUE_PROPERTY);
-       if (prop) {
-               dt = icalproperty_get_due (prop);
-               ewscal_set_time (msg, "DueDate", &dt, TRUE);
-       }
-
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
-       if (prop) {
-               value = icalproperty_get_percentcomplete (prop);
-               snprintf (buffer, 16, "%d", value);
-               e_ews_message_write_string_parameter (msg, "PercentComplete", NULL, buffer);
-       }
-
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
-       if (prop) {
-               dt = icalproperty_get_dtstart (prop);
-               ewscal_set_time (msg, "StartDate", &dt, TRUE);
-       }
-
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_STATUS_PROPERTY);
-       if (prop) {
-               switch (icalproperty_get_status (prop)) {
-               case ICAL_STATUS_INPROCESS:
-                       e_ews_message_write_string_parameter (msg, "Status", NULL, "InProgress");
-                       break;
-               case ICAL_STATUS_COMPLETED:
-                       e_ews_message_write_string_parameter (msg, "Status", NULL, "Completed");
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       e_soap_message_end_element (msg); // "Task"
-}
-
-static void
-convert_vjournal_calcomp_to_xml (ESoapMessage *msg,
-                                gpointer user_data)
-{
-       EwsConvertData *convert_data = user_data;
-       icalcomponent *icalcomp = convert_data->icalcomp;
-       const gchar *text;
-
-       e_soap_message_start_element (msg, "Message", NULL, NULL);
-       e_ews_message_write_string_parameter (msg, "ItemClass", NULL, "IPM.StickyNote");
-
-       e_ews_message_write_string_parameter (msg, "Subject", NULL, icalcomponent_get_summary (icalcomp));
-
-       convert_sensitivity_calcomp_to_xml (msg, icalcomp);
-
-       text = icalcomponent_get_description (icalcomp);
-       if (!text || !*text)
-               text = icalcomponent_get_summary (icalcomp);
-       e_ews_message_write_string_parameter_with_attribute (msg, "Body", NULL, text, "BodyType", "Text");
-
-       convert_categories_calcomp_to_xml (msg, NULL, icalcomp);
-
-       e_soap_message_end_element (msg); /* Message */
-}
-
-static void
-convert_calcomp_to_xml (ESoapMessage *msg,
-                        gpointer user_data)
-{
-       EwsConvertData *convert_data = user_data;
-
-       switch (icalcomponent_isa (convert_data->icalcomp)) {
-       case ICAL_VEVENT_COMPONENT:
-               convert_vevent_calcomp_to_xml (msg, user_data);
-               break;
-       case ICAL_VTODO_COMPONENT:
-               convert_vtodo_calcomp_to_xml (msg, user_data);
-               break;
-       case ICAL_VJOURNAL_COMPONENT:
-               convert_vjournal_calcomp_to_xml (msg, user_data);
-               break;
-       default:
-               g_warn_if_reached ();
-               break;
-       }
-
-       g_object_unref (convert_data->cbews);
-       g_free (convert_data);
-}
-
-/*I will unate both type, they are same now*/
-typedef struct {
-        ECalBackendEws *cbews;
-        ECalComponent *comp;
-        gint cb_type; /* 0 - nothing,
-                                 1 - create,
-                                 2 - update */
-        EDataCal *cal;
-        guint32 context;
-        ECalComponent *oldcomp;
-        gchar *itemid;
-        gchar *changekey;
-
-} EwsAttachmentsData;
-
-typedef struct {
-        ECalBackendEws *cbews;
-        EDataCal *cal;
-        ECalComponent *comp;
-        ECalComponent *oldcomp;
-        guint32 context;
-        gchar *itemid;
-        gchar *changekey;
-} EwsModifyData;
-
 static void
 e_cal_backend_ews_modify_object (ECalBackend *backend,
                                  EDataCal *cal,
@@ -1627,8 +1241,6 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
                                  const gchar *calobj,
                                  ECalObjModType mod);
 
-static void convert_component_to_updatexml (ESoapMessage *msg,
-                                 gpointer user_data);
 static void ews_cal_modify_object_cb (GObject *object,
                                  GAsyncResult *res,
                                  gpointer user_data);
@@ -1639,7 +1251,7 @@ ews_create_attachments_cb (GObject *object,
                                  gpointer user_data)
 {
        EEwsConnection *cnc = E_EWS_CONNECTION (object);
-       EwsAttachmentsData *create_data = user_data;
+       EwsCalendarAsyncData *create_data = user_data;
        ECalBackendEwsPrivate *priv = create_data->cbews->priv;
        gchar *change_key;
        GSList *ids, *i;
@@ -1687,26 +1299,27 @@ ews_create_attachments_cb (GObject *object,
        e_cal_backend_store_thaw_changes (priv->store);
 
        e_cal_component_get_uid (create_data->comp, &comp_uid);
-       if (create_data->cb_type == 1) {
-               /*In case we have attendees we have to fake update items,
-               * this is the only way to pass attachments in meeting invite mail*/
-               if (e_cal_component_has_attendees (create_data->comp)) {
-                       icalcomponent *icalcomp = e_cal_component_get_icalcomponent (create_data->comp);
-                       e_cal_backend_ews_modify_object ((ECalBackend *) create_data->cbews, 
create_data->cal, 0, NULL, icalcomponent_as_ical_string (icalcomp), E_CAL_OBJ_MOD_ALL);
-               }
-       } else if (create_data->cb_type == 2) {
+       if (create_data->cb_type == E_EWS_ATTACHMENT_TYPE_UPDATE) {
                const gchar *send_meeting_invitations;
                const gchar *send_or_save;
-               EwsModifyData * modify_data;
+               EwsCalendarAsyncData *modify_data;
+               EwsCalendarConvertData convert_data;
 
-               modify_data = g_new0 (EwsModifyData, 1);
+               modify_data = g_new0 (EwsCalendarAsyncData, 1);
                modify_data->cbews = g_object_ref (create_data->cbews);
                modify_data->comp = create_data->comp;
-               modify_data->oldcomp = create_data->oldcomp;
+               modify_data->extra_comp = create_data->extra_comp;
                modify_data->cal = g_object_ref (create_data->cal);
                modify_data->context = create_data->context;
-               modify_data->itemid = create_data->itemid;
-               modify_data->changekey = change_key;
+               modify_data->item_id = create_data->item_id;
+
+               convert_data.connection = create_data->cbews->priv->cnc;
+               convert_data.user_email = create_data->cbews->priv->user_email;
+               convert_data.comp = create_data->comp;
+               convert_data.old_comp = create_data->extra_comp;
+               convert_data.item_id = create_data->item_id;
+               convert_data.change_key = change_key;
+               convert_data.default_zone = create_data->cbews->priv->default_zone;
 
                if (e_cal_component_has_attendees (create_data->comp)) {
                        send_meeting_invitations = "SendToAllAndSaveCopy";
@@ -1723,20 +1336,30 @@ ews_create_attachments_cb (GObject *object,
                        send_or_save,
                        send_meeting_invitations,
                        priv->folder_id,
-                       convert_component_to_updatexml,
-                       modify_data,
+                       e_cal_backend_ews_convert_component_to_updatexml,
+                       &convert_data,
                        priv->cancellable,
                        ews_cal_modify_object_cb,
-                       modify_data);
+                       create_data);
+       } else {
+               if (create_data->cb_type == E_EWS_ATTACHMENT_TYPE_CREATE) {
+                       /*In case we have attendees we have to fake update items,
+                       * this is the only way to pass attachments in meeting invite mail*/
+                       if (e_cal_component_has_attendees (create_data->comp)) {
+                               icalcomponent *icalcomp = e_cal_component_get_icalcomponent 
(create_data->comp);
+                               e_cal_backend_ews_modify_object (
+                                       E_CAL_BACKEND (create_data->cbews),
+                                       create_data->cal,
+                                       0,
+                                       NULL,
+                                       icalcomponent_as_ical_string (icalcomp),
+                                       E_CAL_OBJ_MOD_ALL);
+                       }
+               }
+               e_cal_backend_ews_async_data_free (create_data);
        }
 
        g_slist_free (ids);
-
-       g_object_unref (create_data->cbews);
-       g_object_unref (create_data->cal);
-       g_object_unref (create_data->comp);
-       if (create_data->oldcomp) g_object_unref (create_data->oldcomp);
-       g_free (create_data);
 }
 
 static void
@@ -1745,7 +1368,7 @@ ews_create_object_cb (GObject *object,
                       gpointer user_data)
 {
        EEwsConnection *cnc = E_EWS_CONNECTION (object);
-       EwsCreateData *create_data = user_data;
+       EwsCalendarAsyncData *create_data = user_data;
        ECalBackendEws *cbews = create_data->cbews;
        ECalBackendEwsPrivate *priv = cbews->priv;
        GError *error = NULL;
@@ -1815,7 +1438,7 @@ ews_create_object_cb (GObject *object,
        n_attach = e_cal_component_get_num_attachments (create_data->comp);
        if (n_attach > 0) {
                GSList *info_attachments = NULL;
-               EwsAttachmentsData *attach_data = g_new0 (EwsAttachmentsData, 1);
+               EwsCalendarAsyncData *attach_data = g_new0 (EwsCalendarAsyncData, 1);
 
                attach_data->cbews = g_object_ref (create_data->cbews);
                attach_data->comp = g_object_ref (create_data->comp);
@@ -1905,13 +1528,7 @@ ews_create_object_cb (GObject *object,
                g_slist_free_full (exceptions, g_free);
        }
 
-       /* no need to keep reference to the object */
-       g_object_unref (create_data->comp);
-
-       /* free memory allocated for create_data & unref contained objects */
-       g_object_unref (create_data->cbews);
-       g_object_unref (create_data->cal);
-       g_free (create_data);
+       e_cal_backend_ews_async_data_free (create_data);
 }
 
 struct TzidCbData {
@@ -1948,8 +1565,8 @@ e_cal_backend_ews_create_objects (ECalBackend *backend,
                                   GCancellable *cancellable,
                                   const GSList *calobjs)
 {
-       EwsCreateData *create_data;
-       EwsConvertData *convert_data;
+       EwsCalendarAsyncData *create_data;
+       EwsCalendarConvertData convert_data;
        EwsFolderId *fid;
        ECalBackendEws *cbews;
        ECalBackendEwsPrivate *priv;
@@ -1989,7 +1606,7 @@ e_cal_backend_ews_create_objects (ECalBackend *backend,
        }
 
        /* parse ical data */
-       comp =  e_cal_component_new_from_string (calobj);
+       comp = e_cal_component_new_from_string (calobj);
        if (comp == NULL) {
                g_propagate_error (&error, EDC_ERROR (InvalidObject));
                goto exit;
@@ -2021,29 +1638,32 @@ e_cal_backend_ews_create_objects (ECalBackend *backend,
        e_cal_component_set_created (comp, &current);
        e_cal_component_set_last_modified (comp, &current);
 
-       create_data = g_new0 (EwsCreateData, 1);
+       create_data = g_new0 (EwsCalendarAsyncData, 1);
        create_data->cbews = g_object_ref (cbews);
        create_data->comp = comp;
        create_data->cal = g_object_ref (cal);
        create_data->context = context;
 
-       convert_data = g_new0 (EwsConvertData, 1);
-       convert_data->cbews = g_object_ref (cbews);
-       convert_data->icalcomp = icalcomp;
+       convert_data.connection = cbews->priv->cnc;
+       convert_data.icalcomp = icalcomp;
+       convert_data.default_zone = cbews->priv->default_zone;
 
-       /*In case we are creating a meeting with attendees and attachments. 
+       /*
+        * In case we are creating a meeting with attendees and attachments.
         * We have to preform 3 steps in order to allow attendees to receive attachments in their invite 
mails.
         * 1. create meeting and do not send invites
         * 2. create attachments
-        * 3. dummy update meeting and send invites to all*/
+        * 3. dummy update meeting and send invites to all
+        */
        if (e_cal_component_has_attendees (comp)) {
                if (e_cal_component_has_attachments (comp))
                        send_meeting_invitations = "SendToNone";
                else
                        send_meeting_invitations = "SendToAllAndSaveCopy";
-       } else
+       } else {
                /*In case of appointment we have to set SendMeetingInvites to SendToNone */
                send_meeting_invitations = "SendToNone";
+       }
 
        fid = e_ews_folder_id_new (priv->folder_id, NULL, FALSE);
 
@@ -2053,8 +1673,8 @@ e_cal_backend_ews_create_objects (ECalBackend *backend,
                "SaveOnly",
                send_meeting_invitations,
                fid,
-               convert_calcomp_to_xml,
-               convert_data,
+               e_cal_backend_ews_convert_calcomp_to_xml,
+               &convert_data,
                cancellable,
                ews_create_object_cb,
                create_data);
@@ -2074,7 +1694,7 @@ ews_cal_modify_object_cb (GObject *object,
                           gpointer user_data)
 {
        EEwsConnection *cnc = E_EWS_CONNECTION (object);
-       EwsModifyData *modify_data = user_data;
+       EwsCalendarAsyncData *modify_data = user_data;
        ECalBackendEws *cbews = modify_data->cbews;
        ECalBackendEwsPrivate *priv = cbews->priv;
        GError *error = NULL;
@@ -2093,7 +1713,7 @@ ews_cal_modify_object_cb (GObject *object,
        }
 
        g_object_ref (modify_data->comp);
-       g_object_ref (modify_data->oldcomp);
+       g_object_ref (modify_data->extra_comp);
 
        e_cal_backend_store_freeze_changes (priv->store);
 
@@ -2119,9 +1739,9 @@ ews_cal_modify_object_cb (GObject *object,
        if (modify_data->context) {
                GSList *old_components, *new_components;
 
-               e_cal_backend_notify_component_modified (E_CAL_BACKEND (cbews), modify_data->oldcomp, 
modify_data->comp);
+               e_cal_backend_notify_component_modified (E_CAL_BACKEND (cbews), modify_data->extra_comp, 
modify_data->comp);
 
-               old_components = g_slist_append (NULL, modify_data->oldcomp);
+               old_components = g_slist_append (NULL, modify_data->extra_comp);
                new_components = g_slist_append (NULL, modify_data->comp);
 
                convert_error_to_edc_error (&error);
@@ -2136,7 +1756,7 @@ ews_cal_modify_object_cb (GObject *object,
        } else ews_start_sync (modify_data->cbews);
 
        PRIV_LOCK (priv);
-       g_hash_table_replace (priv->item_id_hash, g_strdup (modify_data->itemid), g_object_ref 
(modify_data->comp));
+       g_hash_table_replace (priv->item_id_hash, g_strdup (modify_data->item_id), g_object_ref 
(modify_data->comp));
        PRIV_UNLOCK (priv);
 
        e_cal_backend_store_thaw_changes (priv->store);
@@ -2145,474 +1765,7 @@ ews_cal_modify_object_cb (GObject *object,
        e_cal_component_free_id (id);
 
 exit:
-       g_free (modify_data->itemid);
-       g_free (modify_data->changekey);
-       g_object_unref (modify_data->comp);
-       g_object_unref (modify_data->oldcomp);
-       g_object_unref (modify_data->cbews);
-       g_object_unref (modify_data->cal);
-       g_free (modify_data);
-}
-
-static void
-convert_component_categories_to_updatexml (ECalComponent *comp,
-                                          ESoapMessage *msg,
-                                          const gchar *base_elem_name)
-{
-       GSList *categ_list = NULL, *citer;
-
-       g_return_if_fail (comp != NULL);
-       g_return_if_fail (msg != NULL);
-       g_return_if_fail (base_elem_name != NULL);
-
-       e_cal_component_get_categories_list (comp, &categ_list);
-       e_ews_message_start_set_item_field (msg, "Categories", "item", base_elem_name);
-       e_soap_message_start_element (msg, "Categories", NULL, NULL);
-
-       for (citer = categ_list; citer;  citer = g_slist_next (citer)) {
-               const gchar *category = citer->data;
-
-               if (!category || !*category)
-                       continue;
-
-               e_ews_message_write_string_parameter (msg, "String", NULL, category);
-       }
-
-       e_soap_message_end_element (msg); /* Categories */
-       e_ews_message_end_set_item_field (msg);
-
-       e_cal_component_free_categories_list (categ_list);
-}
-
-static void
-convert_vevent_property_to_updatexml (ESoapMessage *msg,
-                                      const gchar *name,
-                                      const gchar *value,
-                                      const gchar *prefix,
-                                      const gchar *attr_name,
-                                      const gchar *attr_value)
-{
-       e_ews_message_start_set_item_field (msg, name, prefix, "CalendarItem");
-       e_ews_message_write_string_parameter_with_attribute (msg, name, NULL, value, attr_name, attr_value);
-       e_ews_message_end_set_item_field (msg);
-}
-
-static void
-convert_vevent_component_to_updatexml (ESoapMessage *msg,
-                                       gpointer user_data)
-{
-       EwsModifyData *modify_data = user_data;
-       icalcomponent *icalcomp = e_cal_component_get_icalcomponent (modify_data->comp);
-       icalcomponent *icalcomp_old = e_cal_component_get_icalcomponent (modify_data->oldcomp);
-       GSList *required = NULL, *optional = NULL, *resource = NULL;
-       icaltimetype dtstart, dtend, dtstart_old, dtend_old;
-       icalproperty *prop, *transp;
-       const gchar *org_email_address = NULL, *value = NULL, *old_value = NULL;
-       gboolean has_alarms, has_alarms_old, dt_changed = FALSE;
-       gint alarm = 0, alarm_old = 0;
-       gchar *recid;
-       GError *error = NULL;
-
-       /* Modifying a recurring meeting ? */
-       if (icalcomponent_get_first_property (icalcomp_old, ICAL_RRULE_PROPERTY) != NULL) {
-               /* A single occurrence ? */
-               prop = icalcomponent_get_first_property (icalcomp, ICAL_RECURRENCEID_PROPERTY);
-               if (prop != NULL) {
-                       recid = icalproperty_get_value_as_string_r (prop);
-                       e_ews_message_start_item_change (
-                               msg, E_EWS_ITEMCHANGE_TYPE_OCCURRENCEITEM,
-                               modify_data->itemid, modify_data->changekey, e_cal_rid_to_index 
(E_CAL_BACKEND (modify_data->cbews), recid, icalcomp_old, &error));
-                       free (recid);
-               } else {
-                       e_ews_message_start_item_change (
-                               msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
-                               modify_data->itemid, modify_data->changekey, 0);
-               }
-       } else e_ews_message_start_item_change (msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
-               modify_data->itemid, modify_data->changekey, 0);
-
-       /* subject */
-       value = icalcomponent_get_summary (icalcomp);
-       old_value = icalcomponent_get_summary (icalcomp_old);
-       if ((value && old_value && g_ascii_strcasecmp (value, old_value)) ||
-        (value && old_value == NULL)) {
-               convert_vevent_property_to_updatexml (msg, "Subject", value, "item", NULL, NULL);
-       } else if (!value && old_value)
-               convert_vevent_property_to_updatexml (msg, "Subject", "", "item", NULL, NULL);
-
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
-       if (prop) {
-               icalproperty_class classify = icalproperty_get_class (prop);
-               if (classify == ICAL_CLASS_PUBLIC) {
-                       convert_vevent_property_to_updatexml (msg, "Sensitivity", "Normal", "item", NULL, 
NULL);
-               } else if (classify == ICAL_CLASS_PRIVATE) {
-                       convert_vevent_property_to_updatexml (msg, "Sensitivity", "Private", "item", NULL, 
NULL);
-               } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
-                       convert_vevent_property_to_updatexml (msg, "Sensitivity", "Personal", "item", NULL, 
NULL);
-               }
-       }
-
-       /*description*/
-       value = icalcomponent_get_description (icalcomp);
-       old_value = icalcomponent_get_description (icalcomp_old);
-       if ((value && old_value && g_ascii_strcasecmp (value, old_value)) ||
-        (value && old_value == NULL)) {
-               convert_vevent_property_to_updatexml (msg, "Body", value, "item", "BodyType", "Text");
-       } else if (!value && old_value)
-               convert_vevent_property_to_updatexml (msg, "Body", "", "item", "BodyType", "Text");
-
-       /*update alarm items*/
-       has_alarms = e_cal_component_has_alarms (modify_data->comp);
-       if (has_alarms) {
-               alarm = ews_get_alarm (modify_data->comp);
-               has_alarms_old = e_cal_component_has_alarms (modify_data->oldcomp);
-               if (has_alarms_old)
-                       alarm_old = ews_get_alarm (modify_data->oldcomp);
-               if (!(alarm == alarm_old)) {
-                       gchar buf[20];
-                       snprintf (buf, 20, "%d", alarm);
-                       convert_vevent_property_to_updatexml (msg, "ReminderIsSet", "true", "item", NULL, 
NULL);
-                       convert_vevent_property_to_updatexml (msg, "ReminderMinutesBeforeStart", buf, "item", 
NULL, NULL);
-               }
-       }
-       else convert_vevent_property_to_updatexml (msg, "ReminderIsSet", "false", "item", NULL, NULL);
-
-       /* Categories */
-       convert_component_categories_to_updatexml (modify_data->comp, msg, "CalendarItem");
-
-       /*location*/
-       value = icalcomponent_get_location (icalcomp);
-       old_value = icalcomponent_get_location (icalcomp_old);
-       if ((value && old_value && g_ascii_strcasecmp (value, old_value)) ||
-        (value && old_value == NULL)) {
-               convert_vevent_property_to_updatexml (msg, "Location", value, "calendar", NULL, NULL);
-       } else if (!value && old_value)
-               convert_vevent_property_to_updatexml (msg, "Location", "", "calendar", NULL, NULL);
-
-       /*freebusy*/
-       transp = icalcomponent_get_first_property (icalcomp, ICAL_TRANSP_PROPERTY);
-       value = icalproperty_get_value_as_string (transp);
-       transp = icalcomponent_get_first_property (icalcomp_old, ICAL_TRANSP_PROPERTY);
-       old_value = icalproperty_get_value_as_string (transp);
-       if (g_strcmp0 (value, old_value)) {
-               if (!g_strcmp0 (value, "TRANSPARENT"))
-                       convert_vevent_property_to_updatexml (msg, "LegacyFreeBusyStatus","Free" , 
"calendar", NULL, NULL);
-               else
-                       convert_vevent_property_to_updatexml (msg, "LegacyFreeBusyStatus","Busy" , 
"calendar", NULL, NULL);
-       }
-
-       org_email_address = e_ews_collect_organizer (icalcomp);
-       if (org_email_address && g_ascii_strcasecmp (org_email_address, 
modify_data->cbews->priv->user_email)) {
-               e_ews_message_end_item_change (msg);
-               return;
-       }
-       /* Update other properties allowed only for meeting organizers*/
-       /*meeting dates*/
-       dtstart = icalcomponent_get_dtstart (icalcomp);
-       dtend = icalcomponent_get_dtend (icalcomp);
-       dtstart_old = icalcomponent_get_dtstart (icalcomp_old);
-       dtend_old = icalcomponent_get_dtend (icalcomp_old);
-       if (icaltime_compare (dtstart, dtstart_old) != 0) {
-               e_ews_message_start_set_item_field (msg, "Start", "calendar","CalendarItem");
-               ewscal_set_time (msg, "Start", &dtstart, FALSE);
-               e_ews_message_end_set_item_field (msg);
-               dt_changed = TRUE;
-       }
-
-       if (icaltime_compare (dtend, dtend_old) != 0) {
-               e_ews_message_start_set_item_field (msg, "End", "calendar", "CalendarItem");
-               ewscal_set_time (msg, "End", &dtend, FALSE);
-               e_ews_message_end_set_item_field (msg);
-               dt_changed = TRUE;
-       }
-
-       /*Check for All Day Event*/
-       if (dt_changed) {
-               if (icaltime_is_date (dtstart))
-                       convert_vevent_property_to_updatexml (msg, "IsAllDayEvent", "true", "calendar", NULL, 
NULL);
-               else
-                       convert_vevent_property_to_updatexml (msg, "IsAllDayEvent", "false", "calendar", 
NULL, NULL);
-       }
-
-       /*need to test it*/
-       e_ews_collect_attendees (icalcomp, &required, &optional, &resource);
-       if (required != NULL) {
-               e_ews_message_start_set_item_field (msg, "RequiredAttendees", "calendar", "CalendarItem");
-
-               add_attendees_list_to_message (msg, "RequiredAttendees", required);
-               g_slist_free (required);
-
-               e_ews_message_end_set_item_field (msg);
-       }
-       if (optional != NULL) {
-               e_ews_message_start_set_item_field (msg, "OptionalAttendees", "calendar", "CalendarItem");
-
-               add_attendees_list_to_message (msg, "OptionalAttendees", optional);
-               g_slist_free (optional);
-
-               e_ews_message_end_set_item_field (msg);
-       }
-       if (resource != NULL) {
-               e_ews_message_start_set_item_field (msg, "Resources", "calendar", "CalendarItem");
-
-               add_attendees_list_to_message (msg, "Resources", resource);
-               g_slist_free (resource);
-
-               e_ews_message_end_set_item_field (msg);
-       }
-
-       /* Recurrence */
-       value = NULL; old_value = NULL;
-       prop = icalcomponent_get_first_property (icalcomp_old, ICAL_RRULE_PROPERTY);
-       if (prop != NULL)
-               old_value = icalproperty_get_value_as_string (prop);
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
-       if (prop != NULL)
-               value = icalproperty_get_value_as_string (prop);
-
-       if (prop != NULL && g_strcmp0 (value, old_value)) {
-               e_ews_message_start_set_item_field (msg, "Recurrence", "calendar", "CalendarItem");
-               ewscal_set_reccurence (msg, prop, &dtstart);
-               e_ews_message_end_set_item_field (msg);
-       }
-
-       /* We have to cast these because libical puts a const pointer into the
-        * icaltimetype, but its basic read-only icaltimezone_foo() functions
-        * take a non-const pointer! */
-       if (e_ews_connection_satisfies_server_version (modify_data->cbews->priv->cnc, E_EWS_EXCHANGE_2010)) {
-               const gchar *ical_location;
-               const gchar *msdn_location;
-               icaltimezone *tzid;
-               GSList *msdn_locations = NULL;
-               GSList *tzds = NULL;
-
-               if (dtstart.zone != NULL) {
-                       tzid = (icaltimezone *) dtstart.zone;
-                       ical_location = icaltimezone_get_location (tzid);
-                       msdn_location = e_cal_backend_ews_tz_util_get_msdn_equivalent (ical_location);
-                       msdn_locations = g_slist_append (msdn_locations, (gchar *) msdn_location);
-               }
-
-               if (dtend.zone != NULL) {
-                       tzid = (icaltimezone *) dtend.zone;
-                       ical_location = icaltimezone_get_location (tzid);
-                       msdn_location = e_cal_backend_ews_tz_util_get_msdn_equivalent (ical_location);
-                       msdn_locations = g_slist_append (msdn_locations, (gchar *) msdn_location);
-               }
-
-               if (e_ews_connection_get_server_time_zones_sync (
-                               modify_data->cbews->priv->cnc,
-                               EWS_PRIORITY_MEDIUM,
-                               msdn_locations,
-                               &tzds,
-                               NULL,
-                               NULL)) {
-                       GSList *tmp;
-
-                       tmp = tzds;
-                       if (dtstart.zone != NULL) {
-                               e_ews_message_start_set_item_field (msg, "StartTimeZone", "calendar", 
"CalendarItem");
-                               ewscal_set_timezone (msg, "StartTimeZone", tmp->data);
-                               e_ews_message_end_set_item_field (msg);
-
-                               /*
-                                * Exchange server is smart enough to return the list of
-                                * ServerTimeZone without repeated elements
-                                */
-                               if (tmp->next != NULL)
-                                       tmp = tmp->next;
-                       }
-
-                       if (dtend.zone != NULL) {
-                               e_ews_message_start_set_item_field (msg, "EndTimeZone", "calendar", 
"CalendarItem");
-                               ewscal_set_timezone (msg, "EndTimeZone", tmp->data);
-                               e_ews_message_end_set_item_field (msg);
-                       }
-               }
-
-               g_slist_free (msdn_locations);
-               g_slist_free_full (tzds, (GDestroyNotify) e_ews_calendar_time_zone_definition_free);
-       } else {
-               e_ews_message_start_set_item_field (msg, "MeetingTimeZone", "calendar", "CalendarItem");
-               ewscal_set_meeting_timezone (
-                       msg,
-                       (icaltimezone *)(dtstart.zone ? dtstart.zone : 
modify_data->cbews->priv->default_zone));
-               e_ews_message_end_set_item_field (msg);
-       }
-
-       e_ews_message_end_item_change (msg);
-}
-
-static void
-convert_vtodo_property_to_updatexml (ESoapMessage *msg,
-                                     const gchar *name,
-                                     const gchar *value,
-                                     const gchar *prefix,
-                                     const gchar *attr_name,
-                                     const gchar *attr_value)
-{
-       e_ews_message_start_set_item_field (msg, name, prefix, "Task");
-       e_ews_message_write_string_parameter_with_attribute (msg, name, NULL, value, attr_name, attr_value);
-       e_ews_message_end_set_item_field (msg);
-}
-
-static void
-convert_vtodo_component_to_updatexml (ESoapMessage *msg,
-                                      gpointer user_data)
-{
-       EwsModifyData *modify_data = user_data;
-       icalcomponent *icalcomp = e_cal_component_get_icalcomponent (modify_data->comp);
-       icalproperty *prop;
-       icaltimetype dt;
-       gint value;
-       gchar buffer[16];
-
-       e_ews_message_start_item_change (
-               msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
-               modify_data->itemid, modify_data->changekey, 0);
-
-       convert_vtodo_property_to_updatexml (msg, "Subject", icalcomponent_get_summary (icalcomp), "item", 
NULL, NULL);
-
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
-       if (prop) {
-               icalproperty_class classify = icalproperty_get_class (prop);
-               if (classify == ICAL_CLASS_PUBLIC) {
-                       convert_vtodo_property_to_updatexml (msg, "Sensitivity", "Normal", "item", NULL, 
NULL);
-               } else if (classify == ICAL_CLASS_PRIVATE) {
-                       convert_vtodo_property_to_updatexml (msg, "Sensitivity", "Private", "item", NULL, 
NULL);
-               } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
-                       convert_vtodo_property_to_updatexml (msg, "Sensitivity", "Personal", "item", NULL, 
NULL);
-               }
-       }
-
-       convert_vtodo_property_to_updatexml (msg, "Body", icalcomponent_get_description (icalcomp), "item", 
"BodyType", "Text");
-
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_DUE_PROPERTY);
-       if (prop) {
-               dt = icalproperty_get_due (prop);
-               e_ews_message_start_set_item_field (msg, "DueDate", "task", "Task");
-               ewscal_set_time (msg, "DueDate", &dt, TRUE);
-               e_ews_message_end_set_item_field (msg);
-       } else {
-               e_ews_message_add_delete_item_field (msg, "DueDate", "task");
-       }
-
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
-       if (prop) {
-               value = icalproperty_get_percentcomplete (prop);
-               snprintf (buffer, 16, "%d", value);
-               e_ews_message_start_set_item_field (msg, "PercentComplete", "task", "Task");
-               e_ews_message_write_string_parameter (msg, "PercentComplete", NULL, buffer);
-               e_ews_message_end_set_item_field (msg);
-       }
-
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
-       if (prop) {
-               dt = icalproperty_get_dtstart (prop);
-               e_ews_message_start_set_item_field (msg, "StartDate", "task", "Task");
-               ewscal_set_time (msg, "StartDate", &dt, TRUE);
-               e_ews_message_end_set_item_field (msg);
-       } else {
-               e_ews_message_add_delete_item_field (msg, "StartDate", "task");
-       }
-
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_STATUS_PROPERTY);
-       if (prop) {
-               switch (icalproperty_get_status (prop)) {
-               case ICAL_STATUS_INPROCESS:
-                       convert_vtodo_property_to_updatexml (msg, "Status", "InProgress", "task", NULL, NULL);
-                       break;
-               case ICAL_STATUS_COMPLETED:
-                       convert_vtodo_property_to_updatexml (msg, "Status", "Completed", "task", NULL, NULL);
-                       break;
-               case ICAL_STATUS_NONE:
-               case ICAL_STATUS_NEEDSACTION:
-                       convert_vtodo_property_to_updatexml (msg, "Status", "NotStarted", "task", NULL, NULL);
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       /* Categories */
-       convert_component_categories_to_updatexml (modify_data->comp, msg, "Task");
-
-       e_ews_message_end_item_change (msg);
-}
-
-static void
-convert_vjournal_property_to_updatexml (ESoapMessage *msg,
-                                     const gchar *name,
-                                     const gchar *value,
-                                     const gchar *prefix,
-                                     const gchar *attr_name,
-                                     const gchar *attr_value)
-{
-       e_ews_message_start_set_item_field (msg, name, prefix, "Message");
-       e_ews_message_write_string_parameter_with_attribute (msg, name, NULL, value, attr_name, attr_value);
-       e_ews_message_end_set_item_field (msg);
-}
-
-static void
-convert_vjournal_component_to_updatexml (ESoapMessage *msg,
-                                        gpointer user_data)
-{
-       EwsModifyData *modify_data = user_data;
-       icalcomponent *icalcomp = e_cal_component_get_icalcomponent (modify_data->comp);
-       icalproperty *prop;
-       const gchar *text;
-
-       e_ews_message_start_item_change (
-               msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
-               modify_data->itemid, modify_data->changekey, 0);
-
-       convert_vjournal_property_to_updatexml (msg, "ItemClass", "IPM.StickyNote", "item", NULL, NULL);
-       convert_vjournal_property_to_updatexml (msg, "Subject", icalcomponent_get_summary (icalcomp), "item", 
NULL, NULL);
-
-       prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
-       if (prop) {
-               icalproperty_class classify = icalproperty_get_class (prop);
-               if (classify == ICAL_CLASS_PUBLIC) {
-                       convert_vjournal_property_to_updatexml (msg, "Sensitivity", "Normal", "item", NULL, 
NULL);
-               } else if (classify == ICAL_CLASS_PRIVATE) {
-                       convert_vjournal_property_to_updatexml (msg, "Sensitivity", "Private", "item", NULL, 
NULL);
-               } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
-                       convert_vjournal_property_to_updatexml (msg, "Sensitivity", "Personal", "item", NULL, 
NULL);
-               }
-       }
-
-       text = icalcomponent_get_description (icalcomp);
-       if (!text || !*text)
-               text = icalcomponent_get_summary (icalcomp);
-
-       convert_vjournal_property_to_updatexml (msg, "Body", text, "item", "BodyType", "Text");
-
-       /* Categories */
-       convert_component_categories_to_updatexml (modify_data->comp, msg, "Message");
-
-       e_ews_message_end_item_change (msg);
-}
-
-static void
-convert_component_to_updatexml (ESoapMessage *msg,
-                                gpointer user_data)
-{
-       EwsModifyData *modify_data = user_data;
-       icalcomponent *icalcomp = e_cal_component_get_icalcomponent (modify_data->comp);
-
-       switch (icalcomponent_isa (icalcomp)) {
-       case ICAL_VEVENT_COMPONENT:
-               convert_vevent_component_to_updatexml (msg, user_data);
-               break;
-       case ICAL_VTODO_COMPONENT:
-               convert_vtodo_component_to_updatexml (msg, user_data);
-               break;
-       case ICAL_VJOURNAL_COMPONENT:
-               convert_vjournal_component_to_updatexml (msg, user_data);
-               break;
-       default:
-               break;
-       }
+       e_cal_backend_ews_async_data_free (modify_data);
 }
 
 static void
@@ -2652,7 +1805,7 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
                                  const gchar *calobj,
                                  ECalObjModType mod)
 {
-       EwsModifyData *modify_data;
+       EwsCalendarAsyncData *modify_data;
        ECalBackendEws *cbews;
        ECalBackendEwsPrivate *priv;
        icalcomponent_kind kind;
@@ -2662,7 +1815,7 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
        struct icaltimetype current;
        GError *error = NULL;
        GSList *original_attachments = NULL, *modified_attachments = NULL, *added_attachments = NULL, 
*removed_attachments = NULL, *removed_attachments_ids = NULL, *i;
-       EwsAttachmentsData *attach_data;
+       EwsCalendarAsyncData *attach_data;
        struct TzidCbData cbd;
 
        e_data_cal_error_if_fail (E_IS_CAL_BACKEND_EWS (backend), InvalidArg);
@@ -2780,16 +1933,15 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
                EwsId *item_id = g_new0 (EwsId, 1);
                item_id->id = itemid;
                item_id->change_key = changekey;
-               attach_data = g_new0 (EwsAttachmentsData, 1);
+               attach_data = g_new0 (EwsCalendarAsyncData, 1);
 
                attach_data->cbews = g_object_ref (cbews);
                attach_data->comp = g_object_ref (comp);
-               attach_data->cb_type = 2;
-               attach_data->oldcomp = g_object_ref (oldcomp);
+               attach_data->cb_type = E_EWS_ATTACHMENT_TYPE_UPDATE;
+               attach_data->extra_comp = g_object_ref (oldcomp);
                attach_data->cal = g_object_ref (cal);
                attach_data->context = 0;
-               attach_data->itemid = itemid;
-               attach_data->changekey = changekey;
+               attach_data->item_id = itemid;
 
                e_cal_component_get_uid (oldcomp, &old_uid);
                if (old_uid)
@@ -2833,17 +1985,25 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
                g_free (item_id);
 
        } else {
+               EwsCalendarConvertData convert_data;
                const gchar *send_meeting_invitations;
                const gchar *send_or_save;
 
-               modify_data = g_new0 (EwsModifyData, 1);
+               modify_data = g_new0 (EwsCalendarAsyncData, 1);
                modify_data->cbews = g_object_ref (cbews);
                modify_data->comp = g_object_ref (comp);
-               modify_data->oldcomp = g_object_ref (oldcomp);
+               modify_data->extra_comp = g_object_ref (oldcomp);
                modify_data->cal = g_object_ref (cal);
                modify_data->context = context;
-               modify_data->itemid = itemid;
-               modify_data->changekey = changekey;
+               modify_data->item_id = itemid;
+
+               convert_data.connection = cbews->priv->cnc;
+               convert_data.user_email = cbews->priv->user_email;
+               convert_data.comp = comp;
+               convert_data.old_comp = oldcomp;
+               convert_data.item_id = itemid;
+               convert_data.change_key = changekey;
+               convert_data.default_zone = cbews->priv->default_zone;
 
                if (e_cal_component_has_attendees (comp)) {
                        send_meeting_invitations = "SendToAllAndSaveCopy";
@@ -2860,8 +2020,8 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
                        send_or_save,
                        send_meeting_invitations,
                        priv->folder_id,
-                       convert_component_to_updatexml,
-                       modify_data,
+                       e_cal_backend_ews_convert_component_to_updatexml,
+                       &convert_data,
                        cancellable,
                        ews_cal_modify_object_cb,
                        modify_data);
@@ -2878,12 +2038,6 @@ exit:
        }
 }
 
-typedef struct {
-       const gchar *response_type;
-       const gchar *item_id;
-       const gchar *change_key;
-} EwsAcceptData;
-
 static void
 e_ews_receive_objects_no_exchange_mail (ECalBackendEws *cbews,
                                         icalcomponent *subcomp,
@@ -2891,12 +2045,12 @@ e_ews_receive_objects_no_exchange_mail (ECalBackendEws *cbews,
                                         GCancellable *cancellable,
                                         GError **error)
 {
-       EwsConvertData *convert_data;
+       EwsCalendarConvertData convert_data;
        EwsFolderId *fid;
 
-       convert_data = g_new0 (EwsConvertData, 1);
-       convert_data->cbews = g_object_ref (cbews);
-       convert_data->icalcomp = subcomp;
+       convert_data.connection = cbews->priv->cnc;
+       convert_data.icalcomp = subcomp;
+       convert_data.default_zone = cbews->priv->default_zone;
 
        fid = e_ews_folder_id_new (cbews->priv->folder_id, NULL, FALSE);
 
@@ -2906,8 +2060,8 @@ e_ews_receive_objects_no_exchange_mail (ECalBackendEws *cbews,
                "SaveOnly",
                "SendToNone",
                fid,
-               convert_calcomp_to_xml,
-               convert_data,
+               e_cal_backend_ews_convert_calcomp_to_xml,
+               &convert_data,
                ids,
                cancellable,
                error);
@@ -2951,49 +2105,155 @@ e_ews_get_current_user_meeting_reponse (icalcomponent *icalcomp,
 }
 
 static void
-prepare_accept_item_request (ESoapMessage *msg,
-                             gpointer user_data)
+ews_cal_do_method_request_publish_reply (ECalBackendEws *cbews,
+                                        ECalComponent *comp,
+                                        icalcomponent *subcomp,
+                                        const gchar *response_type,
+                                        GCancellable *cancellable,
+                                        GError **error)
 {
-       EwsAcceptData *data = user_data;
-       const gchar *response_type = data->response_type;
-
-       /* FORMAT OF A SAMPLE SOAP MESSAGE: 
http://msdn.microsoft.com/en-us/library/aa566464%28v=exchg.140%29.aspx
-        * Accept and Decline meeting have same method code (10032)
-        * The real status is reflected at Attendee property PARTSTAT
-        * need to find current user as attendee and make a decision what to do.
-        * Prepare AcceptItem node in the SOAP message */
-
-       if (response_type && !g_ascii_strcasecmp (response_type, "ACCEPTED"))
-               e_soap_message_start_element (msg, "AcceptItem", NULL, NULL);
-       else if (response_type && !g_ascii_strcasecmp (response_type, "DECLINED"))
-               e_soap_message_start_element (msg, "DeclineItem", NULL, NULL);
-       else
-               e_soap_message_start_element (msg, "TentativelyAcceptItem", NULL, NULL);
+       GError *local_error = NULL;
+       gchar *item_id = NULL;
+       gchar *change_key = NULL;
+       gchar *mail_id = NULL;
+       gint pass = 0;
 
-       e_soap_message_start_element (msg, "ReferenceItemId", NULL, NULL);
-       e_soap_message_add_attribute (msg, "Id", data->item_id, NULL, NULL);
-       e_soap_message_add_attribute (msg, "ChangeKey", data->change_key, NULL, NULL);
-       e_soap_message_end_element (msg); // "ReferenceItemId"
+       ews_cal_component_get_calendar_item_accept_id (comp, &item_id, &change_key, &mail_id);
 
-       /* end of "AcceptItem" */
-       e_soap_message_end_element (msg);
-}
+       while (pass < 2) {
+               GSList *ids = NULL;
 
-static void
-prepare_set_free_busy_status (ESoapMessage *msg,
-                              gpointer user_data)
-{
-       EwsAcceptData *data = user_data;
+               /*in case we do not have item id we will create item with mime content only*/
+               if (item_id == NULL) {
+                       e_ews_receive_objects_no_exchange_mail (cbews, subcomp, &ids, cancellable, 
&local_error);
+               } else {
+                       EwsCalendarConvertData convert_data;
+
+                       convert_data.response_type = (gchar *) response_type;
+                       convert_data.item_id = item_id;
+                       convert_data.change_key = change_key;
+
+                       e_ews_connection_create_items_sync (
+                               cbews->priv->cnc,
+                               EWS_PRIORITY_MEDIUM,
+                               "SendAndSaveCopy",
+                               NULL,
+                               NULL,
+                               e_cal_backend_ews_prepare_accept_item_request,
+                               &convert_data,
+                               &ids,
+                               cancellable,
+                               &local_error);
+               }
+
+               if (pass == 0 && mail_id != NULL && item_id != NULL &&
+                   g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_ITEMNOTFOUND)) {
+                       /*
+                        * maybe the associated accept calendar item changed
+                        * on the server, thus retry with updated values
+                        */
+                       GSList *ids = NULL, *my_ids = NULL;
+
+                       g_clear_error (&local_error);
+
+                       my_ids = g_slist_append (my_ids, mail_id);
+
+                       if (e_ews_connection_get_items_sync (
+                               cbews->priv->cnc,
+                               EWS_PRIORITY_MEDIUM,
+                               my_ids,
+                               "AllProperties",
+                               NULL,
+                               FALSE,
+                               NULL,
+                               E_EWS_BODY_TYPE_ANY,
+                               &ids,
+                               NULL,
+                               NULL,
+                               cancellable,
+                               &local_error) &&
+                           ids != NULL &&
+                           ids->data != NULL) {
+                               EEwsItem *item = ids->data;
+                               const EwsId *id = e_ews_item_get_id (item);
+
+                               if (id != NULL && g_strcmp0 (id->id, mail_id) == 0) {
+                                       const EwsId *cal_item_accepted_id;
+
+                                       cal_item_accepted_id = e_ews_item_get_calendar_item_accept_id (item);
+                                       if (cal_item_accepted_id != NULL) {
+                                               g_clear_error (&local_error);
+                                               pass++;
+
+                                               g_free (item_id);
+                                               g_free (change_key);
+
+                                               item_id = g_strdup (cal_item_accepted_id->id);
+                                               change_key = g_strdup (cal_item_accepted_id->change_key);
+                                       }
+                               }
+                       }
+
+                       g_slist_free (my_ids);
+                       g_slist_free_full (ids, g_object_unref);
+
+                       if (pass == 0)
+                               break;
+               } else {
+                       break;
+               }
+       }
+
+       if (error == NULL) {
+               icalproperty *transp;
+
+               transp = icalcomponent_get_first_property (subcomp, ICAL_TRANSP_PROPERTY);
+
+               if (g_strcmp0 (icalproperty_get_value_as_string (transp), "TRANSPARENT") == 0 &&
+                   g_strcmp0 (response_type, "ACCEPTED") == 0) {
+                       EwsCalendarConvertData convert_data;
+                       GSList *l, *ids = NULL;
+
+                       /*
+                        * user can accept meeting but mark it as free in it's calendar
+                        * the following code is updating the exchange meeting status to free
+                        */
+                       for (l = ids; l != NULL; l = g_slist_next (l)) {
+                               EEwsItem *item = l->data;
+
+                               if (item != NULL) {
+                                       const EwsId *id = e_ews_item_get_id (item);
 
-       e_ews_message_start_item_change (msg, E_EWS_ITEMCHANGE_TYPE_ITEM, data->item_id, data->change_key, 0);
+                                       convert_data.item_id = id->id;
+                                       convert_data.change_key = id->change_key;
+                                       break;
+                               }
+                       }
 
-       e_ews_message_start_set_item_field (msg, "LegacyFreeBusyStatus", "calendar", "CalendarItem");
+                       e_ews_connection_update_items_sync (
+                               cbews->priv->cnc,
+                               EWS_PRIORITY_MEDIUM,
+                               "AlwaysOverwrite",
+                               NULL,
+                               "SendToNone",
+                               NULL,
+                               e_cal_backend_ews_prepare_set_free_busy_status,
+                               &convert_data,
+                               &ids,
+                               cancellable,
+                               &local_error);
+               }
+       }
 
-       e_ews_message_write_string_parameter (msg, "LegacyFreeBusyStatus", NULL, "Free");
+       if (error != NULL)
+               g_propagate_error (error, local_error);
 
-       e_ews_message_end_set_item_field (msg);
+       g_free (item_id);
+       g_free (change_key);
+       g_free (mail_id);
 
-       e_ews_message_end_item_change (msg);
+       /*We have to run sync before any other operations */
+       ews_start_sync (cbews);
 }
 
 static void
@@ -3009,7 +2269,6 @@ e_cal_backend_ews_receive_objects (ECalBackend *backend,
        icalcomponent *icalcomp, *subcomp;
        GError *error = NULL;
        icalproperty_method method;
-       EwsAcceptData *accept_data;
 
        cbews = E_CAL_BACKEND_EWS (backend);
        priv = cbews->priv;
@@ -3046,115 +2305,26 @@ e_cal_backend_ews_receive_objects (ECalBackend *backend,
        while (subcomp) {
                ECalComponent *comp = e_cal_component_new ();
                const gchar *response_type;
-               gchar *item_id = NULL, *change_key = NULL, *mail_id = NULL;
-               GSList *ids = NULL, *l;
-               icalproperty *transp, *summary;
-               gchar **split_subject;
-               gint pass = 0;
 
                /* duplicate the ical component */
                e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (subcomp));
 
                /*getting a data for meeting request response*/
-               response_type = e_ews_get_current_user_meeting_reponse (e_cal_component_get_icalcomponent 
(comp), priv->user_email);
-               ews_cal_component_get_calendar_item_accept_id (comp, &item_id, &change_key, &mail_id);
+               response_type = e_ews_get_current_user_meeting_reponse (
+                       e_cal_component_get_icalcomponent (comp),
+                       priv->user_email);
 
                switch (method) {
                        case ICAL_METHOD_REQUEST:
                        case ICAL_METHOD_PUBLISH:
                        case ICAL_METHOD_REPLY:
-                               accept_data = g_new0 (EwsAcceptData, 1);
-                               accept_data->response_type = response_type;
-                               accept_data->item_id = item_id;
-                               accept_data->change_key = change_key;
-
-                               while (pass < 2) {
-                                       /*in case we do not have item id we will create item with mime 
content only*/
-                                       if (item_id == NULL)
-                                               e_ews_receive_objects_no_exchange_mail (cbews, subcomp, &ids, 
cancellable, &error);
-                                       else
-                                               e_ews_connection_create_items_sync (
-                                                       priv->cnc, EWS_PRIORITY_MEDIUM,
-                                                       "SendAndSaveCopy",
-                                                       NULL, NULL,
-                                                       prepare_accept_item_request,
-                                                       accept_data,
-                                                       &ids, cancellable, &error);
-                                       if (pass == 0 && mail_id && item_id &&
-                                           g_error_matches (error, EWS_CONNECTION_ERROR, 
EWS_CONNECTION_ERROR_ITEMNOTFOUND)) {
-                                               /* maybe the associated accept calendar item changed
-                                                  on the server, thus retry with updated values */
-                                               GSList *my_ids;
-
-                                               my_ids = g_slist_append (NULL, mail_id);
-                                               ids = NULL;
-                                               if (e_ews_connection_get_items_sync (priv->cnc, 
EWS_PRIORITY_MEDIUM, my_ids,
-                                                               "AllProperties", NULL, FALSE, NULL, 
E_EWS_BODY_TYPE_ANY, &ids, NULL, NULL,
-                                                               cancellable, NULL)
-                                                   && ids && ids->data) {
-                                                       EEwsItem *item = ids->data;
-                                                       if (e_ews_item_get_id (item) &&
-                                                           g_strcmp0 (e_ews_item_get_id (item)->id, mail_id) 
== 0) {
-                                                               const EwsId *calendar_item_accept_id = 
e_ews_item_get_calendar_item_accept_id (item);
-
-                                                               if (calendar_item_accept_id) {
-                                                                       g_clear_error (&error);
-                                                                       pass++;
-
-                                                                       g_free (item_id);
-                                                                       g_free (change_key);
-                                                                       item_id = g_strdup 
(calendar_item_accept_id->id);
-                                                                       change_key = g_strdup 
(calendar_item_accept_id->change_key);
-
-                                                                       accept_data->item_id = item_id;
-                                                                       accept_data->change_key = change_key;
-                                                               }
-                                                       }
-                                               }
-
-                                               g_slist_free (my_ids);
-                                               g_slist_free_full (ids, g_object_unref);
-                                               ids = NULL;
-
-                                               if (pass == 0)
-                                                       break;
-                                       } else {
-                                               break;
-                                       }
-                               }
-                               if (!error) {
-                                       transp = icalcomponent_get_first_property (subcomp, 
ICAL_TRANSP_PROPERTY);
-                                       if (!g_strcmp0 (icalproperty_get_value_as_string (transp), 
"TRANSPARENT") &&
-                                           !g_strcmp0 (response_type, "ACCEPTED")) {
-                                               /*user can accept meeting but mark it as free in it's calendar
-                                                the following code is updating the exchange meeting status 
to free */
-                                               for (l = ids; l != NULL; l = g_slist_next (l)) {
-                                                       EEwsItem *item = (EEwsItem *) l->data;
-                                                       if (item) {
-                                                               accept_data->item_id = e_ews_item_get_id 
(item)->id;
-                                                               accept_data->change_key = e_ews_item_get_id 
(item)->change_key;
-                                                               break;
-                                                       }
-                                               }
-                                               e_ews_connection_update_items_sync (
-                                                       priv->cnc,
-                                                       EWS_PRIORITY_MEDIUM,
-                                                       "AlwaysOverwrite",
-                                                       NULL, "SendToNone",
-                                                       NULL,
-                                                       prepare_set_free_busy_status,
-                                                       accept_data,
-                                                       &ids,
-                                                       cancellable,
-                                                       &error);
-                                       }
-                               }
-                               g_free (item_id);
-                               g_free (change_key);
-                               g_free (mail_id);
-                               g_free (accept_data);
-                               /*We have to run sync before any other operations */
-                               ews_start_sync (cbews);
+                               ews_cal_do_method_request_publish_reply (
+                                       cbews,
+                                       comp,
+                                       subcomp,
+                                       response_type,
+                                       cancellable,
+                                       &error);
                                break;
                        case ICAL_METHOD_CANCEL: {
                                const gchar *uid = NULL;
@@ -3170,13 +2340,21 @@ e_cal_backend_ews_receive_objects (ECalBackend *backend,
                                break;
                        }
                        case ICAL_METHOD_COUNTER:
-                               /*this is a new time proposal mail from one of the attendees
+                               /*
+                                * this is a new time proposal mail from one of the attendees
                                 * if we decline the proposal, nothing have to be done
-                                * if we accept it we will call to modify_object */
-                               if (!g_strcmp0 (response_type, "ACCEPTED")) {
-                                       /*we have to edit the meeting subject to remove exchange header*/
+                                * if we accept it we will call to modify_object
+                                */
+                               if (g_strcmp0 (response_type, "ACCEPTED") == 0) {
+                                       gchar **split_subject;
+                                       icalproperty *summary;
+
+                                       /*
+                                        * we have to edit the meeting subject to remove exchange header
+                                        */
                                        summary = icalcomponent_get_first_property (subcomp, 
ICAL_SUMMARY_PROPERTY);
-                                       split_subject  = g_strsplit (icalproperty_get_value_as_string 
(summary), ":", -1);
+                                       split_subject =
+                                               g_strsplit (icalproperty_get_value_as_string (summary), ":", 
-1);
                                        icalproperty_set_value_from_string (summary, split_subject[1] , "NO");
                                        g_strfreev (split_subject);
 
@@ -3186,6 +2364,7 @@ e_cal_backend_ews_receive_objects (ECalBackend *backend,
                        default:
                                break;
                }
+
                g_object_unref (comp);
                subcomp = icalcomponent_get_next_component (icalcomp, kind);
        }
@@ -3219,34 +2398,6 @@ e_cal_get_meeting_cancellation_comment (ECalComponent *comp)
        return NULL;
 }
 
-static icaltimezone *
-e_cal_get_timezone_from_ical_component (ECalBackend *backend,
-                                        icalcomponent *comp)
-{
-       ETimezoneCache *timezone_cache;
-       icalproperty *prop;
-       icalparameter *param;
-
-       timezone_cache = E_TIMEZONE_CACHE (backend);
-
-       prop = icalcomponent_get_first_property (
-               comp, ICAL_DTSTART_PROPERTY);
-       param = icalproperty_get_first_parameter (
-               prop, ICAL_TZID_PARAMETER);
-
-       if (param != NULL) {
-               const gchar *tzid;
-
-               tzid = icalparameter_get_tzid (param);
-
-               return e_timezone_cache_get_timezone (timezone_cache, tzid);
-       }
-
-       g_warning ("EEE Cant figure the relevant timezone of the component\n");
-
-       return NULL;
-}
-
 static void
 ewscal_send_cancellation_email (ECalBackend *backend,
                                 EEwsConnection *cnc,
@@ -3277,7 +2428,8 @@ ewscal_send_cancellation_email (ECalBackend *backend,
        prop = icalcomponent_get_first_property (vevent, ICAL_METHOD_PROPERTY);
        if (prop != NULL) icalcomponent_remove_property (vevent, prop);
        dt = icalcomponent_get_dtstart (vevent);
-       icaltz = (icaltimezone *)(dt.zone ? dt.zone : e_cal_get_timezone_from_ical_component (backend, 
vevent));
+       icaltz = (icaltimezone *)
+               (dt.zone ? dt.zone : e_cal_backend_ews_get_timezone_from_ical_component (backend, vevent));
        vtz = icaltimezone_get_component (icaltz);
        icalcomponent_add_component (vcal, icalcomponent_new_clone (vtz));
        icalcomponent_add_component (vcal, vevent);
@@ -4370,65 +3522,13 @@ exit:
        e_data_cal_respond_refresh (cal, context, error);
 }
 
-typedef struct {
-       ECalBackendEws *cbews;
-       EDataCal *cal;
-       guint32 context;
-       GSList *users;
-       time_t start;
-       time_t end;
-} EwsFreeBusyData;
-
-static void
-prepare_free_busy_request (ESoapMessage *msg,
-                           gpointer user_data)
-{
-       EwsFreeBusyData *free_busy_data = user_data;
-       GSList *addr;
-       icaltimetype t_start, t_end;
-       icaltimezone *utc_zone = icaltimezone_get_utc_timezone ();
-
-       ewscal_set_availability_timezone (msg, utc_zone);
-
-       e_soap_message_start_element (msg, "MailboxDataArray", "messages", NULL);
-
-       for (addr = free_busy_data->users; addr; addr = addr->next) {
-               e_soap_message_start_element (msg, "MailboxData", NULL, NULL);
-
-               e_soap_message_start_element (msg, "Email", NULL, NULL);
-               e_ews_message_write_string_parameter (msg, "Address", NULL, addr->data);
-               e_soap_message_end_element (msg); /* "Email" */
-
-               e_ews_message_write_string_parameter (msg, "AttendeeType", NULL, "Required");
-               e_ews_message_write_string_parameter (msg, "ExcludeConflicts", NULL, "false");
-
-               e_soap_message_end_element (msg); /* "MailboxData" */
-       }
-
-       e_soap_message_end_element (msg); /* "MailboxDataArray" */
-
-       e_soap_message_start_element (msg, "FreeBusyViewOptions", NULL, NULL);
-
-       e_soap_message_start_element (msg, "TimeWindow", NULL, NULL);
-       t_start = icaltime_from_timet_with_zone (free_busy_data->start, 0, utc_zone);
-       t_end = icaltime_from_timet_with_zone (free_busy_data->end, 0, utc_zone);
-       ewscal_set_time (msg, "StartTime", &t_start, FALSE);
-       ewscal_set_time (msg, "EndTime", &t_end, FALSE);
-       e_soap_message_end_element (msg); /* "TimeWindow" */
-
-       e_ews_message_write_string_parameter (msg, "MergedFreeBusyIntervalInMinutes", NULL, "60");
-       e_ews_message_write_string_parameter (msg, "RequestedView", NULL, "DetailedMerged");
-
-       e_soap_message_end_element (msg); /* "FreeBusyViewOptions" */
-}
-
 static void
 ews_cal_get_free_busy_cb (GObject *obj,
                           GAsyncResult *res,
                           gpointer user_data)
 {
        EEwsConnection *cnc = (EEwsConnection *) obj;
-       EwsFreeBusyData *free_busy_data = user_data;
+       EwsCalendarAsyncData *free_busy_data = user_data;
        GSList *free_busy_sl = NULL, *i;
        GSList *free_busy = NULL, *j;
        GError *error = NULL;
@@ -4451,12 +3551,8 @@ done:
        convert_error_to_edc_error (&error);
        e_data_cal_respond_get_free_busy (free_busy_data->cal, free_busy_data->context, error);
 
-       /* FIXME free free_busy_sl ? */
        g_slist_free_full (free_busy, g_free);
-       g_slist_free_full (free_busy_data->users, g_free);
-       g_object_unref (free_busy_data->cal);
-       g_object_unref (free_busy_data->cbews);
-       g_free (free_busy_data);
+       e_cal_backend_ews_async_data_free (free_busy_data);
 }
 
 static void
@@ -4471,7 +3567,8 @@ e_cal_backend_ews_get_free_busy (ECalBackend *backend,
        ECalBackendEws *cbews = E_CAL_BACKEND_EWS (backend);
        ECalBackendEwsPrivate *priv = cbews->priv;
        GError *error = NULL;
-       EwsFreeBusyData *free_busy_data;
+       EwsCalendarAsyncData *free_busy_data;
+       EwsCalendarConvertData convert_data;
        GSList *users_copy = NULL;
 
        /* make sure we're not offline */
@@ -4495,19 +3592,21 @@ e_cal_backend_ews_get_free_busy (ECalBackend *backend,
        for (; users; users = users->next)
            users_copy = g_slist_append (users_copy, g_strdup (users->data));
 
-       free_busy_data = g_new0 (EwsFreeBusyData, 1);
+       free_busy_data = g_new0 (EwsCalendarAsyncData, 1);
        free_busy_data->cbews = g_object_ref (cbews);
        free_busy_data->cal = g_object_ref (cal);
        free_busy_data->context = context;
        free_busy_data->users = users_copy;
-       free_busy_data->start = start;
-       free_busy_data->end = end;
+
+       convert_data.users = users_copy;
+       convert_data.start = start;
+       convert_data.end = end;
 
        e_ews_connection_get_free_busy (
                priv->cnc,
                EWS_PRIORITY_MEDIUM,
-               prepare_free_busy_request,
-               free_busy_data,
+               e_cal_backend_ews_prepare_free_busy_request,
+               &convert_data,
                cancellable,
                ews_cal_get_free_busy_cb,
                free_busy_data);
diff --git a/src/calendar/e-cal-backend-ews.h b/src/calendar/e-cal-backend-ews.h
index 0959405..48480f3 100644
--- a/src/calendar/e-cal-backend-ews.h
+++ b/src/calendar/e-cal-backend-ews.h
@@ -51,6 +51,15 @@ struct _ECalBackendEwsClass {
 
 GType   e_cal_backend_ews_get_type (void);
 
+const EEwsConnection *
+       e_cal_backend_ews_get_connection                (ECalBackendEws *cbews);
+
+const icaltimezone *
+       e_cal_backend_ews_get_default_zone              (ECalBackendEws *cbews);
+
+const gchar *
+       e_cal_backend_ews_get_user_email                (ECalBackendEws *cbews);
+
 G_END_DECLS
 
 #endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]