From a6c595f4f305c43d9da825ad31c0011fe02d0684 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sat, 18 Aug 2018 23:30:12 +0100 Subject: add win32 http authentication dialog --- frontends/windows/Makefile | 2 +- frontends/windows/about.c | 2 +- frontends/windows/about.h | 6 +- frontends/windows/gui.c | 71 ++++++++- frontends/windows/gui.h | 11 ++ frontends/windows/login.c | 297 ++++++++++++++++++++++++++++++++++++++ frontends/windows/login.h | 39 +++++ frontends/windows/main.c | 3 + frontends/windows/res/resource.rc | 12 +- frontends/windows/window.c | 2 +- 10 files changed, 432 insertions(+), 13 deletions(-) create mode 100644 frontends/windows/login.c create mode 100644 frontends/windows/login.h (limited to 'frontends/windows') diff --git a/frontends/windows/Makefile b/frontends/windows/Makefile index de01ce33a..f6995910d 100644 --- a/frontends/windows/Makefile +++ b/frontends/windows/Makefile @@ -50,7 +50,7 @@ S_RESOURCES := windows_resource.o # sources purely for the windows build S_FRONTEND := main.c window.c gui.c drawable.c plot.c findfile.c \ font.c bitmap.c about.c prefs.c download.c filetype.c file.c \ - local_history.c schedule.c windbg.c pointers.c \ + local_history.c schedule.c windbg.c pointers.c login.c \ corewindow.c hotlist.c cookies.c global_history.c ssl_cert.c # This is the final source build list diff --git a/frontends/windows/about.c b/frontends/windows/about.c index f73c0c83a..325587d8a 100644 --- a/frontends/windows/about.c +++ b/frontends/windows/about.c @@ -139,7 +139,7 @@ nsws_about_event_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) return FALSE; } -void nsws_about_dialog_init(HINSTANCE hinst, HWND parent) +void nsw32_about_dialog_init(HINSTANCE hinst, HWND parent) { int ret = DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUT), parent, nsws_about_event_callback); diff --git a/frontends/windows/about.h b/frontends/windows/about.h index e0315b507..807c7b900 100644 --- a/frontends/windows/about.h +++ b/frontends/windows/about.h @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -#ifndef _NETSURF_WINDOWS_ABOUT_H_ -#define _NETSURF_WINDOWS_ABOUT_H_ +#ifndef NETSURF_WINDOWS_ABOUT_H +#define NETSURF_WINDOWS_ABOUT_H -void nsws_about_dialog_init(HINSTANCE hinst, HWND parent); +void nsw32_about_dialog_init(HINSTANCE hinst, HWND parent); #endif diff --git a/frontends/windows/gui.c b/frontends/windows/gui.c index 890bfae42..674484fea 100644 --- a/frontends/windows/gui.c +++ b/frontends/windows/gui.c @@ -52,6 +52,74 @@ HINSTANCE hinst; static bool win32_quit = false; +struct dialog_list_entry { + struct dialog_list_entry *next; + HWND hwnd; +}; + +static struct dialog_list_entry *dlglist = NULL; + +/* exported interface documented in gui.h */ +nserror nsw32_add_dialog(HWND hwndDlg) +{ + struct dialog_list_entry *nentry; + nentry = malloc(sizeof(struct dialog_list_entry)); + if (nentry == NULL) { + return NSERROR_NOMEM; + } + + nentry->hwnd = hwndDlg; + nentry->next = dlglist; + dlglist = nentry; + + return NSERROR_OK; +} + +/* exported interface documented in gui.h */ +nserror nsw32_del_dialog(HWND hwndDlg) +{ + struct dialog_list_entry **prev; + struct dialog_list_entry *cur; + + prev = &dlglist; + cur = *prev; + + while (cur != NULL) { + if (cur->hwnd == hwndDlg) { + /* found match */ + *prev = cur->next; + NSLOG(netsurf, DEBUG, + "removed hwnd %p entry %p", cur->hwnd, cur); + free(cur); + return NSERROR_OK; + } + prev = &cur->next; + cur = *prev; + } + NSLOG(netsurf, INFO, "did not find hwnd %p", hwndDlg); + + return NSERROR_NOT_FOUND; +} + +/** + * walks dialog list and attempts to process any messages for them + */ +static nserror handle_dialog_message(LPMSG lpMsg) +{ + struct dialog_list_entry *cur; + cur = dlglist; + while (cur != NULL) { + if (IsDialogMessage(cur->hwnd, lpMsg)) { + NSLOG(netsurf, DEBUG, + "dispatched dialog hwnd %p", cur->hwnd); + return NSERROR_OK; + } + cur = cur->next; + } + + return NSERROR_NOT_FOUND; +} + /* exported interface documented in gui.h */ void win32_set_quit(bool q) { @@ -92,7 +160,8 @@ void win32_run(void) } } - if (bRet > 0) { + if ((bRet > 0) && + (handle_dialog_message(&Msg) != NSERROR_OK)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } diff --git a/frontends/windows/gui.h b/frontends/windows/gui.h index efbf02924..5fd9decb2 100644 --- a/frontends/windows/gui.h +++ b/frontends/windows/gui.h @@ -56,4 +56,15 @@ void win32_set_quit(bool q); */ nserror win32_warning(const char *warning, const char *detail); +/** + * add a modeless dialog to the special handling list + */ +nserror nsw32_add_dialog(HWND hwndDlg); + +/** + * remove a modeless dialog from the special handling list + */ +nserror nsw32_del_dialog(HWND hwndDlg); + + #endif diff --git a/frontends/windows/login.c b/frontends/windows/login.c new file mode 100644 index 000000000..ca6c9163d --- /dev/null +++ b/frontends/windows/login.c @@ -0,0 +1,297 @@ +/* +* Copyright 2018 Vincent Sanders +* +* 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 . +*/ + +/** + * \file + * This is The win32 API basic authentication login dialog implementation. + */ + +#include + +#include "utils/config.h" + +#include + +#include "utils/log.h" +#include "utils/messages.h" +#include "utils/nsurl.h" +#include "desktop/version.h" + +#include "windows/gui.h" +#include "windows/window.h" +#include "windows/login.h" +#include "windows/resourceid.h" + +#include "windbg.h" + +struct login_ctx { + char *username; + char *password; + char *description; + nserror (*cb)(const char *username, const char *password, void *cbctx); + void *cbctx; +}; + + +/** + * free login dialog context + */ +static nserror +free_loginctx(struct login_ctx *ctx) +{ + free(ctx->username); + free(ctx->password); + free(ctx->description); + free(ctx); + + return NSERROR_OK; +} + + +/** + * generate the description of the login request + */ +static nserror +get_login_description(struct nsurl *url, + const char *realm, + char **out_str) +{ + char *url_s; + size_t url_l; + nserror res; + const char *fmt = "The site %s is requesting your username and password. The realm is \"%s\""; + char *str = NULL; + int strlen; + + res = nsurl_get(url, NSURL_SCHEME | NSURL_HOST, &url_s, &url_l); + if (res != NSERROR_OK) { + return res; + } + + strlen = snprintf(str, 0, fmt, url_s, realm) + 1; + str = malloc(strlen); + if (str == NULL) { + res = NSERROR_NOMEM; + } else { + snprintf(str, strlen, fmt, url_s, realm); + *out_str = str; + } + + free(url_s); + + return res; +} + +/** + * win32 login dialog initialisation handler + */ +static BOOL +login_dialog_init(HWND hwndDlg, WPARAM wParam, LPARAM lParam) +{ + struct login_ctx *ctx; + HWND hwndOwner; + RECT rc, rcDlg, rcOwner; + ctx = (struct login_ctx *)lParam; + + /* make context available in future calls */ + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); + + /* set default contents */ + SetDlgItemText(hwndDlg, IDC_LOGIN_USERNAME, ctx->username); + SetDlgItemText(hwndDlg, IDC_LOGIN_PASSWORD, ctx->password); + SetDlgItemText(hwndDlg, IDC_LOGIN_DESCRIPTION, ctx->description); + + /* Get the owner window and dialog box rectangles. */ + if ((hwndOwner = GetParent(hwndDlg)) == NULL) { + hwndOwner = GetDesktopWindow(); + } + + GetWindowRect(hwndOwner, &rcOwner); + GetWindowRect(hwndDlg, &rcDlg); + CopyRect(&rc, &rcOwner); + + /* Offset the owner and dialog box rectangles so that right + * and bottom values represent the width and height, and then + * offset the owner again to discard space taken up by the + * dialog box. + */ + + OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top); + OffsetRect(&rc, -rc.left, -rc.top); + OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom); + + /* The new position is the sum of half the remaining space and + * the owner's original position. + */ + SetWindowPos(hwndDlg, + HWND_TOP, + rcOwner.left + (rc.right / 2), + rcOwner.top + (rc.bottom / 2), + 0, 0, /* Ignores size arguments. */ + SWP_NOSIZE); + + /* ensure username gets focus */ + if (GetDlgCtrlID((HWND) wParam) != IDC_LOGIN_USERNAME) { + SetFocus(GetDlgItem(hwndDlg, IDC_LOGIN_USERNAME)); + return FALSE; + } + + return TRUE; +} + + +/** + * win32 login dialog ok handler + */ +static BOOL +login_dialog_ok(HWND hwndDlg, struct login_ctx *ctx) +{ + char username[255]; + char password[255]; + + if (GetDlgItemText(hwndDlg, + IDC_LOGIN_USERNAME, + username, + sizeof(username)) == 0) { + username[0]=0; + } + + if (GetDlgItemText(hwndDlg, + IDC_LOGIN_PASSWORD, + password, + sizeof(password)) == 0) { + password[0]=0; + } + + NSLOG(netsurf, DEBUG, + "context %p, user:\"%s\" pw:\"%s\"", ctx, username, password); + + ctx->cb(username, password, ctx->cbctx); + + DestroyWindow(hwndDlg); + + nsw32_del_dialog(hwndDlg); + + free_loginctx(ctx); + + return TRUE; +} + + +/** + * win32 login dialog cancel handler + */ +static BOOL +login_dialog_cancel(HWND hwndDlg, struct login_ctx *ctx) +{ + NSLOG(netsurf, DEBUG, "context %p", ctx); + + ctx->cb(NULL, NULL, ctx->cbctx); + + DestroyWindow(hwndDlg); + + nsw32_del_dialog(hwndDlg); + + free_loginctx(ctx); + + return TRUE; +} + + +/** + * win32 API callback for login dialog + */ +static BOOL CALLBACK +login_dialog_callback(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + struct login_ctx *ctx; + + LOG_WIN_MSG(hwndDlg, message, wParam, lParam); + + /* obtain login dialog context */ + ctx = (struct login_ctx *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + switch (message) { + case WM_INITDIALOG: + return login_dialog_init(hwndDlg, wParam, lParam); + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + return login_dialog_ok(hwndDlg, ctx); + + case IDCANCEL: + return login_dialog_cancel(hwndDlg, ctx); + } + } + return FALSE; +} + + +/** + * Request credentials for http login + */ +nserror +nsw32_401login(nsurl *url, + const char *realm, + const char *username, + const char *password, + nserror (*cb)(const char *username, + const char *password, + void *cbctx), + void *cbctx) +{ + HWND hwndDlg; + struct login_ctx *nctx; + struct gui_window *gw; + nserror res; + + /* locate parent window */ + gw = nsws_get_gui_window(GetActiveWindow()); + if (gw == NULL) { + return NSERROR_INIT_FAILED; + } + + /* setup context for parameters */ + nctx = calloc(1, sizeof(struct login_ctx)); + if (nctx == NULL) { + return NSERROR_NOMEM; + } + + nctx->username = strdup(username); + nctx->password = strdup(password); + nctx->cb = cb; + nctx->cbctx = cbctx; + + res = get_login_description(url, realm, &nctx->description); + if (res != NSERROR_OK) { + free_loginctx(nctx); + return res; + } + + /* create modeless dialog */ + hwndDlg = CreateDialogParam(NULL, + MAKEINTRESOURCE(IDD_LOGIN), + gw->main, + login_dialog_callback, + (LPARAM)nctx); + + nsw32_add_dialog(hwndDlg); + + return NSERROR_OK; +} diff --git a/frontends/windows/login.h b/frontends/windows/login.h new file mode 100644 index 000000000..411306230 --- /dev/null +++ b/frontends/windows/login.h @@ -0,0 +1,39 @@ +/* + * Copyright 2018 Vincent Sanders + * + * 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 . + */ + +/** + * \file + * Basic authentication login interfaces. + */ + +#ifndef NSW32_LOGIN_H +#define NSW32_LOGIN_H + +/** + * login window request. + */ +extern nserror nsw32_401login(nsurl *url, + const char *realm, + const char *username, + const char *password, + nserror (*cb)(const char *username, + const char *password, + void *cbctx), + void *cbctx); + +#endif diff --git a/frontends/windows/main.c b/frontends/windows/main.c index a3a7c2b39..5dd1e7316 100644 --- a/frontends/windows/main.c +++ b/frontends/windows/main.c @@ -45,6 +45,7 @@ #include "windows/drawable.h" #include "windows/corewindow.h" #include "windows/ssl_cert.h" +#include "windows/login.h" #include "windows/download.h" #include "windows/local_history.h" #include "windows/window.h" @@ -272,7 +273,9 @@ static nserror nsw32_option_init(int *pargc, char** argv) static struct gui_misc_table win32_misc_table = { .schedule = win32_schedule, .warning = win32_warning, + .cert_verify = nsw32_cert_verify, + .login = nsw32_401login, }; /** diff --git a/frontends/windows/res/resource.rc b/frontends/windows/res/resource.rc index fb0468a33..746888cc8 100644 --- a/frontends/windows/res/resource.rc +++ b/frontends/windows/res/resource.rc @@ -206,18 +206,18 @@ FONT 8, "Ms Shell Dlg" LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL -IDD_LOGIN DIALOGEX 0, 0, 200, 93 +IDD_LOGIN DIALOGEX 0, 0, 280, 93 STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU CAPTION "Log In" FONT 8, "Ms Shell Dlg" { LTEXT "Password:", 0, 7, 53, 35, 9, SS_LEFT, WS_EX_LEFT LTEXT "User name:", 0, 7, 35, 40, 9, SS_LEFT, WS_EX_LEFT - EDITTEXT IDC_LOGIN_PASSWORD, 49, 50, 144, 14, ES_AUTOHSCROLL, WS_EX_LEFT - LTEXT "The site foo.bar requires authorization for a realm", IDC_LOGIN_DESCRIPTION, 49, 7, 144, 18, SS_LEFT, WS_EX_LEFT - EDITTEXT IDC_LOGIN_USERNAME, 49, 32, 144, 14, ES_AUTOHSCROLL, WS_EX_LEFT - PUSHBUTTON "Cancel", IDCANCEL, 143, 71, 50, 14, 0, WS_EX_LEFT - DEFPUSHBUTTON "Log in", IDOK, 89, 71, 50, 14, 0, WS_EX_LEFT + LTEXT "The site foo.bar requires authorization for a realm", IDC_LOGIN_DESCRIPTION, 49, 7, 224, 18, SS_LEFT, WS_EX_LEFT + EDITTEXT IDC_LOGIN_USERNAME, 49, 32, 224, 14, ES_AUTOHSCROLL, WS_EX_LEFT + EDITTEXT IDC_LOGIN_PASSWORD, 49, 50, 224, 14, ES_AUTOHSCROLL, WS_EX_LEFT + DEFPUSHBUTTON "Log in", IDOK, 169, 71, 50, 14, 0, WS_EX_LEFT + PUSHBUTTON "Cancel", IDCANCEL, 223, 71, 50, 14, 0, WS_EX_LEFT } diff --git a/frontends/windows/window.c b/frontends/windows/window.c index 90d076812..3ccf8295e 100644 --- a/frontends/windows/window.c +++ b/frontends/windows/window.c @@ -1274,7 +1274,7 @@ nsws_window_command(HWND hwnd, break; case IDM_HELP_ABOUT: - nsws_about_dialog_init(hinst, gw->main); + nsw32_about_dialog_init(hinst, gw->main); break; case IDC_MAIN_LAUNCH_URL: -- cgit v1.2.3