[evolution-ews] Bug #724232 - Empty Trash doesn't delete Trash subfolders
- From: Fabiano Fidêncio <ffidencio src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews] Bug #724232 - Empty Trash doesn't delete Trash subfolders
- Date: Mon, 17 Feb 2014 20:06:49 +0000 (UTC)
commit 8c2bbd445185271c1d4fc43b33ae08da87aaed35
Author: Fabiano Fidêncio <fidencio redhat com>
Date: Thu Feb 13 13:29:32 2014 +0100
Bug #724232 - Empty Trash doesn't delete Trash subfolders
src/camel/camel-ews-folder.c | 249 +++++++++++++++++++++++++++++++++---------
src/camel/camel-ews-store.c | 32 +-----
src/camel/camel-ews-utils.c | 36 ++++++
src/camel/camel-ews-utils.h | 5 +
4 files changed, 238 insertions(+), 84 deletions(-)
---
diff --git a/src/camel/camel-ews-folder.c b/src/camel/camel-ews-folder.c
index bb4aabc..45be1f6 100644
--- a/src/camel/camel-ews-folder.c
+++ b/src/camel/camel-ews-folder.c
@@ -1888,80 +1888,190 @@ ews_transfer_messages_to_sync (CamelFolder *source,
}
static gboolean
+ews_delete_messages_from_server (CamelEwsStore *ews_store,
+ GSList *deleted_items,
+ EwsDeleteType delete_type,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EEwsConnection *cnc;
+ gboolean ret;
+
+ cnc = camel_ews_store_ref_connection (ews_store);
+
+ ret = e_ews_connection_delete_items_sync (
+ cnc, EWS_PRIORITY_MEDIUM, deleted_items, delete_type,
+ EWS_SEND_TO_NONE, FALSE, cancellable, error);
+
+ g_object_unref (cnc);
+
+ return ret;
+}
+
+static void
+ews_delete_messages_from_folder (CamelFolder *folder,
+ GSList *deleted_items)
+{
+ CamelFolderChangeInfo *changes;
+ GSList *l;
+
+ changes = camel_folder_change_info_new ();
+
+ for (l = deleted_items; l != NULL; l = l->next) {
+ const gchar *uid = l->data;
+
+ camel_folder_summary_lock (folder->summary);
+ camel_folder_change_info_remove_uid (changes, uid);
+ camel_folder_summary_remove_uid (folder->summary, uid);
+ ews_data_cache_remove (CAMEL_EWS_FOLDER (folder)->cache, "cur", uid, NULL);
+ camel_folder_summary_unlock (folder->summary);
+ }
+
+ if (camel_folder_change_info_changed (changes)) {
+ camel_folder_summary_touch (folder->summary);
+ camel_folder_changed (folder, changes);
+ }
+
+ camel_folder_change_info_free (changes);
+}
+
+static gboolean
ews_delete_messages (CamelFolder *folder,
GSList *deleted_items,
gboolean expunge,
GCancellable *cancellable,
GError **error)
{
- CamelEwsFolder *ews_folder;
CamelStore *parent_store;
CamelEwsStore *ews_store;
- CamelFolderChangeInfo *changes;
- EEwsConnection *cnc;
- gboolean status = TRUE;
- GSList *deleted_head = NULL;
+ GError *local_error = NULL;
+
+ if (deleted_items == NULL)
+ return TRUE;
parent_store = camel_folder_get_parent_store (folder);
- ews_folder = CAMEL_EWS_FOLDER (folder);
ews_store = CAMEL_EWS_STORE (parent_store);
- deleted_head = deleted_items;
- if (!camel_ews_store_connected (ews_store, cancellable, error)) {
+ if (!camel_ews_store_connected (ews_store, cancellable, error))
+ return FALSE;
+
+ ews_delete_messages_from_server (
+ ews_store,
+ deleted_items,
+ expunge ? EWS_HARD_DELETE : EWS_MOVE_TO_DELETED_ITEMS,
+ cancellable,
+ &local_error);
+
+ if (local_error != NULL && local_error->code == EWS_CONNECTION_ERROR_ITEMNOTFOUND) {
+ /* If delete failed due to the item not found, ignore the error,
+ * trigger folder info refresh and then go on to clear the
+ * cache of the deleted items anyway. */
+ g_clear_error (&local_error);
+ ews_refresh_info_sync (folder, cancellable, &local_error);
+ }
+
+ if (local_error != NULL) {
+ camel_ews_store_maybe_disconnect (ews_store, local_error);
+ g_propagate_error (error, local_error);
+
return FALSE;
}
+ ews_delete_messages_from_folder (folder, deleted_items);
+
+ return TRUE;
+}
+
+static gboolean
+ews_expunge_deleted_items_sync (CamelFolder *folder,
+ CamelEwsStore *ews_store,
+ gboolean *delete_items,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EEwsConnection *cnc;
+ CamelFolderInfo *folder_info = NULL;
+ CamelFolderInfo *to_delete;
+ gchar *trash_id;
+ gchar *folder_name;
+ gboolean ret = FALSE;
+ gboolean expunge_deleted_items_at_once = FALSE;
+
cnc = camel_ews_store_ref_connection (ews_store);
- changes = camel_folder_change_info_new ();
+ trash_id = camel_ews_store_summary_get_folder_id_from_folder_type (ews_store->summary,
CAMEL_FOLDER_TYPE_TRASH);
- if (deleted_items) {
- GError *local_error = NULL;
- EwsDeleteType delete_type;
+ folder_name = camel_ews_store_summary_get_folder_full_name (ews_store->summary, trash_id, error);
+ if (folder_name == NULL)
+ goto exit;
- delete_type = expunge ? EWS_HARD_DELETE : EWS_MOVE_TO_DELETED_ITEMS;
+ folder_info = camel_store_get_folder_info_sync (
+ CAMEL_STORE (ews_store), folder_name,
+ CAMEL_STORE_FOLDER_INFO_RECURSIVE |
+ CAMEL_STORE_FOLDER_INFO_SUBSCRIBED,
+ cancellable, error);
- status = e_ews_connection_delete_items_sync (
- cnc, EWS_PRIORITY_MEDIUM, deleted_items, delete_type,
- EWS_SEND_TO_NONE, FALSE, cancellable, &local_error);
- if (!status && local_error->code == EWS_CONNECTION_ERROR_ITEMNOTFOUND) {
- /* If delete failed due to the item not found, ignore the error,
- * trigger folder info refresh and then go on to clear the
- * cache of the deleted items anyway. */
- g_clear_error (&local_error);
- status = ews_refresh_info_sync (folder, cancellable, &local_error);
- }
+ if (folder_info == NULL)
+ goto exit;
- if (status) {
- while (deleted_items) {
- const gchar *uid = (gchar *) deleted_items->data;
- camel_folder_summary_lock (folder->summary);
- camel_folder_change_info_remove_uid (changes, uid);
- camel_folder_summary_remove_uid (folder->summary, uid);
- ews_data_cache_remove (ews_folder->cache, "cur", uid, NULL);
- camel_folder_summary_unlock (folder->summary);
- deleted_items = g_slist_next (deleted_items);
- }
- }
+ to_delete = folder_info->child;
- if (local_error) {
- camel_ews_store_maybe_disconnect (ews_store, local_error);
- g_propagate_error (error, local_error);
- }
+ expunge_deleted_items_at_once = e_ews_connection_satisfies_server_version (cnc, E_EWS_EXCHANGE_2010);
- if (camel_folder_change_info_changed (changes)) {
- camel_folder_summary_touch (folder->summary);
- camel_folder_changed (folder, changes);
- }
+ if (expunge_deleted_items_at_once) {
+ ret = e_ews_connection_empty_folder_sync (
+ cnc,
+ EWS_PRIORITY_MEDIUM,
+ trash_id,
+ FALSE,
+ "HardDelete",
+ TRUE,
+ cancellable,
+ error);
+
+ if (!ret)
+ goto exit;
+ } else {
+ /*
+ * As we cannot delete the "Deleted Items" folder itself, we have to walk throught its first
+ * level subfolders and delete each folder one by one from the server,
+ */
+ while (to_delete != NULL) {
+ gchar *fid;
+
+ fid = camel_ews_store_summary_get_folder_id_from_name (
+ ews_store->summary, to_delete->full_name);
- g_slist_foreach (deleted_head, (GFunc) camel_pstring_free, NULL);
- g_slist_free (deleted_head);
+ ret = e_ews_connection_delete_folder_sync (
+ cnc,
+ EWS_PRIORITY_MEDIUM,
+ fid,
+ FALSE,
+ "HardDelete",
+ cancellable,
+ error);
+
+ g_free (fid);
+
+ if (!ret)
+ goto exit;
+
+ to_delete = to_delete->next;
+ }
}
- camel_folder_change_info_free (changes);
+ to_delete = folder_info->child;
+ ret = camel_ews_utils_delete_folders_from_summary_recursive (ews_store, to_delete, TRUE, error);
+
+exit:
+ camel_folder_info_free (folder_info);
+ g_free (folder_name);
+ g_free (trash_id);
g_object_unref (cnc);
- return status;
+ *delete_items = !expunge_deleted_items_at_once;
+
+ return ret;
}
static gboolean
@@ -1969,43 +2079,76 @@ ews_expunge_sync (CamelFolder *folder,
GCancellable *cancellable,
GError **error)
{
- CamelEwsStore *ews_store;
CamelEwsMessageInfo *ews_info;
- CamelMessageInfo *info;
CamelStore *parent_store;
GSList *deleted_items = NULL;
gint i;
gboolean is_trash;
+ gboolean delete_items_from_server = TRUE;
+ gboolean ret;
GPtrArray *known_uids;
+ GError *local_error = NULL;
parent_store = camel_folder_get_parent_store (folder);
- ews_store = CAMEL_EWS_STORE (parent_store);
- if (!camel_ews_store_connected (ews_store, cancellable, error))
+ if (!camel_ews_store_connected (CAMEL_EWS_STORE (parent_store), cancellable, error))
return FALSE;
+ /*
+ * If the user is expunging the trash folder, we should delete
+ * all messages, subfolders and subfolders' messages inside the
+ * trash folder.
+ */
is_trash = ews_folder_is_of_type (folder, CAMEL_FOLDER_TYPE_TRASH);
camel_folder_summary_prepare_fetch_all (folder->summary, NULL);
known_uids = camel_folder_summary_get_array (folder->summary);
- if (!known_uids)
+
+ if (known_uids == NULL)
return TRUE;
- /* Collect UIDs of deleted messages. */
+ if (is_trash) {
+ ews_expunge_deleted_items_sync (
+ folder,
+ CAMEL_EWS_STORE (parent_store),
+ &delete_items_from_server,
+ cancellable,
+ &local_error);
+
+ if (local_error != NULL) {
+ camel_ews_store_maybe_disconnect (CAMEL_EWS_STORE (parent_store), local_error);
+ g_propagate_error (error, local_error);
+
+ camel_folder_summary_free_array (known_uids);
+
+ return FALSE;
+ }
+ }
+
for (i = 0; i < known_uids->len; i++) {
+ CamelMessageInfo *info;
const gchar *uid = g_ptr_array_index (known_uids, i);
info = camel_folder_summary_get (folder->summary, uid);
ews_info = (CamelEwsMessageInfo *) info;
+
if (ews_info && (is_trash || (ews_info->info.flags & CAMEL_MESSAGE_DELETED) != 0))
deleted_items = g_slist_prepend (deleted_items, (gpointer) camel_pstring_strdup
(uid));
camel_message_info_unref (info);
}
+ if (is_trash && !delete_items_from_server) {
+ ews_delete_messages_from_folder (folder, deleted_items);
+ ret = TRUE;
+ } else {
+ ret = ews_delete_messages (folder, deleted_items, TRUE, cancellable, error);
+ }
+
+ g_slist_free_full (deleted_items, (GDestroyNotify) camel_pstring_free);
camel_folder_summary_free_array (known_uids);
- return ews_delete_messages (folder, deleted_items, TRUE, cancellable, error);
+ return ret;
}
static gint
diff --git a/src/camel/camel-ews-store.c b/src/camel/camel-ews-store.c
index 6979b76..7d50774 100644
--- a/src/camel/camel-ews-store.c
+++ b/src/camel/camel-ews-store.c
@@ -2562,36 +2562,6 @@ ews_create_folder_sync (CamelStore *store,
return fi;
}
-static gboolean
-ews_update_store_delete_recursive (CamelEwsStore *ews_store,
- CamelFolderInfo *folder_info,
- GError **error)
-{
- gboolean success = TRUE;
-
- while (folder_info != NULL) {
- gchar *fid;
-
- if (folder_info->child != NULL) {
- success = ews_update_store_delete_recursive (ews_store, folder_info->child, error);
-
- if (!success)
- break;
- }
-
- fid = camel_ews_store_summary_get_folder_id_from_name (ews_store->summary,
folder_info->full_name);
- success = camel_ews_store_summary_remove_folder (ews_store->summary, fid, error);
- g_free (fid);
-
- if (!success)
- break;
-
- folder_info = folder_info->next;
- }
-
- return success;
-}
-
static void
ews_update_store_move_recursive (CamelEwsStore *ews_store,
CamelFolderInfo *folder_info)
@@ -2727,7 +2697,7 @@ ews_delete_folder_sync (CamelStore *store,
}
if (is_under_trash_folder) {
- success = ews_update_store_delete_recursive (ews_store, to_update, &local_error);
+ success = camel_ews_utils_delete_folders_from_summary_recursive (ews_store, to_update, FALSE,
error);
if (!success) {
g_free (trash_fid);
diff --git a/src/camel/camel-ews-utils.c b/src/camel/camel-ews-utils.c
index dece5a0..9d5aeb0 100644
--- a/src/camel/camel-ews-utils.c
+++ b/src/camel/camel-ews-utils.c
@@ -1078,3 +1078,39 @@ ews_utils_update_followup_flags (ESoapMessage *msg,
e_ews_message_add_set_item_field_extended_distinguished_tag_boolean (msg, NULL, "Message",
"Task", 0x811c, FALSE);
}
}
+gboolean
+camel_ews_utils_delete_folders_from_summary_recursive (CamelEwsStore *ews_store,
+ CamelFolderInfo *folder_info,
+ gboolean send_signals,
+ GError **error)
+{
+ gboolean success = TRUE;
+
+ while (folder_info != NULL) {
+ gchar *fid;
+
+ if (folder_info->child != NULL) {
+ success = camel_ews_utils_delete_folders_from_summary_recursive (
+ ews_store, folder_info->child, send_signals, error);
+
+ if (!success)
+ break;
+ }
+
+ fid = camel_ews_store_summary_get_folder_id_from_name (ews_store->summary,
folder_info->full_name);
+ success = camel_ews_store_summary_remove_folder (ews_store->summary, fid, error);
+ g_free (fid);
+
+ if (!success)
+ break;
+
+ if (send_signals) {
+ camel_subscribable_folder_unsubscribed (CAMEL_SUBSCRIBABLE (ews_store), folder_info);
+ camel_store_folder_deleted (CAMEL_STORE (ews_store), folder_info);
+ }
+
+ folder_info = folder_info->next;
+ }
+
+ return success;
+}
diff --git a/src/camel/camel-ews-utils.h b/src/camel/camel-ews-utils.h
index a48d86d..8b4caf0 100644
--- a/src/camel/camel-ews-utils.h
+++ b/src/camel/camel-ews-utils.h
@@ -77,6 +77,11 @@ void ews_utils_replace_server_user_flags
void ews_utils_update_followup_flags (ESoapMessage *msg,
CamelMessageInfo *mi);
gchar * camel_ews_utils_get_host_name (CamelSettings *settings);
+gboolean camel_ews_utils_delete_folders_from_summary_recursive
+ (CamelEwsStore *ews_store,
+ CamelFolderInfo *folder_info,
+ gboolean send_signals,
+ GError **error);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]