1 /* HTTP Auth dialog stuff */
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"
34 struct dialog
*dlg
= data
;
35 struct auth_entry
*entry
= dlg
->udata2
;
36 struct session
*ses
= dlg
->udata
;
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
);
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);
54 add_to_list(submit
, user
);
56 password
= init_submitted_value("password", entry
->password
, FC_PASSWORD
, NULL
, 0);
58 add_to_list(submit
, password
);
61 memorize_form(ses
, &submit
, &form
);
62 done_submitted_value_list(&submit
);
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
);
80 goto_uri_frame(ses
, uri
, NULL
, CACHE_MODE_INCREMENT
);
87 reload(ses
, CACHE_MODE_INCREMENT
);
91 auth_cancel(void *data
)
93 struct auth_entry
*entry
= data
;
96 del_auth_entry(entry
);
99 /* TODO: Take auth_entry from data. --jonas */
101 do_auth_dialog(struct session
*ses
, void *data
)
103 /* [gettext_accelerator_context(do_auth_dialog)] */
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
;
111 if (!a
|| a
->blocked
) return;
113 text
= get_uri_string(a
->uri
, URI_HTTP_AUTH
);
116 #ifdef CONFIG_FORMHIST
118 unsigned char *user
= get_form_history_value(text
, "user");
119 unsigned char *password
= get_form_history_value(text
, "password");
122 strncpy(a
->user
, user
, AUTH_USER_MAXLEN
- 1);
125 strncpy(a
->password
, password
, AUTH_PASSWORD_MAXLEN
- 1);
130 sticker_len
= snprintf(sticker
, sizeof(sticker
),
131 _("Authentication required for %s at %s", term
),
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);
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
;
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
167 if (dlg_data
&& a
->user
[0] && !a
->password
[0])
168 select_widget_by_id(dlg_data
, 1);
173 lock_auth_entry(struct listbox_item
*item
)
175 object_lock((struct auth_entry
*) item
->udata
);
179 unlock_auth_entry(struct listbox_item
*item
)
181 object_unlock((struct auth_entry
*) item
->udata
);
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
;
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. */
216 add_bytes_to_string(&info
, auth_entry
->realm
, len
);
218 add_bytes_to_string(&info
, auth_entry
->realm
, maxlen
);
219 add_to_string(&info
, "...");
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
));
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
)
246 can_delete_auth_entry(struct listbox_item
*item
)
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 */
268 /* cant_delete_used_folder */
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 */
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
= {
297 can_delete_auth_entry
,
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(
313 N_("Authentication manager"),
319 auth_manager(struct session
*ses
)
321 hierbox_browser(&auth_browser
, ses
);