managesieve: fix command aborting and discarding
- Add "aborted" callback argument to indicate command is cancelled - Add helper function for issuing command callbacks
This commit is contained in:
parent
99738a91f6
commit
32924ce7e8
4 changed files with 93 additions and 61 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue