managesieve: allow script loading to be interrupted
authorCharles Lehner <cel@celehner.com>
Thu, 9 Jul 2015 07:24:02 +0000 (03:24 -0400)
committerCharles Lehner <cel@celehner.com>
Fri, 17 Jul 2015 03:28:37 +0000 (23:28 -0400)
Prevent use after free when an editor window is closed while loading

Uses string "Loading..." which is already translated

src/plugins/managesieve/sieve_editor.c
src/plugins/managesieve/sieve_editor.h
src/plugins/managesieve/sieve_manager.c

index eedd3e7..66dd6ea 100644 (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,
                        page);
 
-       gtk_widget_show_all(window);
-
        page->window = window;
        page->ui_manager = ui_manager;
        page->text = text;
@@ -661,6 +659,11 @@ void sieve_editor_present(SieveEditorPage *page)
        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,
                gboolean modified)
 {
@@ -680,3 +683,49 @@ static void sieve_editor_set_modified(SieveEditorPage *page,
                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);
+}
index 4925a54..bac8eea 100644 (file)
@@ -38,12 +38,19 @@ struct SieveEditorPage
        gboolean        first_line;
        gboolean        modified;
        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_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_close(SieveEditorPage *page);
+void sieve_editor_show(SieveEditorPage *page);
 void sieve_editor_present(SieveEditorPage *page);
 
 #endif /* SIEVE_EDITOR_H */
index 400a671..42e7911 100644 (file)
@@ -59,13 +59,6 @@ typedef struct {
        gchar *filter_name;
 } CommandDataName;
 
-typedef struct {
-       SieveManagerPage *page;
-       gchar *filter_name;
-       SieveEditorPage *editor_page;
-       gboolean first_line;
-} CommandDataGetScript;
-
 static void account_changed(GtkWidget *widget, SieveManagerPage *page);
 void sieve_manager_close(GtkWidget *widget, SieveManagerPage *page);
 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])
                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_data_cb_fn)filter_added, (gpointer)page);
                        */
 }
 
-static void filter_got_data(SieveSession *session, gboolean abort,
-               gchar *contents, CommandDataGetScript *cmd_data)
+static void filter_got_load_error(SieveSession *session, gpointer data)
 {
-       SieveManagerPage *page = cmd_data->page;
-       SieveEditorPage *editor;
+       SieveManagerPage *page = data;
 
-       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);
-               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));
+       got_session_error(session, _("Unable to get script contents"), page);
 }
 
 static void filter_edit(GtkWidget *widget, SieveManagerPage *page)
 {
        SieveEditorPage *editor;
-       CommandDataGetScript *cmd_data;
        SieveSession *session = page->active_session;
+
        if (!session)
                return;
+
        gchar *filter_name = filters_list_get_selected_filter(page->filters_list);
        if (!filter_name)
                return;
@@ -205,13 +180,9 @@ static void filter_edit(GtkWidget *widget, SieveManagerPage *page)
        if (editor) {
                sieve_editor_present(editor);
        } else {
-               cmd_data = g_new0(CommandDataGetScript, 1);
-               cmd_data->first_line = TRUE;
-               cmd_data->filter_name = filter_name;
-               cmd_data->page = page;
-
-               sieve_session_get_script(session, filter_name,
-                       (sieve_session_data_cb_fn)filter_got_data, cmd_data);
+               editor = sieve_editor_new(session, filter_name);
+               sieve_editor_load(editor,
+                       (sieve_session_cb_fn)filter_got_load_error, page);
        }
 }