talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit 32924ce7e82afbe83ffa9087fa56694825c6d0ef
parent 99738a91f6c2ca14fb8feeef9be42904556cf97f
Author: Charles Lehner <cel@celehner.com>
Date:   Thu, 16 Jul 2015 20:06:47 -0400

managesieve: fix command aborting and discarding

- Add "aborted" callback argument to indicate command is cancelled
- Add helper function for issuing command callbacks

Diffstat:
Msrc/plugins/managesieve/managesieve.c | 100++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/plugins/managesieve/managesieve.h | 3++-
Msrc/plugins/managesieve/sieve_editor.c | 17++++++++++++-----
Msrc/plugins/managesieve/sieve_manager.c | 34+++++++++++++++++++++-------------
4 files changed, 93 insertions(+), 61 deletions(-)

diff --git a/src/plugins/managesieve/managesieve.c b/src/plugins/managesieve/managesieve.c @@ -39,6 +39,9 @@ GSList *sessions = NULL; static void sieve_session_destroy(Session *session); static gint sieve_pop_send_queue(SieveSession *session); static void sieve_session_reset(SieveSession *session); +static void command_free(SieveCommand *cmd); +static void command_abort(SieveCommand *cmd); +static void command_cb(SieveCommand *cmd, gpointer result); void sieve_sessions_close() { @@ -48,34 +51,55 @@ void sieve_sessions_close() } } -void noop_data_cb_fn(SieveSession *session, gpointer cb_data, - gpointer user_data) -{ - /* noop */ -} - /* remove all command callbacks with a given data pointer */ void sieve_sessions_discard_callbacks(gpointer user_data) { GSList *item; GSList *queue; + GSList *prev = NULL; SieveSession *session; SieveCommand *cmd; for (item = sessions; item; item = item->next) { session = (SieveSession *)item->data; cmd = session->current_cmd; - if (cmd && cmd->data == user_data) - cmd->cb = noop_data_cb_fn; + /* abort current command handler */ + if (cmd && cmd->data == user_data) { + command_abort(cmd); + session->current_cmd = NULL; + } + /* abort queued command handlers */ for (queue = session->send_queue; queue; queue = queue->next) { - cmd = (SieveCommand *)item->data; - if (cmd && cmd->data == user_data) - cmd->cb = noop_data_cb_fn; + cmd = (SieveCommand *)queue->data; + if (cmd && cmd->data == user_data) { + if (prev) + prev->next = queue->next; + else + session->send_queue = NULL; + command_abort(cmd); + g_slist_free_1(queue); + } else { + prev = queue; + } } } } -void command_free(SieveCommand *cmd) { +static void command_cb(SieveCommand *cmd, gpointer result) +{ + if (cmd) + cmd->cb(cmd->session, FALSE, result, cmd->data); +} + +static void command_abort(SieveCommand *cmd) +{ + cmd->cb(cmd->session, TRUE, NULL, cmd->data); + g_free(cmd->msg); + g_free(cmd); +} + +static void command_free(SieveCommand *cmd) +{ g_free(cmd->msg); g_free(cmd); } @@ -319,7 +343,7 @@ static void sieve_session_putscript_cb(SieveSession *session, SieveResult *resul result->description = desc; } /* pass along the callback */ - session->current_cmd->cb(session, result, session->current_cmd->data); + command_cb(session->current_cmd, result); } static inline gboolean response_is_ok(const char *msg) @@ -614,17 +638,15 @@ static gint sieve_session_recv_msg(Session *session, const gchar *msg) case SIEVE_LISTSCRIPTS: if (response_is_no(msg)) { /* got an error. probably not authenticated. */ - sieve_session->current_cmd->cb(sieve_session, NULL, - sieve_session->current_cmd->data); + command_cb(sieve_session->current_cmd, NULL); sieve_session->state = SIEVE_READY; ret = sieve_pop_send_queue(sieve_session); } else if (response_is_ok(msg)) { /* end of list */ sieve_session->state = SIEVE_READY; sieve_session->error = SE_OK; - sieve_session->current_cmd->cb(sieve_session, - (gpointer)&(SieveScript){0}, - sieve_session->current_cmd->data); + command_cb(sieve_session->current_cmd, + (gpointer)&(SieveScript){0}); ret = sieve_pop_send_queue(sieve_session); } else { /* got a script name */ @@ -635,19 +657,17 @@ static gint sieve_session_recv_msg(Session *session, const gchar *msg) script.active = (script_status && strcasecmp(script_status, "active") == 0); - sieve_session->current_cmd->cb(sieve_session, (gpointer)&script, - sieve_session->current_cmd->data); + command_cb(sieve_session->current_cmd, + (gpointer)&script); ret = SE_OK; } break; case SIEVE_RENAMESCRIPT: if (response_is_no(msg)) { /* error */ - sieve_session->current_cmd->cb(sieve_session, NULL, - sieve_session->current_cmd->data); + command_cb(sieve_session->current_cmd, NULL); } else if (response_is_ok(msg)) { - sieve_session->current_cmd->cb(sieve_session, (void*)TRUE, - sieve_session->current_cmd->data); + command_cb(sieve_session->current_cmd, (void*)TRUE); } else { log_warning(LOG_PROTOCOL, _("error occurred on SIEVE session\n")); } @@ -656,11 +676,9 @@ static gint sieve_session_recv_msg(Session *session, const gchar *msg) case SIEVE_SETACTIVE: if (response_is_no(msg)) { /* error */ - sieve_session->current_cmd->cb(sieve_session, NULL, - sieve_session->current_cmd->data); + command_cb(sieve_session->current_cmd, NULL); } else if (response_is_ok(msg)) { - sieve_session->current_cmd->cb(sieve_session, (void*)TRUE, - sieve_session->current_cmd->data); + command_cb(sieve_session->current_cmd, (void*)TRUE); } else { log_warning(LOG_PROTOCOL, _("error occurred on SIEVE session\n")); } @@ -668,8 +686,7 @@ static gint sieve_session_recv_msg(Session *session, const gchar *msg) break; case SIEVE_GETSCRIPT: if (response_is_no(msg)) { - sieve_session->current_cmd->cb(sieve_session, (void *)-1, - sieve_session->current_cmd->data); + command_cb(sieve_session->current_cmd, (void *)-1); sieve_session->state = SIEVE_READY; } else { parse_response((gchar *)msg, &result); @@ -681,14 +698,11 @@ static gint sieve_session_recv_msg(Session *session, const gchar *msg) break; case SIEVE_GETSCRIPT_DATA: if (sieve_session->octets_remaining > 0) { - sieve_session->current_cmd->cb(sieve_session, - (gchar *)msg, - sieve_session->current_cmd->data); + command_cb(sieve_session->current_cmd, (gchar *)msg); sieve_session->octets_remaining -= strlen(msg) + 1; } else if (response_is_ok(msg)) { sieve_session->state = SIEVE_READY; - sieve_session->current_cmd->cb(sieve_session, NULL, - sieve_session->current_cmd->data); + command_cb(sieve_session->current_cmd, NULL); } else { log_warning(LOG_PROTOCOL, _("error occurred on SIEVE session\n")); } @@ -720,11 +734,10 @@ static gint sieve_session_recv_msg(Session *session, const gchar *msg) case SIEVE_DELETESCRIPT: parse_response((gchar *)msg, &result); if (!result.success) { - sieve_session->current_cmd->cb(sieve_session, result.description, - sieve_session->current_cmd->data); + command_cb(sieve_session->current_cmd, + result.description); } else { - sieve_session->current_cmd->cb(sieve_session, NULL, - sieve_session->current_cmd->data); + command_cb(sieve_session->current_cmd, NULL); } sieve_session->state = SIEVE_READY; break; @@ -791,8 +804,10 @@ static void sieve_session_destroy(Session *session) SieveSession *sieve_session = SIEVE_SESSION(session); g_free(sieve_session->pass); if (sieve_session->current_cmd) - command_free(sieve_session->current_cmd); + command_abort(sieve_session->current_cmd); sessions = g_slist_remove(sessions, (gconstpointer)session); + g_slist_free_full(sieve_session->send_queue, + (GDestroyNotify)command_abort); } static void sieve_connect_finished(Session *session, gboolean success) @@ -834,7 +849,7 @@ static void sieve_session_reset(SieveSession *session) SieveAccountConfig *config = sieve_prefs_account_get_config(account); gboolean reuse_auth = (config->auth == SIEVEAUTH_REUSE); - g_slist_free_full(session->send_queue, (GDestroyNotify)command_free); + g_slist_free_full(session->send_queue, (GDestroyNotify)command_abort); session_disconnect(SESSION(session)); @@ -921,6 +936,7 @@ static void sieve_queue_send(SieveSession *session, SieveState next_state, { gboolean queue = FALSE; SieveCommand *cmd = g_new0(SieveCommand, 1); + cmd->session = session; cmd->next_state = next_state; cmd->msg = msg; cmd->data = data; @@ -980,7 +996,7 @@ void sieve_session_set_active_script(SieveSession *session, gchar *msg = g_strdup_printf("SETACTIVE \"%s\"", filter_name ? filter_name : ""); if (!msg) { - cb(session, (void*)FALSE, data); + cb(session, FALSE, (void*)FALSE, data); return; } diff --git a/src/plugins/managesieve/managesieve.h b/src/plugins/managesieve/managesieve.h @@ -98,7 +98,7 @@ typedef enum { typedef void (*sieve_session_cb_fn) (SieveSession *session, gpointer data); typedef void (*sieve_session_data_cb_fn) (SieveSession *session, - gpointer cb_data, gpointer user_data); + gboolean aborted, gpointer cb_data, gpointer user_data); typedef void (*sieve_session_error_cb_fn) (SieveSession *session, const gchar *msg, gpointer user_data); typedef void (*sieve_session_connected_cb_fn) (SieveSession *session, @@ -140,6 +140,7 @@ struct SieveSession }; struct SieveCommand { + SieveSession *session; SieveState next_state; gchar *msg; sieve_session_data_cb_fn cb; diff --git a/src/plugins/managesieve/sieve_editor.c b/src/plugins/managesieve/sieve_editor.c @@ -266,9 +266,12 @@ static void sieve_editor_search(SieveEditorPage *page) /* Actions */ -static void got_data_reverting(SieveSession *session, gchar *contents, +static void got_data_reverting(SieveSession *session, gboolean abort, + gchar *contents, SieveEditorPage *page) { + if (abort) + return; if (contents == NULL) { /* end of data */ undo_unblock(page->undostruct); @@ -324,9 +327,11 @@ static void sieve_editor_revert_cb(GtkAction *action, SieveEditorPage *page) sieve_editor_revert(page); } -static void got_data_saved(SieveSession *session, SieveResult *result, - SieveEditorPage *page) +static void got_data_saved(SieveSession *session, gboolean abort, + SieveResult *result, SieveEditorPage *page) { + if (abort) + return; if (result->has_status && result->success) { sieve_editor_set_modified(page, FALSE); if (page->closing) { @@ -362,9 +367,11 @@ static void sieve_editor_find_cb(GtkAction *action, SieveEditorPage *page) sieve_editor_search(page); } -static void got_data_checked(SieveSession *session, SieveResult *result, - SieveEditorPage *page) +static void got_data_checked(SieveSession *session, gboolean abort, + SieveResult *result, SieveEditorPage *page) { + if (abort) + return; sieve_editor_update_status(page, result); } diff --git a/src/plugins/managesieve/sieve_manager.c b/src/plugins/managesieve/sieve_manager.c @@ -164,13 +164,13 @@ static void filter_add(GtkWidget *widget, SieveManagerPage *page) */ } -static void filter_got_data(SieveSession *session, gchar *contents, - CommandDataGetScript *cmd_data) +static void filter_got_data(SieveSession *session, gboolean abort, + gchar *contents, CommandDataGetScript *cmd_data) { SieveManagerPage *page = cmd_data->page; SieveEditorPage *editor; - if (!contents) { + if (abort || !contents) { g_free(cmd_data->filter_name); g_free(cmd_data); return; @@ -215,13 +215,14 @@ static void filter_edit(GtkWidget *widget, SieveManagerPage *page) } } -static void filter_renamed(SieveSession *session, gboolean success, - CommandDataRename *data) +static void filter_renamed(SieveSession *session, gboolean abort, + gboolean success, CommandDataRename *data) { SieveManagerPage *page = data->page; GSList *cur; - if (!success) { + if (abort) { + } else if (!success) { got_session_error(session, "Unable to rename script", page); } else { manager_sessions_foreach(cur, session, page) { @@ -261,13 +262,14 @@ static void filter_rename(GtkWidget *widget, SieveManagerPage *page) (sieve_session_data_cb_fn)filter_renamed, (gpointer)cmd_data); } -static void filter_activated(SieveSession *session, gboolean success, - CommandDataName *cmd_data) +static void filter_activated(SieveSession *session, gboolean abort, + gboolean success, CommandDataName *cmd_data) { SieveManagerPage *page = cmd_data->page; GSList *cur; - if (!success) { + if (abort) { + } else if (!success) { got_session_error(session, "Unable to set active script", page); } else { manager_sessions_foreach(cur, session, page) { @@ -292,13 +294,15 @@ static void sieve_set_active_filter(SieveManagerPage *page, gchar *filter_name) (sieve_session_data_cb_fn)filter_activated, cmd_data); } -static void filter_deleted(SieveSession *session, const gchar *err_msg, +static void filter_deleted(SieveSession *session, gboolean abort, + const gchar *err_msg, CommandDataName *cmd_data) { SieveManagerPage *page = cmd_data->page; GSList *cur; - if (err_msg) { + if (abort) { + } else if (err_msg) { got_session_error(session, err_msg, page); } else { manager_sessions_foreach(cur, session, page) { @@ -550,6 +554,8 @@ static void size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation) static void got_session_error(SieveSession *session, const gchar *msg, SieveManagerPage *page) { + if (!g_slist_find(manager_pages, page)) + return; if (page->active_session != session) return; gtk_label_set_text(GTK_LABEL(page->status_text), msg); @@ -575,9 +581,11 @@ static void sieve_manager_on_connected(SieveSession *session, } } -static void got_filter_listed(SieveSession *session, SieveScript *script, - SieveManagerPage *page) +static void got_filter_listed(SieveSession *session, gboolean abort, + SieveScript *script, SieveManagerPage *page) { + if (abort) + return; if (!script) { got_session_error(session, "Unable to list scripts", page); return;