summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2016-03-14 14:02:48 +0000
committerVincent Sanders <vince@kyllikki.org>2016-03-14 14:02:48 +0000
commitc45afb6a291cd803469276607db6264e39d09b47 (patch)
tree01ca3efd8725d15df9a09b32044e0b4a65458556
parent1d7b305db97d175a3c60169e7fa76d470242436d (diff)
downloadnetsurf-c45afb6a291cd803469276607db6264e39d09b47.tar.gz
netsurf-c45afb6a291cd803469276607db6264e39d09b47.tar.bz2
Clean up gtk login window
This fixes coverity ID 1316338 by dealing with memory and window creation errors properly. Previously such errors could seg fault or leave the browser navigation logic "stuck" waiting for user input to a window that never existed. The code was also refactored to remove forward declarations and add documentation comments.
-rw-r--r--gtk/login.c182
1 files changed, 116 insertions, 66 deletions
diff --git a/gtk/login.c b/gtk/login.c
index 2de2996b3..260e70d5c 100644
--- a/gtk/login.c
+++ b/gtk/login.c
@@ -33,57 +33,129 @@
#include "gtk/resources.h"
#include "gtk/login.h"
+/** login window session data */
struct session_401 {
nsurl *url; /**< URL being fetched */
lwc_string *host; /**< Host for user display */
char *realm; /**< Authentication realm */
nserror (*cb)(bool proceed, void *pw); /**< Continuation callback */
void *cbpw; /**< Continuation data */
- GtkBuilder *x; /**< Our glade windows */
+ GtkBuilder *x; /**< Our builder windows */
GtkWindow *wnd; /**< The login window itself */
GtkEntry *user; /**< Widget with username */
GtkEntry *pass; /**< Widget with password */
};
-static void create_login_window(nsurl *url, lwc_string *host,
- const char *realm, nserror (*cb)(bool proceed, void *pw),
- void *cbpw);
-static void destroy_login_window(struct session_401 *session);
-static void nsgtk_login_next(GtkWidget *w, gpointer data);
-static void nsgtk_login_ok_clicked(GtkButton *w, gpointer data);
-static void nsgtk_login_cancel_clicked(GtkButton *w, gpointer data);
+/**
+ * Destroy login window and free all associated resources
+ *
+ * \param session The login window session to destroy.
+ */
+static void destroy_login_window(struct session_401 *session)
+{
+ nsurl_unref(session->url);
+ lwc_string_unref(session->host);
+ free(session->realm);
+ gtk_widget_destroy(GTK_WIDGET(session->wnd));
+ g_object_unref(G_OBJECT(session->x));
+ free(session);
+}
+
-void gui_401login_open(nsurl *url, const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw)
+/**
+ * process next signal in entry widgets.
+ *
+ * \param w current widget
+ * \param data next widget
+ */
+static void nsgtk_login_next(GtkWidget *w, gpointer data)
{
- lwc_string *host;
+ gtk_widget_grab_focus(GTK_WIDGET(data));
+}
- host = nsurl_get_component(url, NSURL_HOST);
- assert(host != NULL);
- create_login_window(url, host, realm, cb, cbpw);
+/**
+ * handler called when navigation is continued
+ *
+ * \param w current widget
+ * \param data login window session
+ */
+static void nsgtk_login_ok_clicked(GtkButton *w, gpointer data)
+{
+ /* close the window and destroy it, having continued the fetch
+ * assoicated with it.
+ */
+
+ struct session_401 *session = (struct session_401 *)data;
+ const gchar *user = gtk_entry_get_text(session->user);
+ const gchar *pass = gtk_entry_get_text(session->pass);
+ char *auth;
- lwc_string_unref(host);
+ auth = malloc(strlen(user) + strlen(pass) + 2);
+ sprintf(auth, "%s:%s", user, pass);
+ urldb_set_auth_details(session->url, session->realm, auth);
+ free(auth);
+
+ session->cb(true, session->cbpw);
+
+ destroy_login_window(session);
+}
+
+
+/**
+ * handler called when navigation is cancelled
+ *
+ * \param w widget
+ * \param data login window session
+ */
+static void nsgtk_login_cancel_clicked(GtkButton *w, gpointer data)
+{
+ struct session_401 *session = (struct session_401 *) data;
+
+ session->cb(false, session->cbpw);
+
+ /* close and destroy the window */
+ destroy_login_window(session);
}
-/* create a new instance of the login window, and get handles to all
- * the widgets we're interested in.
+
+/**
+ * create a new instance of the login window
+ *
+ * creates login window and handles to all the widgets we're
+ * interested in.
+ *
+ * \param url The url causing the login.
+ * \param host the host being logged into
+ * \param realm realmm the login relates to
+ * \param cb callback when complete
+ * \param cbpw data to pass to callback
+ * \return NSERROR_OK on sucessful window creation or error code on faliure.
*/
-void create_login_window(nsurl *url, lwc_string *host, const char *realm,
- nserror (*cb)(bool proceed, void *pw), void *cbpw)
+static nserror
+create_login_window(nsurl *url,
+ lwc_string *host,
+ const char *realm,
+ nserror (*cb)(bool proceed, void *pw),
+ void *cbpw)
{
struct session_401 *session;
GtkWindow *wnd;
GtkLabel *lhost, *lrealm;
GtkEntry *euser, *epass;
GtkButton *bok, *bcan;
- GtkBuilder* builder;
+ GtkBuilder* builder;
nserror res;
+ session = calloc(1, sizeof(struct session_401));
+ if (session == NULL) {
+ return NSERROR_NOMEM;
+ }
+
res = nsgtk_builder_new_from_resname("login", &builder);
if (res != NSERROR_OK) {
- LOG("Login UI builder init failed");
- return;
+ free(session);
+ return res;
}
gtk_builder_connect_signals(builder, NULL);
@@ -97,8 +169,6 @@ void create_login_window(nsurl *url, lwc_string *host, const char *realm,
bcan = GTK_BUTTON(gtk_builder_get_object(builder, "buttonLoginCan"));
/* create and fill in our session structure */
-
- session = calloc(1, sizeof(struct session_401));
session->url = nsurl_ref(url);
session->host = lwc_string_ref(host);
session->realm = strdup(realm ? realm : "Secure Area");
@@ -120,69 +190,49 @@ void create_login_window(nsurl *url, lwc_string *host, const char *realm,
* window to call functions in this file to process the login
*/
g_signal_connect(G_OBJECT(bok), "clicked",
- G_CALLBACK(nsgtk_login_ok_clicked), (gpointer)session);
+ G_CALLBACK(nsgtk_login_ok_clicked), (gpointer)session);
g_signal_connect(G_OBJECT(bcan), "clicked",
- G_CALLBACK(nsgtk_login_cancel_clicked),
- (gpointer)session);
+ G_CALLBACK(nsgtk_login_cancel_clicked),
+ (gpointer)session);
/* attach signal handlers to the entry boxes such that pressing
* enter in one progresses the focus onto the next widget.
*/
g_signal_connect(G_OBJECT(euser), "activate",
- G_CALLBACK(nsgtk_login_next), (gpointer)epass);
+ G_CALLBACK(nsgtk_login_next), (gpointer)epass);
g_signal_connect(G_OBJECT(epass), "activate",
- G_CALLBACK(nsgtk_login_next), (gpointer)bok);
+ G_CALLBACK(nsgtk_login_next), (gpointer)bok);
/* make sure the username entry box currently has the focus */
gtk_widget_grab_focus(GTK_WIDGET(euser));
/* finally, show the window */
gtk_widget_show(GTK_WIDGET(wnd));
-}
-void destroy_login_window(struct session_401 *session)
-{
- nsurl_unref(session->url);
- lwc_string_unref(session->host);
- free(session->realm);
- gtk_widget_destroy(GTK_WIDGET(session->wnd));
- g_object_unref(G_OBJECT(session->x));
- free(session);
+ return NSERROR_OK;
}
-void nsgtk_login_next(GtkWidget *w, gpointer data)
-{
- gtk_widget_grab_focus(GTK_WIDGET(data));
-}
-void nsgtk_login_ok_clicked(GtkButton *w, gpointer data)
+/* exported function documented in gtk/login.h */
+void gui_401login_open(nsurl *url,
+ const char *realm,
+ nserror (*cb)(bool proceed, void *pw),
+ void *cbpw)
{
- /* close the window and destroy it, having continued the fetch
- * assoicated with it.
- */
-
- struct session_401 *session = (struct session_401 *)data;
- const gchar *user = gtk_entry_get_text(session->user);
- const gchar *pass = gtk_entry_get_text(session->pass);
- char *auth;
-
- auth = malloc(strlen(user) + strlen(pass) + 2);
- sprintf(auth, "%s:%s", user, pass);
- urldb_set_auth_details(session->url, session->realm, auth);
- free(auth);
-
- session->cb(true, session->cbpw);
+ lwc_string *host;
+ nserror res;
- destroy_login_window(session);
-}
+ host = nsurl_get_component(url, NSURL_HOST);
+ assert(host != NULL);
-void nsgtk_login_cancel_clicked(GtkButton *w, gpointer data)
-{
- struct session_401 *session = (struct session_401 *) data;
+ res = create_login_window(url, host, realm, cb, cbpw);
+ if (res != NSERROR_OK) {
+ LOG("Login init failed");
- session->cb(false, session->cbpw);
+ /* creating login failed so cancel navigation */
+ cb(false, cbpw);
+ }
- /* close and destroy the window */
- destroy_login_window(session);
+ lwc_string_unref(host);
}