iconv: Bail out of the loop when an illegal sequence of bytes occurs.
[elinks/elinks-j605.git] / src / protocol / auth / dialogs.c
blob71fd4e6f5dafdf93025635d3820c15f1c3d9c029
1 /* HTTP Auth dialog stuff */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <string.h>
9 #include "elinks.h"
11 #include "bfu/dialog.h"
12 #include "document/forms.h"
13 #include "formhist/formhist.h"
14 #include "intl/gettext/libintl.h"
15 #include "main/object.h"
16 #include "protocol/auth/auth.h"
17 #include "protocol/auth/dialogs.h"
18 #include "protocol/uri.h"
19 #include "session/location.h"
20 #include "session/session.h"
21 #include "session/task.h"
22 #include "terminal/terminal.h"
23 #include "util/color.h"
24 #include "util/lists.h"
25 #include "util/memory.h"
26 #include "util/snprintf.h"
27 #include "util/string.h"
28 #include "viewer/text/form.h"
31 static void
32 auth_ok(void *data)
34 struct dialog *dlg = data;
35 struct auth_entry *entry = dlg->udata2;
36 struct session *ses = dlg->udata;
38 entry->blocked = 0;
39 entry->valid = auth_entry_has_userinfo(entry);
41 #ifdef CONFIG_FORMHIST
42 if (get_opt_bool("document.browse.forms.show_formhist", ses)) {
43 unsigned char *url = get_uri_string(entry->uri, URI_HTTP_AUTH);
45 if (url) {
46 struct form form = {
47 .action = url,
49 INIT_LIST_OF(struct submitted_value, submit);
50 struct submitted_value *user, *password;
52 user = init_submitted_value("user", entry->user, FC_TEXT, NULL, 0);
53 if (user) {
54 add_to_list(submit, user);
56 password = init_submitted_value("password", entry->password, FC_PASSWORD, NULL, 0);
57 if (password) {
58 add_to_list(submit, password);
61 memorize_form(ses, &submit, &form);
62 done_submitted_value_list(&submit);
63 mem_free(url);
66 #endif
68 if (entry->valid && have_location(ses)) {
69 struct location *loc = cur_loc(ses);
70 struct uri *uri = loc->vs.uri;
72 /* Make a 'fake' redirect to a URI without user/password so that
73 * the user/password from the URI will not override what the
74 * user just entered in the dialog. */
75 if ((uri->userlen && strlcmp(entry->user, -1, uri->user, uri->userlen))
76 || (uri->password && strlcmp(entry->password, -1, uri->password, uri->passwordlen))) {
78 uri = get_composed_uri(uri, URI_HTTP_AUTH | URI_DATA | URI_POST);
79 if (uri) {
80 goto_uri_frame(ses, uri, NULL, CACHE_MODE_INCREMENT);
81 done_uri(uri);
82 return;
87 reload(ses, CACHE_MODE_INCREMENT);
90 static void
91 auth_cancel(void *data)
93 struct auth_entry *entry = data;
95 entry->blocked = 0;
96 del_auth_entry(entry);
99 /* TODO: Take auth_entry from data. --jonas */
100 void
101 do_auth_dialog(struct session *ses, void *data)
103 /* [gettext_accelerator_context(do_auth_dialog)] */
104 struct dialog *dlg;
105 struct dialog_data *dlg_data;
106 struct terminal *term = ses->tab->term;
107 struct auth_entry *a = get_invalid_auth_entry();
108 unsigned char sticker[MAX_STR_LEN], *text;
109 int sticker_len;
111 if (!a || a->blocked) return;
113 text = get_uri_string(a->uri, URI_HTTP_AUTH);
114 if (!text) return;
116 #ifdef CONFIG_FORMHIST
118 unsigned char *user = get_form_history_value(text, "user");
119 unsigned char *password = get_form_history_value(text, "password");
121 if (user) {
122 strncpy(a->user, user, AUTH_USER_MAXLEN - 1);
124 if (password) {
125 strncpy(a->password, password, AUTH_PASSWORD_MAXLEN - 1);
128 #endif
130 sticker_len = snprintf(sticker, sizeof(sticker),
131 _("Authentication required for %s at %s", term),
132 a->realm, text);
133 mem_free(text);
134 if (sticker_len < 0 || sticker_len > MAX_STR_LEN) return;
136 #define AUTH_WIDGETS_COUNT 5
137 /* + 1 to leave room for the '\0'. */
138 dlg = calloc_dialog(AUTH_WIDGETS_COUNT, sticker_len + 1);
139 if (!dlg) return;
141 a->blocked = 1;
143 /* This function is used for at least HTTP and FTP, so don't
144 * name the protocol here. Consider also what an FTP server
145 * behind an HTTP proxy should be called. */
146 dlg->title = _("Authentication required", term);
147 dlg->layouter = generic_dialog_layouter;
149 text = get_dialog_offset(dlg, AUTH_WIDGETS_COUNT);
150 memcpy(text, sticker, sticker_len); /* calloc_dialog has stored '\0' */
152 dlg->udata = (void *) ses;
153 dlg->udata2 = a;
155 add_dlg_text(dlg, text, ALIGN_LEFT, 0);
156 add_dlg_field_float(dlg, _("Login", term), 0, 0, NULL, AUTH_USER_MAXLEN, a->user, NULL);
157 add_dlg_field_float_pass(dlg, _("Password", term), 0, 0, NULL, AUTH_PASSWORD_MAXLEN, a->password);
159 add_dlg_ok_button(dlg, _("~OK", term), B_ENTER, auth_ok, dlg);
160 add_dlg_ok_button(dlg, _("~Cancel", term), B_ESC, auth_cancel, a);
162 add_dlg_end(dlg, AUTH_WIDGETS_COUNT);
164 dlg_data = do_dialog(term, dlg, getml(dlg, (void *) NULL));
165 /* When there's some username, but no password, automagically jump to
166 * the password. */
167 if (dlg_data && a->user[0] && !a->password[0])
168 select_widget_by_id(dlg_data, 1);
172 static void
173 lock_auth_entry(struct listbox_item *item)
175 object_lock((struct auth_entry *) item->udata);
178 static void
179 unlock_auth_entry(struct listbox_item *item)
181 object_unlock((struct auth_entry *) item->udata);
184 static int
185 is_auth_entry_used(struct listbox_item *item)
187 return is_object_used((struct auth_entry *) item->udata);
190 static unsigned char *
191 get_auth_entry_text(struct listbox_item *item, struct terminal *term)
193 struct auth_entry *auth_entry = item->udata;
195 return get_uri_string(auth_entry->uri, URI_HTTP_AUTH);
198 static unsigned char *
199 get_auth_entry_info(struct listbox_item *item, struct terminal *term)
201 struct auth_entry *auth_entry = item->udata;
202 struct string info;
204 if (item->type == BI_FOLDER) return NULL;
205 if (!init_string(&info)) return NULL;
207 add_format_to_string(&info, "%s: ", _("URL", term));
208 add_uri_to_string(&info, auth_entry->uri, URI_HTTP_AUTH);
210 add_format_to_string(&info, "\n%s: ", _("Realm", term));
211 if (auth_entry->realm) {
212 int len = strlen(auth_entry->realm);
213 int maxlen = 512; /* Max. number of chars displayed for realm. */
215 if (len < maxlen)
216 add_bytes_to_string(&info, auth_entry->realm, len);
217 else {
218 add_bytes_to_string(&info, auth_entry->realm, maxlen);
219 add_to_string(&info, "...");
221 } else {
222 add_to_string(&info, _("none", term));
225 add_format_to_string(&info, "\n%s: %s\n", _("State", term),
226 auth_entry->valid ? _("valid", term) : _("invalid", term));
228 return info.source;
231 static struct uri *
232 get_auth_entry_uri(struct listbox_item *item)
234 struct auth_entry *auth_entry = item->udata;
236 return get_composed_uri(auth_entry->uri, URI_HTTP_AUTH);
239 static struct listbox_item *
240 get_auth_entry_root(struct listbox_item *box_item)
242 return NULL;
245 static int
246 can_delete_auth_entry(struct listbox_item *item)
248 return 1;
251 static void
252 delete_auth_entry(struct listbox_item *item, int last)
254 struct auth_entry *auth_entry = item->udata;
256 assert(!is_object_used(auth_entry));
258 del_auth_entry(auth_entry);
261 static struct listbox_ops_messages http_auth_messages = {
262 /* cant_delete_item */
263 N_("Sorry, but auth entry \"%s\" cannot be deleted."),
264 /* cant_delete_used_item */
265 N_("Sorry, but auth entry \"%s\" is being used by something else."),
266 /* cant_delete_folder */
267 NULL,
268 /* cant_delete_used_folder */
269 NULL,
270 /* delete_marked_items_title */
271 N_("Delete marked auth entries"),
272 /* delete_marked_items */
273 N_("Delete marked auth entries?"),
274 /* delete_folder_title */
275 NULL,
276 /* delete_folder */
277 NULL,
278 /* delete_item_title */
279 N_("Delete auth entry"),
280 /* delete_item; xgettext:c-format */
281 N_("Delete this auth entry?"),
282 /* clear_all_items_title */
283 N_("Clear all auth entries"),
284 /* clear_all_items_title */
285 N_("Do you really want to remove all auth entries?"),
288 static const struct listbox_ops auth_listbox_ops = {
289 lock_auth_entry,
290 unlock_auth_entry,
291 is_auth_entry_used,
292 get_auth_entry_text,
293 get_auth_entry_info,
294 get_auth_entry_uri,
295 get_auth_entry_root,
296 NULL,
297 can_delete_auth_entry,
298 delete_auth_entry,
299 NULL,
300 &http_auth_messages,
303 static const struct hierbox_browser_button auth_buttons[] = {
304 /* [gettext_accelerator_context(.auth_buttons)] */
305 { N_("~Goto"), push_hierbox_goto_button, 1 },
306 { N_("~Info"), push_hierbox_info_button, 1 },
307 { N_("~Delete"), push_hierbox_delete_button, 1 },
308 { N_("C~lear"), push_hierbox_clear_button, 1 },
311 struct_hierbox_browser(
312 auth_browser,
313 N_("Authentication manager"),
314 auth_buttons,
315 &auth_listbox_ops
318 void
319 auth_manager(struct session *ses)
321 hierbox_browser(&auth_browser, ses);