NetSurf
login.c
Go to the documentation of this file.
1 /*
2 * Copyright 2018 Vincent Sanders <vince@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 /**
20  * \file
21  * This is The win32 API basic authentication login dialog implementation.
22  */
23 
24 #include <stdio.h>
25 
26 #include "utils/config.h"
27 
28 #include <windows.h>
29 
30 #include "utils/log.h"
31 #include "utils/messages.h"
32 #include "utils/nsurl.h"
33 #include "desktop/version.h"
34 
35 #include "windows/gui.h"
36 #include "windows/window.h"
37 #include "windows/login.h"
38 #include "windows/resourceid.h"
39 
40 #include "windbg.h"
41 
42 struct login_ctx {
43  char *username;
44  char *password;
45  char *description;
46  nserror (*cb)(const char *username, const char *password, void *cbctx);
47  void *cbctx;
48 };
49 
50 
51 /**
52  * free login dialog context
53  */
54 static nserror
56 {
57  free(ctx->username);
58  free(ctx->password);
59  free(ctx->description);
60  free(ctx);
61 
62  return NSERROR_OK;
63 }
64 
65 
66 /**
67  * generate the description of the login request
68  */
69 static nserror
71  const char *realm,
72  char **out_str)
73 {
74  char *url_s;
75  size_t url_l;
76  nserror res;
77  const char *fmt = "The site %s is requesting your username and password. The realm is \"%s\"";
78  char *str = NULL;
79  int strlen;
80 
81  res = nsurl_get(url, NSURL_SCHEME | NSURL_HOST, &url_s, &url_l);
82  if (res != NSERROR_OK) {
83  return res;
84  }
85 
86  strlen = snprintf(str, 0, fmt, url_s, realm) + 1;
87  str = malloc(strlen);
88  if (str == NULL) {
89  res = NSERROR_NOMEM;
90  } else {
91  snprintf(str, strlen, fmt, url_s, realm);
92  *out_str = str;
93  }
94 
95  free(url_s);
96 
97  return res;
98 }
99 
100 /**
101  * win32 login dialog initialisation handler
102  */
103 static BOOL
104 login_dialog_init(HWND hwndDlg, WPARAM wParam, LPARAM lParam)
105 {
106  struct login_ctx *ctx;
107  HWND hwndOwner;
108  RECT rc, rcDlg, rcOwner;
109  ctx = (struct login_ctx *)lParam;
110 
111  /* make context available in future calls */
112  SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
113 
114  /* set default contents */
115  SetDlgItemText(hwndDlg, IDC_LOGIN_USERNAME, ctx->username);
116  SetDlgItemText(hwndDlg, IDC_LOGIN_PASSWORD, ctx->password);
117  SetDlgItemText(hwndDlg, IDC_LOGIN_DESCRIPTION, ctx->description);
118 
119  /* Get the owner window and dialog box rectangles. */
120  if ((hwndOwner = GetParent(hwndDlg)) == NULL) {
121  hwndOwner = GetDesktopWindow();
122  }
123 
124  GetWindowRect(hwndOwner, &rcOwner);
125  GetWindowRect(hwndDlg, &rcDlg);
126  CopyRect(&rc, &rcOwner);
127 
128  /* Offset the owner and dialog box rectangles so that right
129  * and bottom values represent the width and height, and then
130  * offset the owner again to discard space taken up by the
131  * dialog box.
132  */
133 
134  OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
135  OffsetRect(&rc, -rc.left, -rc.top);
136  OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
137 
138  /* The new position is the sum of half the remaining space and
139  * the owner's original position.
140  */
141  SetWindowPos(hwndDlg,
142  HWND_TOP,
143  rcOwner.left + (rc.right / 2),
144  rcOwner.top + (rc.bottom / 2),
145  0, 0, /* Ignores size arguments. */
146  SWP_NOSIZE);
147 
148  /* ensure username gets focus */
149  if (GetDlgCtrlID((HWND) wParam) != IDC_LOGIN_USERNAME) {
150  SetFocus(GetDlgItem(hwndDlg, IDC_LOGIN_USERNAME));
151  return FALSE;
152  }
153 
154  return TRUE;
155 }
156 
157 
158 /**
159  * win32 login dialog ok handler
160  */
161 static BOOL
162 login_dialog_ok(HWND hwndDlg, struct login_ctx *ctx)
163 {
164  char username[255];
165  char password[255];
166 
167  if (GetDlgItemText(hwndDlg,
169  username,
170  sizeof(username)) == 0) {
171  username[0]=0;
172  }
173 
174  if (GetDlgItemText(hwndDlg,
176  password,
177  sizeof(password)) == 0) {
178  password[0]=0;
179  }
180 
181  NSLOG(netsurf, DEBUG,
182  "context %p, user:\"%s\" pw:\"%s\"", ctx, username, password);
183 
184  ctx->cb(username, password, ctx->cbctx);
185 
186  DestroyWindow(hwndDlg);
187 
188  nsw32_del_dialog(hwndDlg);
189 
190  free_loginctx(ctx);
191 
192  return TRUE;
193 }
194 
195 
196 /**
197  * win32 login dialog cancel handler
198  */
199 static BOOL
200 login_dialog_cancel(HWND hwndDlg, struct login_ctx *ctx)
201 {
202  NSLOG(netsurf, DEBUG, "context %p", ctx);
203 
204  ctx->cb(NULL, NULL, ctx->cbctx);
205 
206  DestroyWindow(hwndDlg);
207 
208  nsw32_del_dialog(hwndDlg);
209 
210  free_loginctx(ctx);
211 
212  return TRUE;
213 }
214 
215 
216 /**
217  * win32 API callback for login dialog
218  */
219 static BOOL CALLBACK
220 login_dialog_callback(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
221 {
222  struct login_ctx *ctx;
223 
224  LOG_WIN_MSG(hwndDlg, message, wParam, lParam);
225 
226  /* obtain login dialog context */
227  ctx = (struct login_ctx *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
228 
229  switch (message) {
230  case WM_INITDIALOG:
231  return login_dialog_init(hwndDlg, wParam, lParam);
232 
233  case WM_COMMAND:
234  switch (LOWORD(wParam)) {
235  case IDOK:
236  return login_dialog_ok(hwndDlg, ctx);
237 
238  case IDCANCEL:
239  return login_dialog_cancel(hwndDlg, ctx);
240  }
241  }
242  return FALSE;
243 }
244 
245 
246 /**
247  * Request credentials for http login
248  */
249 nserror
251  const char *realm,
252  const char *username,
253  const char *password,
254  nserror (*cb)(const char *username,
255  const char *password,
256  void *cbctx),
257  void *cbctx)
258 {
259  HWND hwndDlg;
260  struct login_ctx *nctx;
261  struct gui_window *gw;
262  nserror res;
263 
264  /* locate parent window */
265  gw = nsws_get_gui_window(GetActiveWindow());
266  if (gw == NULL) {
267  return NSERROR_INIT_FAILED;
268  }
269 
270  /* setup context for parameters */
271  nctx = calloc(1, sizeof(struct login_ctx));
272  if (nctx == NULL) {
273  return NSERROR_NOMEM;
274  }
275 
276  nctx->username = strdup(username);
277  nctx->password = strdup(password);
278  nctx->cb = cb;
279  nctx->cbctx = cbctx;
280 
281  res = get_login_description(url, realm, &nctx->description);
282  if (res != NSERROR_OK) {
283  free_loginctx(nctx);
284  return res;
285  }
286 
287  /* create modeless dialog */
288  hwndDlg = CreateDialogParam(NULL,
289  MAKEINTRESOURCE(IDD_LOGIN),
290  gw->main,
292  (LPARAM)nctx);
293 
294  nsw32_add_dialog(hwndDlg);
295 
296  return NSERROR_OK;
297 }
char * description
Definition: login.c:45
void * cbctx
Definition: login.c:47
Localised message support (interface).
char * password
Definition: login.c:44
static nserror get_login_description(struct nsurl *url, const char *realm, char **out_str)
generate the description of the login request
Definition: login.c:70
static nserror free_loginctx(struct login_ctx *ctx)
free login dialog context
Definition: login.c:55
Memory exhaustion.
Definition: errors.h:32
static BOOL login_dialog_init(HWND hwndDlg, WPARAM wParam, LPARAM lParam)
win32 login dialog initialisation handler
Definition: login.c:104
nserror nsurl_get(const nsurl *url, nsurl_component parts, char **url_s, size_t *url_l)
Get URL (section) as a string, from a NetSurf URL object.
Basic authentication login interfaces.
nserror nsw32_add_dialog(HWND hwndDlg)
add a modeless dialog to the special handling list
Definition: gui.c:61
static BOOL login_dialog_cancel(HWND hwndDlg, struct login_ctx *ctx)
win32 login dialog cancel handler
Definition: login.c:200
#define IDC_LOGIN_PASSWORD
Definition: resourceid.h:96
nserror
Enumeration of error codes.
Definition: errors.h:29
struct gui_window * nsws_get_gui_window(HWND hwnd)
Obtain gui window structure from window handle.
Definition: window.c:1722
nserror nsw32_del_dialog(HWND hwndDlg)
remove a modeless dialog from the special handling list
Definition: gui.c:77
char * username
Definition: login.c:43
Initialisation failed.
Definition: errors.h:38
No error.
Definition: errors.h:30
first entry in window list
Definition: gui.c:290
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:115
nserror(* cb)(const char *username, const char *password, void *cbctx)
Definition: login.c:46
Version information interface.
#define IDC_LOGIN_USERNAME
Definition: resourceid.h:95
#define LOG_WIN_MSG(h, m, w, l)
log windows message
Definition: windbg.h:32
static BOOL CALLBACK login_dialog_callback(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
win32 API callback for login dialog
Definition: login.c:220
HWND main
handle to the actual window
Definition: window.h:42
#define IDC_LOGIN_DESCRIPTION
Definition: resourceid.h:97
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)
Request credentials for http login.
Definition: login.c:250
#define IDD_LOGIN
Definition: resourceid.h:94
static BOOL login_dialog_ok(HWND hwndDlg, struct login_ctx *ctx)
win32 login dialog ok handler
Definition: login.c:162
NetSurf URL handling (interface).
struct nsurl nsurl
NetSurf URL object.
Definition: nsurl.h:31