/* * Copyright 2006 Rob Kendrick * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include "utils/log.h" #include "utils/nsurl.h" #include "utils/messages.h" #include "netsurf/url_db.h" #include "gtk/resources.h" #include "gtk/login.h" /** login window session data */ struct session_401 { nserror (*cb)(const char *username, const char *password, void *pw); /**< Continuation callback */ void *cbpw; /**< Continuation data */ GtkBuilder *x; /**< Our builder windows */ GtkWindow *wnd; /**< The login window itself */ GtkEntry *user; /**< Widget with username */ GtkEntry *pass; /**< Widget with password */ }; /** * 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) { gtk_widget_destroy(GTK_WIDGET(session->wnd)); g_object_unref(G_OBJECT(session->x)); free(session); } /** * process next signal in entry widgets. * * \param w current widget * \param data next widget */ static void nsgtk_login_next(GtkWidget *w, gpointer data) { gtk_widget_grab_focus(GTK_WIDGET(data)); } /** * 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; const gchar *pass; user = gtk_entry_get_text(session->user); pass = gtk_entry_get_text(session->pass); session->cb(user, pass, 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(NULL, NULL, session->cbpw); /* close and destroy the window */ destroy_login_window(session); } /** * generate the description of the login request */ static nserror get_login_description(struct nsurl *url, const char *realm, const char *username, const char *password, char **out_str) { char *url_s; size_t url_l; nserror res; char *str = NULL; int slen; const char *key; res = nsurl_get(url, NSURL_SCHEME | NSURL_HOST, &url_s, &url_l); if (res != NSERROR_OK) { return res; } if ((*username == 0) && (*password == 0)) { key = "LoginDescription"; } else { key = "LoginAgain"; } str = messages_get_buff(key, url_s, realm); NSLOG(netsurf, INFO, "key:%s url:%s realm:%s str:%s", key, url_s, realm, str); if ((str != NULL) && (strcmp(key, str) != 0)) { *out_str = str; } else { /* no message so fallback */ const char *fmt = "The site %s is requesting your username and password. The realm is \"%s\""; slen = snprintf(str, 0, fmt, url_s, realm) + 1; str = malloc(slen); if (str == NULL) { res = NSERROR_NOMEM; } else { snprintf(str, slen, fmt, url_s, realm); *out_str = str; } } free(url_s); return res; } /** * 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. */ static nserror create_login_window(nsurl *url, lwc_string *host, const char *realm, const char *username, const char *password, nserror (*cb)(const char *username, const char *password, void *pw), void *cbpw) { nserror res; struct session_401 *session; GtkWindow *wnd; GtkLabel *ldesc; GtkEntry *euser, *epass; GtkButton *bok, *bcan; GtkBuilder *builder; char *description = NULL; 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) { free(session); return res; } gtk_builder_connect_signals(builder, NULL); wnd = GTK_WINDOW(gtk_builder_get_object(builder, "LoginDialog")); ldesc = GTK_LABEL(gtk_builder_get_object(builder, "LoginDescription")); euser = GTK_ENTRY(gtk_builder_get_object(builder, "LoginUsername")); epass = GTK_ENTRY(gtk_builder_get_object(builder, "LoginPassword")); bok = GTK_BUTTON(gtk_builder_get_object(builder, "LoginOK")); bcan = GTK_BUTTON(gtk_builder_get_object(builder, "LoginCancel")); /* create and fill in our session structure */ session->cb = cb; session->cbpw = cbpw; session->x = builder; session->wnd = wnd; session->user = euser; session->pass = epass; /* fill in our new login window */ res = get_login_description(url, realm, username, password, &description); if (res == NSERROR_OK) { gtk_label_set_text(GTK_LABEL(ldesc), description); free(description); } gtk_entry_set_text(euser, username); gtk_entry_set_text(epass, password); /* attach signal handlers to the Login and Cancel buttons in our new * 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_signal_connect(G_OBJECT(bcan), "clicked", 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_signal_connect(G_OBJECT(epass), "activate", 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)); return NSERROR_OK; } /* exported function documented in gtk/login.h */ nserror gui_401login_open(nsurl *url, const char *realm, const char *username, const char *password, nserror (*cb)(const char *username, const char *password, void *pw), void *cbpw) { lwc_string *host; nserror res; host = nsurl_get_component(url, NSURL_HOST); assert(host != NULL); res = create_login_window(url, host, realm, username, password, cb, cbpw); if (res != NSERROR_OK) { NSLOG(netsurf, INFO, "Login init failed"); return res; } lwc_string_unref(host); return NSERROR_OK; }