From c9e188a4d1634d9c7d2292a8d04e02f313f37f3b Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Sat, 25 Oct 2003 19:20:13 +0000 Subject: [project @ 2003-10-25 19:20:13 by jmb] HTTP Auth login improved (greatly). Addresses all three issues in the previous version. svn path=/import/netsurf/; revision=382 --- content/content.h | 3 +- content/fetch.c | 15 ++---- content/fetch.h | 2 +- content/fetchcache.c | 8 +++ desktop/401login.h | 14 +++++- desktop/browser.c | 15 +++++- desktop/loginlist.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++ makefile | 2 +- render/html.c | 6 +++ riscos/401login.c | 52 ++++++++++--------- utils/utils.c | 25 ++++++++-- utils/utils.h | 1 + 12 files changed, 234 insertions(+), 46 deletions(-) create mode 100644 desktop/loginlist.c diff --git a/content/content.h b/content/content.h index 249e21192..72034b316 100644 --- a/content/content.h +++ b/content/content.h @@ -71,7 +71,8 @@ typedef enum { CONTENT_MSG_ERROR, /**< error occurred */ CONTENT_MSG_STATUS, /**< new status string */ CONTENT_MSG_REDIRECT, /**< replacement URL */ - CONTENT_MSG_REFORMAT /**< content_reformat done */ + CONTENT_MSG_REFORMAT, /**< content_reformat done */ + CONTENT_MSG_AUTH /**< authentication required */ } content_msg; /** Linked list of users of a content. */ diff --git a/content/fetch.c b/content/fetch.c index b7f48b506..391aa14d3 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -150,6 +150,7 @@ struct fetch * fetch_start(char *url, char *referer, CURLcode code; CURLMcode codem; xmlURI *uri; + struct login *li; LOG(("fetch %p, url '%s'", fetch, url)); @@ -268,12 +269,11 @@ struct fetch * fetch_start(char *url, char *referer, code = curl_easy_setopt(fetch->curl_handle, CURLOPT_HTTPAUTH, (long)CURLAUTH_BASIC); assert(code == CURLE_OK); -#ifdef riscos - if (LOGIN.string != NULL) { - code = curl_easy_setopt(fetch->curl_handle, CURLOPT_USERPWD, LOGIN.string); + if ((li=login_list_get(url)) != NULL) { + code = curl_easy_setopt(fetch->curl_handle, CURLOPT_USERPWD, li->logindetails); + assert(code == CURLE_OK); } -#endif /* POST */ if (fetch->post_urlenc) { @@ -545,16 +545,11 @@ bool fetch_process_headers(struct fetch *f) return true; } -#ifdef riscos /* handle HTTP 401 (Authentication errors) */ if (http_code == 401) { - /* this shouldn't be here... */ - ro_gui_401login_open(xstrdup(f->host), xstrdup(f->realm), - xstrdup(f->url)); - f->callback(FETCH_ERROR, f->p, "",0); + f->callback(FETCH_AUTH, f->p, xstrdup(f->realm),0); return true; } -#endif /* handle HTTP errors (non 2xx response codes) */ if (f->only_2xx && strncmp(f->url, "http", 4) == 0 && diff --git a/content/fetch.h b/content/fetch.h index 762664923..492645df9 100644 --- a/content/fetch.h +++ b/content/fetch.h @@ -14,7 +14,7 @@ #include -typedef enum {FETCH_TYPE, FETCH_DATA, FETCH_FINISHED, FETCH_ERROR, FETCH_REDIRECT} fetch_msg; +typedef enum {FETCH_TYPE, FETCH_DATA, FETCH_FINISHED, FETCH_ERROR, FETCH_REDIRECT, FETCH_AUTH} fetch_msg; struct content; struct fetch; diff --git a/content/fetchcache.c b/content/fetchcache.c index 13ddbc9c5..28c098034 100644 --- a/content/fetchcache.c +++ b/content/fetchcache.c @@ -154,6 +154,14 @@ void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size) content_destroy(c); break; + case FETCH_AUTH: + /* data -> string containing the Realm */ + LOG(("FETCH_AUTH, '%s'", data)); + c->fetch = 0; + content_broadcast(c, CONTENT_MSG_AUTH, data); + cache_destroy(c); + break; + default: assert(0); } diff --git a/desktop/401login.h b/desktop/401login.h index f9a999ebd..d9262c54c 100644 --- a/desktop/401login.h +++ b/desktop/401login.h @@ -8,11 +8,21 @@ #ifndef NETSURF_DESKTOP_401LOGIN_H #define NETSURF_DESKTOP_401LOGIN_H +#include "netsurf/content/content.h" +#include "netsurf/desktop/browser.h" + struct login { - char *string; + char *host; /**< hostname */ + char *logindetails; /**< string containing "username:password" */ + struct login *next; /**< next in list */ + struct login *prev; /**< previous in list */ }; -extern struct login LOGIN; +void gui_401login_open(struct browser_window *bw, struct content *c, + char *realm); +void login_list_add(char *host, char *logindets); +struct login *login_list_get(char *host); +void login_list_remove(char *host); #endif diff --git a/desktop/browser.c b/desktop/browser.c index 16fc03126..8e311eee8 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -18,6 +18,7 @@ #include "netsurf/content/cache.h" #include "netsurf/content/fetchcache.h" #include "netsurf/css/css.h" +#include "netsurf/desktop/401login.h" #include "netsurf/desktop/browser.h" #include "netsurf/render/box.h" #include "netsurf/render/font.h" @@ -208,6 +209,7 @@ void browser_window_destroy(struct browser_window* bw) if (bw->current_content->status == CONTENT_STATUS_DONE) content_remove_instance(bw->current_content, bw, 0, 0, 0, &bw->current_content_state); content_remove_user(bw->current_content, browser_window_callback, bw, 0); + login_list_remove(bw->current_content->url); } if (bw->loading_content != NULL) { content_remove_user(bw->loading_content, browser_window_callback, bw, 0); @@ -248,10 +250,18 @@ void browser_window_open_location_historical(struct browser_window* bw, const char* url, char *post_urlenc, struct form_successful_control *post_multipart) { + struct login *li; LOG(("bw = %p, url = %s", bw, url)); assert(bw != 0 && url != 0); + if ((li = login_list_get(url)) == NULL) { + + if (bw->current_content != NULL) { + login_list_remove(bw->current_content->url); + } + } + browser_window_set_status(bw, "Opening page..."); browser_window_start_throbber(bw); bw->time0 = clock(); @@ -376,7 +386,6 @@ void browser_window_callback(content_msg msg, struct content *c, case CONTENT_MSG_REDIRECT: bw->loading_content = 0; - bw->url = xstrdup(error); browser_window_set_status(bw, "Redirecting"); /* error actually holds the new URL */ browser_window_open_location(bw, error); @@ -386,6 +395,10 @@ void browser_window_callback(content_msg msg, struct content *c, browser_window_reformat(bw, 0); break; + case CONTENT_MSG_AUTH: + gui_401login_open(bw, c, error); + break; + default: assert(0); } diff --git a/desktop/loginlist.c b/desktop/loginlist.c new file mode 100644 index 000000000..08b1822c1 --- /dev/null +++ b/desktop/loginlist.c @@ -0,0 +1,137 @@ +/* + * This file is part of NetSurf, http://netsurf.sourceforge.net/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2003 John M Bell + */ + +#include +#include +#include "netsurf/desktop/401login.h" +#include "netsurf/utils/log.h" +#include "netsurf/utils/utils.h" + +#define NDEBUG + +void login_list_dump(void); + +/** + * Pointer into the linked list + */ +static struct login login = {0, 0, &login, &login}; +static struct login *loginlist = &login; + +/** + * Adds an item to the list of login details + */ +void login_list_add(char *host, char* logindets) { + + struct login *nli = xcalloc(1, sizeof(*nli)); + char *temp = xstrdup(host); + char *i; + + /* Go back to the path base ie strip the document name + * eg. http://www.blah.com/blah/test.htm becomes + * http://www.blah.com/blah/ + * This does, however, mean that directories MUST have a '/' at the end + */ + if (temp[strlen(temp)-1] != '/') { + i = strrchr(temp, '/'); + temp[(i-temp)+1] = 0; + } + + nli->host = xstrdup(temp); + nli->logindetails = xstrdup(logindets); + nli->prev = loginlist->prev; + nli->next = loginlist; + loginlist->prev->next = nli; + loginlist->prev = nli; + + LOG(("Adding %s : %s", temp, logindets)); +#ifndef NDEBUG + login_list_dump(); +#endif + xfree(temp); +} + +/** + * Retrieves an element from the login list + */ +struct login *login_list_get(char *host) { + + struct login *nli; + char *temp, *temphost; + char* i; + + if (host == NULL) + return NULL; + + temphost = get_host_from_url(host); + temp = xstrdup(host); + + /* Work backwards through the path, directory at at time. + * Finds the closest match. + * eg. http://www.blah.com/moo/ matches the url + * http://www.blah.com/moo/test/index.htm + * This allows multiple realms (and login details) per host. + * Only one set of login details per realm are allowed. + */ + while (strcasecmp(temp, temphost) != 0) { + + LOG(("%s, %d", temp, strlen(temp))); + + for (nli = loginlist->next; nli != loginlist && + (strcasecmp(nli->host, temp)!=0); + nli = nli->next) ; + + if (temp[strlen(temp)-1] == '/') { + temp[strlen(temp)-1] = 0; + } + + i = strrchr(temp, '/'); + + temp[(i-temp)+1] = 0; + + if (nli != loginlist) { + LOG(("Got %s", nli->host)); + xfree(temphost); + return nli; + } + } + + xfree(temphost); + return NULL; +} + +/** + * Remove a realm's login details from the list + */ +void login_list_remove(char *host) { + + struct login *nli = login_list_get(host); + + if (nli != NULL) { + nli->prev->next = nli->next; + nli->next->prev = nli->prev; + xfree(nli->logindetails); + xfree(nli->host); + xfree(nli); + } + + LOG(("Removing %s", host)); +#ifndef NDEBUG + login_list_dump(); +#endif +} + +/** + * Dumps the list of login details (base paths only) + */ +void login_list_dump(void) { + + struct login *nli; + + for (nli = loginlist->next; nli != loginlist; nli = nli->next) { + LOG(("%s", nli->host)); + } +} diff --git a/makefile b/makefile index 1efd0c5ae..78e2143b5 100644 --- a/makefile +++ b/makefile @@ -11,7 +11,7 @@ OBJECTS_COMMON = cache.o content.o fetch.o fetchcache.o other.o \ box.o form.o html.o layout.o textplain.o \ messages.o utils.o OBJECTS = $(OBJECTS_COMMON) \ - browser.o netsurf.o \ + browser.o loginlist.o netsurf.o \ htmlredraw.o \ 401login.o dialog.o download.o gui.o menus.o mouseactions.o \ options.o textselection.o theme.o \ diff --git a/render/html.c b/render/html.c index e023de9e8..30fb0dec5 100644 --- a/render/html.c +++ b/render/html.c @@ -191,6 +191,9 @@ void html_convert_css_callback(content_msg msg, struct content *css, c->active++; break; + case CONTENT_MSG_AUTH: + break; + default: assert(0); } @@ -479,6 +482,9 @@ void html_object_callback(content_msg msg, struct content *object, case CONTENT_MSG_REFORMAT: break; + case CONTENT_MSG_AUTH: + break; + default: assert(0); } diff --git a/riscos/401login.c b/riscos/401login.c index edd081cc0..81f4ba75e 100644 --- a/riscos/401login.c +++ b/riscos/401login.c @@ -6,8 +6,11 @@ */ #include +#include #include #include "oslib/wimp.h" +#include "netsurf/content/content.h" +#include "netsurf/desktop/browser.h" #include "netsurf/desktop/401login.h" #include "netsurf/desktop/gui.h" #include "netsurf/riscos/gui.h" @@ -16,7 +19,6 @@ #include "netsurf/utils/utils.h" static void get_unamepwd(void); -static void do_thing(void); static wimp_window *dialog_401; extern wimp_w dialog_401li; @@ -26,6 +28,7 @@ struct login LOGIN; static char *uname; static char* url; static char *pwd; +static struct browser_window *bwin; /** * Load the 401 login window template. @@ -50,6 +53,21 @@ void ro_gui_401login_init(void) wimp_NO_FONTS, name, 0, 0, 0); } +void gui_401login_open(struct browser_window *bw, struct content *c, char *realm) { + + char *murl, *host; + int i; + + murl = c->url; + host = get_host_from_url(murl); + bwin = bw; + + ro_gui_401login_open(host, realm, murl); + + xfree(host); +} + + /** * Open a 401 login window. */ @@ -62,7 +80,7 @@ void ro_gui_401login_open(char *host, char* realm, char *fetchurl) /* fill in download window icons */ dialog_401->icons[ICON_401LOGIN_HOST].data.indirected_text.text = - host; + xstrdup(host); dialog_401->icons[ICON_401LOGIN_HOST].data.indirected_text.size = strlen(host) + 1; dialog_401->icons[ICON_401LOGIN_REALM].data.indirected_text.text = @@ -90,12 +108,9 @@ void ro_gui_401login_click(wimp_pointer *pointer) { switch (pointer->i) { case ICON_401LOGIN_LOGIN: if (pointer->buttons == wimp_CLICK_SELECT) { - LOG(("here")); get_unamepwd(); ro_gui_dialog_close(dialog_401li); - do_thing(); - LOGIN.string = 0; /* TODO: keep the details until we - * access a new site */ + browser_window_open_location(bwin, url); } else ro_gui_dialog_close(dialog_401li); @@ -106,9 +121,7 @@ void ro_gui_401login_click(wimp_pointer *pointer) { else { get_unamepwd(); ro_gui_dialog_close(dialog_401li); - do_thing(); - LOGIN.string = 0; /* TODO: keep the details until we - * access a new site */ + browser_window_open_location(bwin, url); } break; default: break; @@ -117,24 +130,9 @@ void ro_gui_401login_click(wimp_pointer *pointer) { void get_unamepwd() { - LOGIN.string = xcalloc(strlen(uname)+strlen(pwd)+2, sizeof(char)); - - sprintf(LOGIN.string, "%s:%s", uname, pwd); - LOG(("%s", LOGIN.string)); -} + char *lidets = xcalloc(strlen(uname)+strlen(pwd)+2, sizeof(char)); -void do_thing() { + sprintf(lidets, "%s:%s", uname, pwd); - struct gui_window *gw; - - /* TODO: fix this. For now we just open the page in the - * first window in the list. */ - for (gw=window_list; gw!=NULL; gw=gw->next) { - if (gw->type == GUI_BROWSER_WINDOW /*&& - (strcasecmp(gw->url, url)==0 || - strcasecmp(gw->data.browser.bw->url, url)==0)*/) - break; - } - if (gw != NULL) - browser_window_open_location_historical(gw->data.browser.bw, url, 0, 0); + login_list_add(url, lidets); } diff --git a/utils/utils.c b/utils/utils.c index bc912fdc7..ca7d7f2fc 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -197,14 +197,14 @@ char *url_join(const char* new, const char* base) nn[j] = new[i]; k = j; } - + j++; } if(k < j){ nn[k+1] = '\0'; LOG(("before: %s after: %s", new, nn)); } - + new = nn; if (base == 0) @@ -252,7 +252,26 @@ char *url_join(const char* new, const char* base) strcpy(ret, new); } - xfree(nn); + xfree(nn); return ret; } +char *get_host_from_url (char *url) { + + char *host = xcalloc(strlen(url)+10, sizeof(char)); + int i; + + i = strspn(url, "abcdefghijklmnopqrstuvwxyz"); + if (url[i] == ':') { + strcpy(host, url); + i += 3; + } + + for (; host[i] != 0 && host[i] != '/'; i++) + host[i] = tolower(host[i]); + + host[i] = '/'; + host[i+1] = 0; + + return host; +} diff --git a/utils/utils.h b/utils/utils.h index 9403d194e..30050b0ae 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -24,5 +24,6 @@ char * tolat1(xmlChar * s); char * tolat1_pre(xmlChar * s); char *squash_tolat1(xmlChar *s); char *url_join(const char* new, const char* base); +char *get_host_from_url(char* url); #endif -- cgit v1.2.3