managesieve: allow script loading to be interrupted

Prevent use after free when an editor window is closed while loading

Uses string "Loading..." which is already translated
This commit is contained in:
Charles Lehner 2015-07-09 03:24:02 -04:00
parent 32924ce7e8
commit dc1d2b4ed5
3 changed files with 67 additions and 40 deletions

View file

@ -625,8 +625,6 @@ MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Filter", "Revert", "Filter/Revert", GT
undo_set_change_state_func(undostruct, &sieve_editor_undo_state_changed, undo_set_change_state_func(undostruct, &sieve_editor_undo_state_changed,
page); page);
gtk_widget_show_all(window);
page->window = window; page->window = window;
page->ui_manager = ui_manager; page->ui_manager = ui_manager;
page->text = text; page->text = text;
@ -661,6 +659,11 @@ void sieve_editor_present(SieveEditorPage *page)
gtk_window_present(GTK_WINDOW(page->window)); gtk_window_present(GTK_WINDOW(page->window));
} }
void sieve_editor_show(SieveEditorPage *page)
{
gtk_widget_show_all(GTK_WIDGET(page->window));
}
static void sieve_editor_set_modified(SieveEditorPage *page, static void sieve_editor_set_modified(SieveEditorPage *page,
gboolean modified) gboolean modified)
{ {
@ -680,3 +683,49 @@ static void sieve_editor_set_modified(SieveEditorPage *page,
sieve_editor_set_status_icon(page, NULL); sieve_editor_set_status_icon(page, NULL);
} }
} }
static void got_data_loading(SieveSession *session, gboolean aborted,
gchar *contents, SieveEditorPage *page)
{
if (aborted)
return;
if (contents == NULL) {
/* end of data */
sieve_editor_set_status(page, "");
return;
}
if (contents == (void *)-1) {
/* error */
if (page->first_line) {
/* no data. show error in manager window */
if (page->on_load_error)
page->on_load_error(session, page->on_load_error_data);
} else {
/* partial failure. show error in editor window */
sieve_editor_set_status(page, _("Unable to get script contents"));
sieve_editor_set_status_icon(page, GTK_STOCK_DIALOG_ERROR);
}
return;
}
if (page->first_line) {
page->first_line = FALSE;
sieve_editor_show(page);
} else {
sieve_editor_append_text(page, "\n", 1);
}
sieve_editor_append_text(page, contents, strlen(contents));
}
/* load the script for this editor */
void sieve_editor_load(SieveEditorPage *page,
sieve_session_cb_fn on_load_error, gpointer load_error_data)
{
page->first_line = TRUE;
page->on_load_error = on_load_error;
page->on_load_error_data = load_error_data;
sieve_editor_set_status(page, _("Loading..."));
sieve_editor_set_status_icon(page, NULL);
sieve_session_get_script(page->session, page->script_name,
(sieve_session_data_cb_fn)got_data_loading, page);
}

View file

@ -38,12 +38,19 @@ struct SieveEditorPage
gboolean first_line; gboolean first_line;
gboolean modified; gboolean modified;
gboolean closing; gboolean closing;
/* callback for failure to load the script */
sieve_session_cb_fn on_load_error;
gpointer on_load_error_data;
}; };
SieveEditorPage *sieve_editor_new(SieveSession *session, gchar *script_name); SieveEditorPage *sieve_editor_new(SieveSession *session, gchar *script_name);
SieveEditorPage *sieve_editor_get(SieveSession *session, gchar *script_name); SieveEditorPage *sieve_editor_get(SieveSession *session, gchar *script_name);
void sieve_editor_load(SieveEditorPage *page,
sieve_session_cb_fn on_load_error, gpointer load_error_data);
void sieve_editor_append_text(SieveEditorPage *page, gchar *text, gint len); void sieve_editor_append_text(SieveEditorPage *page, gchar *text, gint len);
void sieve_editor_close(SieveEditorPage *page); void sieve_editor_close(SieveEditorPage *page);
void sieve_editor_show(SieveEditorPage *page);
void sieve_editor_present(SieveEditorPage *page); void sieve_editor_present(SieveEditorPage *page);
#endif /* SIEVE_EDITOR_H */ #endif /* SIEVE_EDITOR_H */

View file

@ -59,13 +59,6 @@ typedef struct {
gchar *filter_name; gchar *filter_name;
} CommandDataName; } CommandDataName;
typedef struct {
SieveManagerPage *page;
gchar *filter_name;
SieveEditorPage *editor_page;
gboolean first_line;
} CommandDataGetScript;
static void account_changed(GtkWidget *widget, SieveManagerPage *page); static void account_changed(GtkWidget *widget, SieveManagerPage *page);
void sieve_manager_close(GtkWidget *widget, SieveManagerPage *page); void sieve_manager_close(GtkWidget *widget, SieveManagerPage *page);
static void filter_set_active(SieveManagerPage *page, gchar *filter_name); static void filter_set_active(SieveManagerPage *page, gchar *filter_name);
@ -157,46 +150,28 @@ static void filter_add(GtkWidget *widget, SieveManagerPage *page)
if (!filter_name || !filter_name[0]) if (!filter_name || !filter_name[0])
return; return;
sieve_editor_new(session, filter_name); sieve_editor_show(sieve_editor_new(session, filter_name));
/* /*
sieve_session_add_script(session, filter_name sieve_session_add_script(session, filter_name
(sieve_session_data_cb_fn)filter_added, (gpointer)page); (sieve_session_data_cb_fn)filter_added, (gpointer)page);
*/ */
} }
static void filter_got_data(SieveSession *session, gboolean abort, static void filter_got_load_error(SieveSession *session, gpointer data)
gchar *contents, CommandDataGetScript *cmd_data)
{ {
SieveManagerPage *page = cmd_data->page; SieveManagerPage *page = data;
SieveEditorPage *editor;
if (abort || !contents) {
g_free(cmd_data->filter_name);
g_free(cmd_data);
return;
} else if (contents == (void *)-1) {
got_session_error(session, _("Unable to get script contents"), page); got_session_error(session, _("Unable to get script contents"), page);
return;
}
if (cmd_data->first_line) {
cmd_data->first_line = FALSE;
editor = sieve_editor_new(session, cmd_data->filter_name);
cmd_data->editor_page = editor;
} else {
editor = cmd_data->editor_page;
sieve_editor_append_text(editor, "\n", 1);
}
sieve_editor_append_text(editor, contents, strlen(contents));
} }
static void filter_edit(GtkWidget *widget, SieveManagerPage *page) static void filter_edit(GtkWidget *widget, SieveManagerPage *page)
{ {
SieveEditorPage *editor; SieveEditorPage *editor;
CommandDataGetScript *cmd_data;
SieveSession *session = page->active_session; SieveSession *session = page->active_session;
if (!session) if (!session)
return; return;
gchar *filter_name = filters_list_get_selected_filter(page->filters_list); gchar *filter_name = filters_list_get_selected_filter(page->filters_list);
if (!filter_name) if (!filter_name)
return; return;
@ -205,13 +180,9 @@ static void filter_edit(GtkWidget *widget, SieveManagerPage *page)
if (editor) { if (editor) {
sieve_editor_present(editor); sieve_editor_present(editor);
} else { } else {
cmd_data = g_new0(CommandDataGetScript, 1); editor = sieve_editor_new(session, filter_name);
cmd_data->first_line = TRUE; sieve_editor_load(editor,
cmd_data->filter_name = filter_name; (sieve_session_cb_fn)filter_got_load_error, page);
cmd_data->page = page;
sieve_session_get_script(session, filter_name,
(sieve_session_data_cb_fn)filter_got_data, cmd_data);
} }
} }