Index: servers/groupwise/e-gw-connection.h =================================================================== --- servers/groupwise/e-gw-connection.h (revision 9156) +++ servers/groupwise/e-gw-connection.h (working copy) @@ -126,6 +126,7 @@ char *e_gw_connection_form EGwConnectionStatus e_gw_connection_create_item (EGwConnection *cnc, EGwItem *item, char** id); +EGwConnectionStatus e_gw_connection_create_items (EGwConnection *cnc, EGwItem *item, GSList **ids); EGwConnectionStatus e_gw_connection_get_item (EGwConnection *cnc, const char *container, const char *id, const char *view, EGwItem **item); EGwConnectionStatus e_gw_connection_modify_item (EGwConnection *cnc, const char *id, EGwItem *item); EGwConnectionStatus e_gw_connection_accept_request (EGwConnection *cnc, const char *id, const char *accept_level, const char *accept_comment, const char *recurrence_key); Index: servers/groupwise/e-gw-connection.c =================================================================== --- servers/groupwise/e-gw-connection.c (revision 9156) +++ servers/groupwise/e-gw-connection.c (working copy) @@ -1299,11 +1299,24 @@ e_gw_connection_send_item (EGwConnection } EGwConnectionStatus -e_gw_connection_create_item (EGwConnection *cnc, EGwItem *item, char** id) +e_gw_connection_create_item (EGwConnection *cnc, EGwItem *item, char** id) +{ + GSList *ids = NULL; + EGwConnectionStatus status; + + status = e_gw_connection_create_items (cnc, item, &ids); + + if (status == E_GW_CONNECTION_STATUS_OK) + *id = ids->data; + + return status; +} + +EGwConnectionStatus +e_gw_connection_create_items (EGwConnection *cnc, EGwItem *item, GSList **id_list) { SoupSoapMessage *msg; SoupSoapResponse *response; - SoupSoapParameter *param; EGwConnectionStatus status = E_GW_CONNECTION_STATUS_UNKNOWN; g_return_val_if_fail (E_IS_GW_CONNECTION (cnc), E_GW_CONNECTION_STATUS_INVALID_CONNECTION); @@ -1332,10 +1345,17 @@ e_gw_connection_create_item (EGwConnecti } status = e_gw_connection_parse_response_status (response); - if (status == E_GW_CONNECTION_STATUS_OK) { - param = soup_soap_response_get_first_parameter_by_name (response, "id"); - if (param != NULL) - *id = soup_soap_parameter_get_string_value (param); + if (status == E_GW_CONNECTION_STATUS_OK && id_list) { + SoupSoapParameter *param; + + *id_list = NULL; + /* get the generated ID from the SOAP response */ + // for loop here to populate the list_ids. + for (param = soup_soap_response_get_first_parameter_by_name (response, "id"); + param; param = soup_soap_response_get_next_parameter_by_name (response, param, "id")) { + + *id_list = g_slist_append (*id_list, soup_soap_parameter_get_string_value (param)); + } } else if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION) reauthenticate (cnc); Index: calendar/backends/groupwise/e-cal-backend-groupwise-utils.c =================================================================== --- calendar/backends/groupwise/e-cal-backend-groupwise-utils.c (revision 9156) +++ calendar/backends/groupwise/e-cal-backend-groupwise-utils.c (working copy) @@ -1383,14 +1383,14 @@ e_gw_item_to_cal_component (EGwItem *ite } EGwConnectionStatus -e_gw_connection_send_appointment (ECalBackendGroupwise *cbgw, const char *container, ECalComponent *comp, icalproperty_method method, gboolean all_instances, ECalComponent **created_comp, icalparameter_partstat *pstatus) +e_gw_connection_send_appointment (ECalBackendGroupwise *cbgw, const char *c_gw_id, ECalComponent *comp, icalproperty_method method, gboolean all_instances, ECalComponent **created_comp, icalparameter_partstat *pstatus, gboolean *is_import) { EGwConnection *cnc; EGwConnectionStatus status; icalparameter_partstat partstat; char *item_id = NULL; const char *gw_id; - const char *recurrence_key = NULL; + const char *recurrence_key = NULL, *container; gboolean need_to_get = FALSE, decline = FALSE; ECalComponentVType type; @@ -1400,25 +1400,29 @@ e_gw_connection_send_appointment (ECalBa e_cal_component_commit_sequence (comp); type = e_cal_component_get_vtype (comp); + container = e_cal_backend_groupwise_get_container_id (cbgw); gw_id = e_cal_component_get_gw_id (comp); - switch (type) { + if (gw_id) { + switch (type) { - case E_CAL_COMPONENT_EVENT: - case E_CAL_COMPONENT_TODO: - case E_CAL_COMPONENT_JOURNAL: - if (!g_str_has_suffix (gw_id, container)) { - item_id = g_strconcat (e_cal_component_get_gw_id (comp), GW_EVENT_TYPE_ID, container, NULL); - need_to_get = TRUE; + case E_CAL_COMPONENT_EVENT: + case E_CAL_COMPONENT_TODO: + case E_CAL_COMPONENT_JOURNAL: + if (!g_str_has_suffix (gw_id, container)) { + item_id = g_strconcat (e_cal_component_get_gw_id (comp), GW_EVENT_TYPE_ID, container, NULL); + need_to_get = TRUE; - } - else - item_id = g_strdup (gw_id); - break; - default: - return E_GW_CONNECTION_STATUS_INVALID_OBJECT; - } + } + else + item_id = g_strdup (gw_id); + break; + default: + return E_GW_CONNECTION_STATUS_INVALID_OBJECT; + } + } else if (c_gw_id) + item_id = g_strdup (c_gw_id); if (all_instances) e_cal_component_get_uid (comp, &recurrence_key); @@ -1491,6 +1495,13 @@ e_gw_connection_send_appointment (ECalBa break; } *pstatus = partstat; + + /* The item is not in the calendar, so we need to import the item */ + if (!item_id) { + *is_import = TRUE; + return E_GW_CONNECTION_STATUS_OK; + } + switch (partstat) { ECalComponentTransparency transp; @@ -1549,41 +1560,20 @@ e_gw_connection_send_appointment (ECalBa } EGwConnectionStatus -e_gw_connection_create_appointment (EGwConnection *cnc, const char *container, ECalBackendGroupwise *cbgw, ECalComponent *comp, GSList **id_list) +e_gw_connection_create_appointment (EGwConnection *cnc, const char *container, ECalBackendGroupwise *cbgw, ECalComponent *comp, GSList **id_list, gboolean personal) { EGwItem *item; EGwConnectionStatus status; - icalproperty *icalprop; - gboolean move_cal = FALSE; - icalcomponent *icalcomp; - char *id = NULL; g_return_val_if_fail (E_IS_GW_CONNECTION (cnc), E_GW_CONNECTION_STATUS_INVALID_CONNECTION); g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), E_GW_CONNECTION_STATUS_INVALID_OBJECT); - icalcomp = e_cal_component_get_icalcomponent (comp); - - icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY); - while (icalprop) { - const char *x_name; - - x_name = icalproperty_get_x_name (icalprop); - if (!strcmp (x_name, "X-EVOLUTION-MOVE-CALENDAR")) { - move_cal = TRUE; - break; - } - - icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY); - } - item = e_gw_item_new_from_cal_component (container, cbgw, comp); e_gw_item_set_container_id (item, container); - if (!move_cal) + if (!personal) status = e_gw_connection_send_item (cnc, item, id_list); else { - e_gw_item_set_source (item, "personal"); - status = e_gw_connection_create_item (cnc, item, &id); - *id_list = g_slist_append (*id_list, id); + status = e_gw_connection_create_items (cnc, item, id_list); } g_object_unref (item); Index: calendar/backends/groupwise/e-cal-backend-groupwise.c =================================================================== --- calendar/backends/groupwise/e-cal-backend-groupwise.c (revision 9156) +++ calendar/backends/groupwise/e-cal-backend-groupwise.c (working copy) @@ -130,6 +130,15 @@ e_cal_backend_groupwise_get_categories_b return cbgw->priv->categories_by_id; } +const char * +e_cal_backend_groupwise_get_container_id (ECalBackendGroupwise *cbgw) +{ + + g_return_val_if_fail (E_IS_CAL_BACKEND_GROUPWISE (cbgw), NULL); + + return cbgw->priv->container_id; +} + GHashTable * e_cal_backend_groupwise_get_categories_by_name (ECalBackendGroupwise *cbgw) { @@ -1932,6 +1941,31 @@ sanitize_component (ECalBackendSync *bac g_string_free (str, TRUE); } + +static gboolean +check_for_move (ECalComponent *comp) +{ + gboolean personal = FALSE; + icalcomponent *icalcomp; + icalproperty *icalprop; + + icalcomp = e_cal_component_get_icalcomponent (comp); + icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY); + + while (icalprop) { + const char *x_name; + + x_name = icalproperty_get_x_name (icalprop); + if (!strcmp (x_name, "X-EVOLUTION-MOVE-CALENDAR")) { + personal = TRUE; + break; + } + icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY); + } + + return personal; +} + static ECalBackendSyncStatus e_cal_backend_groupwise_create_object (ECalBackendSync *backend, EDataCal *cal, char **calobj, char **uid) { @@ -1942,6 +1976,7 @@ e_cal_backend_groupwise_create_object (E EGwConnectionStatus status; char *server_uid = NULL; GSList *uid_list = NULL, *l; + gboolean personal = FALSE; int i; cbgw = E_CAL_BACKEND_GROUPWISE (backend); @@ -1972,11 +2007,13 @@ e_cal_backend_groupwise_create_object (E switch (priv->mode) { case CAL_MODE_ANY : case CAL_MODE_REMOTE : + personal = check_for_move (comp); + /* when online, send the item to the server */ - status = e_gw_connection_create_appointment (priv->cnc, priv->container_id, cbgw, comp, &uid_list); + status = e_gw_connection_create_appointment (priv->cnc, priv->container_id, cbgw, comp, &uid_list, personal); if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION) - status = e_gw_connection_create_appointment (priv->cnc, priv->container_id, cbgw, comp, &uid_list); + status = e_gw_connection_create_appointment (priv->cnc, priv->container_id, cbgw, comp, &uid_list, personal); if (status != E_GW_CONNECTION_STATUS_OK) { g_object_unref (comp); @@ -2483,6 +2520,88 @@ change_status (ECalComponent *comp, ical } } + +static ECalBackendSyncStatus +import_items (ECalBackendGroupwise *cbgw, ECalComponent *comp) +{ + EGwConnectionStatus status; + ECalBackendGroupwisePrivate *priv; + GSList *uid_list = NULL; + gboolean personal = TRUE; + + priv = cbgw->priv; + + status = e_gw_connection_create_appointment (priv->cnc, priv->container_id, cbgw, comp, &uid_list, personal); + if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION) + status = e_gw_connection_create_appointment (priv->cnc, priv->container_id, cbgw, comp, &uid_list, personal); + + if (status != E_GW_CONNECTION_STATUS_OK) { + if (status == E_GW_CONNECTION_STATUS_UNKNOWN_USER) + return GNOME_Evolution_Calendar_UnknownUser; + else + return GNOME_Evolution_Calendar_OtherError; + } + + if (g_slist_length (uid_list) == 1) { + char *server_uid, *temp; + + server_uid = (char *) uid_list->data; + sanitize_component ((ECalBackendSync *) cbgw, comp, server_uid); + g_free (server_uid); + + /* if successful, update the cache */ + e_cal_backend_cache_put_component (priv->cache, comp); + + temp = e_cal_component_get_as_string (comp); + e_cal_backend_notify_object_created (E_CAL_BACKEND (cbgw), temp); + g_free (temp); + } else { + EGwConnectionStatus stat; + GSList *l; + GList *list = NULL, *tmp; + GPtrArray *uid_array = g_ptr_array_new (); + guint i; + + for (l = uid_list; l; l = g_slist_next (l)) { + g_ptr_array_add (uid_array, l->data); + } + + /* convert uid_list to GPtrArray and get the items in a list */ + stat = e_gw_connection_get_items_from_ids (priv->cnc, + priv->container_id, + "attachments recipients message recipientStatus default peek", + uid_array, &list); + + if (stat != E_GW_CONNECTION_STATUS_OK || (list == NULL) || (g_list_length (list) == 0)) { + g_ptr_array_free (uid_array, TRUE); + return GNOME_Evolution_Calendar_OtherError; + } + + comp = g_object_ref ( (ECalComponent *) list->data ); + /* convert items into components and add them to the cache */ + for (i=0, tmp = list; tmp ; tmp = g_list_next (tmp), i++) { + ECalComponent *e_cal_comp; + EGwItem *item; + char *temp; + + item = (EGwItem *) tmp->data; + e_cal_comp = e_gw_item_to_cal_component (item, cbgw); + e_cal_component_commit_sequence (e_cal_comp); + sanitize_component ((ECalBackendSync *) cbgw, e_cal_comp, g_ptr_array_index (uid_array, i)); + e_cal_backend_cache_put_component (priv->cache, e_cal_comp); + + temp = e_cal_component_get_as_string (e_cal_comp); + e_cal_backend_notify_object_created (E_CAL_BACKEND (cbgw), temp); + g_free (temp); + + g_object_unref (e_cal_comp); + } + g_ptr_array_free (uid_array, TRUE); + } + + return GNOME_Evolution_Calendar_Success; +} + static ECalBackendSyncStatus receive_object (ECalBackendGroupwise *cbgw, EDataCal *cal, icalcomponent *icalcomp) { @@ -2493,6 +2612,9 @@ receive_object (ECalBackendGroupwise *cb gboolean all_instances = FALSE; icalparameter_partstat pstatus; icalproperty *icalprop; + ECalComponent *cache_comp; + gboolean is_import = FALSE; + const char *uid, *c_gw_id = NULL; priv = cbgw->priv; @@ -2518,15 +2640,36 @@ receive_object (ECalBackendGroupwise *cb comp = e_cal_component_new (); e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp)); method = icalcomponent_get_method (icalcomp); + e_cal_component_get_uid (comp, &uid); + + cache_comp = e_cal_backend_cache_get_component (priv->cache, uid, NULL); + if (cache_comp) + c_gw_id = e_cal_component_get_gw_id (cache_comp); /* handle attachments */ if (e_cal_component_has_attachments (comp)) fetch_attachments (cbgw, comp); - status = e_gw_connection_send_appointment (cbgw, priv->container_id, comp, method, all_instances, &modif_comp, &pstatus); + status = e_gw_connection_send_appointment (cbgw, c_gw_id, comp, method, all_instances, &modif_comp, &pstatus, &is_import); if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION) - status = e_gw_connection_send_appointment (cbgw, priv->container_id, comp, method, all_instances, &modif_comp, &pstatus); + status = e_gw_connection_send_appointment (cbgw, c_gw_id, comp, method, all_instances, &modif_comp, &pstatus, &is_import); + + if (cache_comp) { + g_object_unref (cache_comp); + cache_comp = NULL; + c_gw_id = NULL; + } + + if (is_import) { + if (pstatus == ICAL_PARTSTAT_DECLINED) + return GNOME_Evolution_Calendar_ObjectNotFound; + + status = import_items (cbgw, comp); + g_object_unref (comp); + + return status; + } if (!modif_comp) modif_comp = g_object_ref (comp); Index: calendar/backends/groupwise/e-cal-backend-groupwise-utils.h =================================================================== --- calendar/backends/groupwise/e-cal-backend-groupwise-utils.h (revision 9156) +++ calendar/backends/groupwise/e-cal-backend-groupwise-utils.h (working copy) @@ -51,8 +51,10 @@ void e_gw_item_set_changes (EGw /* * Connection-related utility functions */ -EGwConnectionStatus e_gw_connection_create_appointment (EGwConnection *cnc, const char *container, ECalBackendGroupwise *cbgw, ECalComponent *comp, GSList **id_list); -EGwConnectionStatus e_gw_connection_send_appointment (ECalBackendGroupwise *cbgw, const char *container, ECalComponent *comp, icalproperty_method method, gboolean all_instances, ECalComponent **created_comp, icalparameter_partstat *pstatus); +EGwConnectionStatus e_gw_connection_create_appointment (EGwConnection *cnc, const char *container, ECalBackendGroupwise *cbgw, ECalComponent *comp, GSList **id_list, gboolean personal); +EGwConnectionStatus e_gw_connection_send_appointment (ECalBackendGroupwise *cbgw, const char *c_gw_id, ECalComponent *comp, icalproperty_method method, gboolean all_instances, ECalComponent **created_comp, icalparameter_partstat *pstatus, gboolean *import); + EGwConnectionStatus e_gw_connection_get_freebusy_info (EGwConnection *cnc, GList *users, time_t start, time_t end, GList **freebusy, icaltimezone *default_zone); + gboolean e_cal_backend_groupwise_store_settings (GwSettings *hold); EGwConnectionStatus e_gw_connection_get_freebusy_info (EGwConnection *cnc, GList *users, time_t start, time_t end, GList **freebusy, icaltimezone *default_zone); gboolean e_cal_backend_groupwise_store_settings (GwSettings *hold); EGwItem * e_gw_item_new_for_delegate_from_cal (ECalBackendGroupwise *cbgw, ECalComponent *comp); Index: calendar/backends/groupwise/e-cal-backend-groupwise.h =================================================================== --- calendar/backends/groupwise/e-cal-backend-groupwise.h (revision 9156) +++ calendar/backends/groupwise/e-cal-backend-groupwise.h (working copy) @@ -63,6 +63,7 @@ GHashTable* e_cal_backend_groupwise_get_ icaltimezone* e_cal_backend_groupwise_get_default_zone (ECalBackendGroupwise *cbgw); void e_cal_backend_groupwise_notify_error_code (ECalBackendGroupwise *cbgw, EGwConnectionStatus status); const char * e_cal_backend_groupwise_get_local_attachments_store (ECalBackendGroupwise *cbgw); +const char * e_cal_backend_groupwise_get_container_id (ECalBackendGroupwise *cbgw); G_END_DECLS #endif