30 instead of 10. Python tutorial looks better.
[elinks.git] / src / cookies / dialogs.c
blob597e9fbc24864fe9432350724cbd5ddd6a16c2d9
1 /* Cookie-related dialogs */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <errno.h>
8 #include <stdlib.h>
9 #include <string.h>
11 #include "elinks.h"
13 #include "bfu/dialog.h"
14 #include "cookies/cookies.h"
15 #include "cookies/dialogs.h"
16 #include "dialogs/edit.h"
17 #include "intl/gettext/libintl.h"
18 #include "main/object.h"
19 #include "session/session.h"
20 #include "terminal/draw.h"
21 #include "terminal/terminal.h"
22 #include "util/conv.h"
23 #include "util/lists.h"
24 #include "util/memory.h"
25 #include "util/string.h"
28 INIT_LIST_OF(struct cookie, cookie_queries);
30 static void
31 add_cookie_info_to_string(struct string *string, struct cookie *cookie,
32 struct terminal *term)
34 add_format_to_string(string, "\n%s: %s", _("Name", term), cookie->name);
35 add_format_to_string(string, "\n%s: %s", _("Value", term), cookie->value);
36 add_format_to_string(string, "\n%s: %s", _("Domain", term), cookie->domain);
37 add_format_to_string(string, "\n%s: %s", _("Path", term), cookie->path);
39 if (!cookie->expires) {
40 add_format_to_string(string, "\n%s: ", _("Expires", term));
41 add_to_string(string, _("at quit time", term));
42 #ifdef HAVE_STRFTIME
43 } else {
44 add_format_to_string(string, "\n%s: ", _("Expires", term));
45 add_date_to_string(string, get_opt_str("ui.date_format", NULL), &cookie->expires);
46 #endif
49 add_format_to_string(string, "\n%s: %s", _("Secure", term),
50 _(cookie->secure ? N_("yes") : N_("no"), term));
53 static void
54 accept_cookie_in_msg_box(void *cookie_)
56 accept_cookie((struct cookie *) cookie_);
59 static void
60 reject_cookie_in_msg_box(void *cookie_)
62 done_cookie((struct cookie *) cookie_);
65 /* TODO: Store cookie in data arg. --jonas*/
66 void
67 accept_cookie_dialog(struct session *ses, void *data)
69 /* [gettext_accelerator_context(accept_cookie_dialog)] */
70 struct cookie *cookie = cookie_queries.next;
71 struct string string;
73 assert(ses);
75 if (list_empty(cookie_queries)
76 || !init_string(&string))
77 return;
79 del_from_list(cookie);
81 add_format_to_string(&string,
82 _("Do you want to accept a cookie from %s?", ses->tab->term),
83 cookie->server->host);
85 add_to_string(&string, "\n\n");
87 add_cookie_info_to_string(&string, cookie, ses->tab->term);
89 msg_box(ses->tab->term, NULL, MSGBOX_FREE_TEXT,
90 N_("Accept cookie?"), ALIGN_LEFT,
91 string.source,
92 cookie, 2,
93 MSG_BOX_BUTTON(N_("~Accept"), accept_cookie_in_msg_box, B_ENTER),
94 MSG_BOX_BUTTON(N_("~Reject"), reject_cookie_in_msg_box, B_ESC));
98 static void
99 lock_cookie(struct listbox_item *item)
101 if (item->type == BI_LEAF)
102 object_lock((struct cookie *) item->udata);
103 else
104 object_lock((struct cookie_server *) item->udata);
107 static void
108 unlock_cookie(struct listbox_item *item)
110 if (item->type == BI_LEAF)
111 object_unlock((struct cookie *) item->udata);
112 else
113 object_unlock((struct cookie_server *) item->udata);
116 static int
117 is_cookie_used(struct listbox_item *item)
119 if (item->type == BI_FOLDER) {
120 struct listbox_item *root = item;
122 foreach (item, root->child)
123 if (is_object_used((struct cookie *) item->udata))
124 return 1;
126 return 0;
129 return is_object_used((struct cookie *) item->udata);
132 static unsigned char *
133 get_cookie_text(struct listbox_item *item, struct terminal *term)
135 /* Are we dealing with a folder? */
136 if (item->type == BI_FOLDER) {
137 struct cookie_server *server = item->udata;
139 return stracpy(server->host);
141 } else {
142 struct cookie *cookie = item->udata;
144 return stracpy(cookie->name);
148 static unsigned char *
149 get_cookie_info(struct listbox_item *item, struct terminal *term)
151 struct cookie *cookie = item->udata;
152 struct cookie_server *server;
153 struct string string;
155 if (item->type == BI_FOLDER) return NULL;
157 if (!init_string(&string)) return NULL;
159 server = cookie->server;
161 add_format_to_string(&string, "%s: %s", _("Server", term), server->host);
163 add_cookie_info_to_string(&string, cookie, term);
165 return string.source;
168 static struct listbox_item *
169 get_cookie_root(struct listbox_item *item)
171 /* Are we dealing with a folder? */
172 if (item->type == BI_FOLDER) {
173 return NULL;
174 } else {
175 struct cookie *cookie = item->udata;
177 return cookie->server->box_item;
181 static int
182 can_delete_cookie(struct listbox_item *item)
184 return 1;
187 static void
188 delete_cookie_item(struct listbox_item *item, int last)
190 struct cookie *cookie = item->udata;
192 if (item->type == BI_FOLDER) {
193 struct listbox_item *next, *root = item;
195 /* Releasing refcounts on the cookie_server will automagically
196 * delete it. */
197 foreachsafe (item, next, root->child)
198 delete_cookie_item(item, 0);
199 } else {
200 assert(!is_object_used(cookie));
202 delete_cookie(cookie);
203 set_cookies_dirty();
207 static struct listbox_ops_messages cookies_messages = {
208 /* cant_delete_item */
209 N_("Sorry, but cookie \"%s\" cannot be deleted."),
210 /* cant_delete_used_item */
211 N_("Sorry, but cookie \"%s\" is being used by something else."),
212 /* cant_delete_folder */
213 N_("Sorry, but cookie domain \"%s\" cannot be deleted."),
214 /* cant_delete_used_folder */
215 N_("Sorry, but cookie domain \"%s\" is being used by something else."),
216 /* delete_marked_items_title */
217 N_("Delete marked cookies"),
218 /* delete_marked_items */
219 N_("Delete marked cookies?"),
220 /* delete_folder_title */
221 N_("Delete domain's cookies"),
222 /* delete_folder */
223 N_("Delete all cookies from domain \"%s\"?"),
224 /* delete_item_title */
225 N_("Delete cookie"),
226 /* delete_item; xgettext:c-format */
227 N_("Delete this cookie?"),
228 /* clear_all_items_title */
229 N_("Clear all cookies"),
230 /* clear_all_items_title */
231 N_("Do you really want to remove all cookies?"),
234 static const struct listbox_ops cookies_listbox_ops = {
235 lock_cookie,
236 unlock_cookie,
237 is_cookie_used,
238 get_cookie_text,
239 get_cookie_info,
240 NULL,
241 get_cookie_root,
242 NULL,
243 can_delete_cookie,
244 delete_cookie_item,
245 NULL,
246 &cookies_messages,
249 static widget_handler_status_T
250 set_cookie_name(struct dialog_data *dlg_data, struct widget_data *widget_data)
252 struct cookie *cookie = dlg_data->dlg->udata;
253 unsigned char *value = widget_data->cdata;
255 if (!value || !cookie) return EVENT_NOT_PROCESSED;
256 mem_free_set(&cookie->name, stracpy(value));
257 set_cookies_dirty();
258 return EVENT_PROCESSED;
261 static widget_handler_status_T
262 set_cookie_value(struct dialog_data *dlg_data, struct widget_data *widget_data)
264 struct cookie *cookie = dlg_data->dlg->udata;
265 unsigned char *value = widget_data->cdata;
267 if (!value || !cookie) return EVENT_NOT_PROCESSED;
268 mem_free_set(&cookie->value, stracpy(value));
269 set_cookies_dirty();
270 return EVENT_PROCESSED;
273 static widget_handler_status_T
274 set_cookie_domain(struct dialog_data *dlg_data, struct widget_data *widget_data)
276 struct cookie *cookie = dlg_data->dlg->udata;
277 unsigned char *value = widget_data->cdata;
279 if (!value || !cookie) return EVENT_NOT_PROCESSED;
280 mem_free_set(&cookie->domain, stracpy(value));
281 set_cookies_dirty();
282 return EVENT_PROCESSED;
285 static widget_handler_status_T
286 set_cookie_expires(struct dialog_data *dlg_data, struct widget_data *widget_data)
288 struct cookie *cookie = dlg_data->dlg->udata;
289 unsigned char *value = widget_data->cdata;
290 unsigned char *end;
291 long number;
293 if (!value || !cookie) return EVENT_NOT_PROCESSED;
295 /* Bug 923: Assumes time_t values fit in long. */
296 errno = 0;
297 number = strtol(value, (char **) &end, 10);
298 if (errno || *end || number < 0) return EVENT_NOT_PROCESSED;
300 cookie->expires = (time_t) number;
301 set_cookies_dirty();
302 return EVENT_PROCESSED;
305 static widget_handler_status_T
306 set_cookie_secure(struct dialog_data *dlg_data, struct widget_data *widget_data)
308 struct cookie *cookie = dlg_data->dlg->udata;
309 unsigned char *value = widget_data->cdata;
310 unsigned char *end;
311 long number;
313 if (!value || !cookie) return EVENT_NOT_PROCESSED;
315 errno = 0;
316 number = strtol(value, (char **) &end, 10);
317 if (errno || *end) return EVENT_NOT_PROCESSED;
319 cookie->secure = (number != 0);
320 set_cookies_dirty();
321 return EVENT_PROCESSED;
324 static void
325 build_edit_dialog(struct terminal *term, struct cookie *cookie)
327 #define EDIT_WIDGETS_COUNT 8
328 /* [gettext_accelerator_context(.build_edit_dialog)] */
329 struct dialog *dlg;
330 unsigned char *name, *value, *domain, *expires, *secure;
331 unsigned char *dlg_server;
332 int length = 0;
334 dlg = calloc_dialog(EDIT_WIDGETS_COUNT, MAX_STR_LEN * 5);
335 if (!dlg) return;
337 dlg->title = _("Edit", term);
338 dlg->layouter = generic_dialog_layouter;
339 dlg->udata = cookie;
340 dlg->udata2 = NULL;
342 name = get_dialog_offset(dlg, EDIT_WIDGETS_COUNT);
343 value = name + MAX_STR_LEN;
344 domain = value + MAX_STR_LEN;
345 expires = domain + MAX_STR_LEN;
346 secure = expires + MAX_STR_LEN;
348 safe_strncpy(name, cookie->name, MAX_STR_LEN);
349 safe_strncpy(value, cookie->value, MAX_STR_LEN);
350 safe_strncpy(domain, cookie->domain, MAX_STR_LEN);
351 /* Bug 923: Assumes time_t values fit in unsigned long. */
352 ulongcat(expires, &length, cookie->expires, MAX_STR_LEN, 0);
353 length = 0;
354 ulongcat(secure, &length, cookie->secure, MAX_STR_LEN, 0);
356 dlg_server = cookie->server->host;
357 dlg_server = straconcat(_("Server", term), ": ", dlg_server, "\n",
358 (unsigned char *) NULL);
360 if (!dlg_server) {
361 mem_free(dlg);
362 return;
365 add_dlg_text(dlg, dlg_server, ALIGN_LEFT, 0);
366 add_dlg_field_float(dlg, _("Name", term), 0, 0, set_cookie_name, MAX_STR_LEN, name, NULL);
367 add_dlg_field_float(dlg, _("Value", term), 0, 0, set_cookie_value, MAX_STR_LEN, value, NULL);
368 add_dlg_field_float(dlg, _("Domain", term), 0, 0, set_cookie_domain, MAX_STR_LEN, domain, NULL);
369 add_dlg_field_float(dlg, _("Expires", term), 0, 0, set_cookie_expires, MAX_STR_LEN, expires, NULL);
370 add_dlg_field_float(dlg, _("Secure", term), 0, 0, set_cookie_secure, MAX_STR_LEN, secure, NULL);
372 add_dlg_button(dlg, _("~OK", term), B_ENTER, ok_dialog, NULL);
373 add_dlg_button(dlg, _("~Cancel", term), B_ESC, cancel_dialog, NULL);
375 add_dlg_end(dlg, EDIT_WIDGETS_COUNT);
377 do_dialog(term, dlg, getml(dlg, (void *) dlg_server, (void *) NULL));
378 #undef EDIT_WIDGETS_COUNT
381 static widget_handler_status_T
382 push_edit_button(struct dialog_data *dlg_data, struct widget_data *button)
384 struct listbox_data *box = get_dlg_listbox_data(dlg_data);
385 struct terminal *term = dlg_data->win->term;
386 struct cookie *cookie;
388 if (!box->sel) return EVENT_PROCESSED;
389 if (box->sel->type == BI_FOLDER) return EVENT_PROCESSED;
390 cookie = box->sel->udata;
391 if (!cookie) return EVENT_PROCESSED;
392 build_edit_dialog(term, cookie);
393 return EVENT_PROCESSED;
396 static widget_handler_status_T
397 push_add_button(struct dialog_data *dlg_data, struct widget_data *button)
399 struct listbox_data *box = get_dlg_listbox_data(dlg_data);
400 struct terminal *term = dlg_data->win->term;
401 struct cookie *new_cookie;
402 struct cookie_server *server;
404 if (!box->sel || !box->sel->udata) return EVENT_PROCESSED;
406 if (box->sel->type == BI_FOLDER) {
407 assert(box->sel->depth == 0);
408 server = box->sel->udata;
409 } else {
410 struct cookie *cookie = box->sel->udata;
412 server = cookie->server;
415 object_lock(server); /* ref consumed by init_cookie */
417 new_cookie = init_cookie(stracpy("") /* name */,
418 stracpy("") /* value */,
419 stracpy("/") /* path */,
420 stracpy(server->host) /* domain */,
421 server);
422 if (!new_cookie) return EVENT_PROCESSED;
424 accept_cookie(new_cookie);
425 build_edit_dialog(term, new_cookie);
426 return EVENT_PROCESSED;
429 /* Called by ok_dialog for the "OK" button in the "Add Server" dialog.
430 * The data parameter points to the buffer used by the server name
431 * widget. */
432 static void
433 add_server_do(void *data)
435 unsigned char *value = data;
436 struct cookie *dummy_cookie;
438 if (!value) return;
440 dummy_cookie = init_cookie(stracpy("empty") /* name */,
441 stracpy("1") /* value */,
442 stracpy("/") /* path */,
443 stracpy(value) /* domain */,
444 get_cookie_server(value, strlen(value)));
445 if (!dummy_cookie) return;
447 accept_cookie(dummy_cookie);
450 static widget_handler_status_T
451 push_add_server_button(struct dialog_data *dlg_data, struct widget_data *button)
453 /* [gettext_accelerator_context(.push_add_server_button)] */
454 #define SERVER_WIDGETS_COUNT 3
455 struct terminal *term = dlg_data->win->term;
456 struct dialog *dlg;
457 unsigned char *name;
458 unsigned char *text;
460 dlg = calloc_dialog(SERVER_WIDGETS_COUNT, MAX_STR_LEN);
461 if (!dlg) return EVENT_NOT_PROCESSED;
463 name = get_dialog_offset(dlg, SERVER_WIDGETS_COUNT);
464 dlg->title = _("Add server", term);
465 dlg->layouter = generic_dialog_layouter;
466 dlg->udata = NULL;
467 dlg->udata2 = NULL;
468 text = _("Server name", term);
469 add_dlg_field_float(dlg, text, 0, 0, check_nonempty, MAX_STR_LEN, name, NULL);
470 add_dlg_ok_button(dlg, _("~OK", term), B_ENTER, add_server_do, name);
471 add_dlg_button(dlg, _("~Cancel", term), B_ESC, cancel_dialog, NULL);
472 add_dlg_end(dlg, SERVER_WIDGETS_COUNT);
473 do_dialog(term, dlg, getml(dlg, (void *) NULL));
475 return EVENT_PROCESSED;
476 #undef SERVER_WIDGETS_COUNT
480 static widget_handler_status_T
481 push_save_button(struct dialog_data *dlg_data, struct widget_data *button)
483 save_cookies(dlg_data->win->term);
484 return EVENT_PROCESSED;
487 static const struct hierbox_browser_button cookie_buttons[] = {
488 /* [gettext_accelerator_context(.cookie_buttons)] */
489 { N_("~Info"), push_hierbox_info_button, 1 },
490 { N_("~Add"), push_add_button, 1 },
491 { N_("Add ~server"), push_add_server_button, 1 },
492 { N_("~Edit"), push_edit_button, 1 },
493 { N_("~Delete"), push_hierbox_delete_button, 1 },
494 { N_("C~lear"), push_hierbox_clear_button, 1 },
495 { N_("Sa~ve"), push_save_button, 0 },
498 struct_hierbox_browser(
499 cookie_browser,
500 N_("Cookie manager"),
501 cookie_buttons,
502 &cookies_listbox_ops
505 void
506 cookie_manager(struct session *ses)
508 hierbox_browser(&cookie_browser, ses);