move some xtp functions over, RB_* prevented all
[xombrero.git] / whitelist.c
blobf6fe18bacaef103a9d1cf51285741b0f682026b3
1 /*
2 * Copyright (c) 2011 Conformal Systems LLC <info@conformal.com>
3 * Copyright (c) 2011 Marco Peereboom <marco@peereboom.us>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include "xxxterm.h"
20 int enable_plugin_whitelist = 0;
21 int enable_cookie_whitelist = 0;
22 int enable_js_whitelist = 0;
24 RB_HEAD(domain_list, domain);
26 int
27 domain_rb_cmp(struct domain *d1, struct domain *d2)
29 return (strcmp(d1->d, d2->d));
31 RB_GENERATE(domain_list, domain, entry, domain_rb_cmp);
33 struct domain_list c_wl;
34 struct domain_list js_wl;
35 struct domain_list pl_wl;
37 void
38 wl_init(void)
40 RB_INIT(&js_wl);
41 RB_INIT(&pl_wl);
44 int
45 set_browser_mode(struct settings *s, char *val)
47 if (!strcmp(val, "whitelist")) {
48 browser_mode = XT_BM_WHITELIST;
49 allow_volatile_cookies = 0;
50 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY;
51 cookies_enabled = 1;
52 enable_cookie_whitelist = 1;
53 enable_plugin_whitelist = 1;
54 enable_plugins = 0;
55 read_only_cookies = 0;
56 save_rejected_cookies = 0;
57 session_timeout = 3600;
58 enable_scripts = 0;
59 enable_js_whitelist = 1;
60 enable_localstorage = 0;
61 } else if (!strcmp(val, "normal")) {
62 browser_mode = XT_BM_NORMAL;
63 allow_volatile_cookies = 0;
64 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_ALWAYS;
65 cookies_enabled = 1;
66 enable_cookie_whitelist = 0;
67 enable_plugin_whitelist = 0;
68 enable_plugins = 1;
69 read_only_cookies = 0;
70 save_rejected_cookies = 0;
71 session_timeout = 3600;
72 enable_scripts = 1;
73 enable_js_whitelist = 0;
74 enable_localstorage = 1;
75 } else if (!strcmp(val, "kiosk")) {
76 browser_mode = XT_BM_KIOSK;
77 allow_volatile_cookies = 0;
78 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_ALWAYS;
79 cookies_enabled = 1;
80 enable_cookie_whitelist = 0;
81 enable_plugin_whitelist = 0;
82 enable_plugins = 1;
83 read_only_cookies = 0;
84 save_rejected_cookies = 0;
85 session_timeout = 3600;
86 enable_scripts = 1;
87 enable_js_whitelist = 0;
88 enable_localstorage = 1;
89 show_tabs = 0;
90 tabless = 1;
91 } else
92 return (1);
94 return (0);
97 char *
98 get_browser_mode(struct settings *s)
100 char *r = NULL;
102 if (browser_mode == XT_BM_WHITELIST)
103 r = g_strdup("whitelist");
104 else if (browser_mode == XT_BM_NORMAL)
105 r = g_strdup("normal");
106 else if (browser_mode == XT_BM_KIOSK)
107 r = g_strdup("kiosk");
108 else
109 return (NULL);
111 return (r);
115 set_cookie_policy(struct settings *s, char *val)
117 if (!strcmp(val, "no3rdparty"))
118 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY;
119 else if (!strcmp(val, "accept"))
120 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_ALWAYS;
121 else if (!strcmp(val, "reject"))
122 cookie_policy = SOUP_COOKIE_JAR_ACCEPT_NEVER;
123 else
124 return (1);
126 return (0);
129 char *
130 get_cookie_policy(struct settings *s)
132 char *r = NULL;
134 if (cookie_policy == SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY)
135 r = g_strdup("no3rdparty");
136 else if (cookie_policy == SOUP_COOKIE_JAR_ACCEPT_ALWAYS)
137 r = g_strdup("accept");
138 else if (cookie_policy == SOUP_COOKIE_JAR_ACCEPT_NEVER)
139 r = g_strdup("reject");
140 else
141 return (NULL);
143 return (r);
146 char *
147 get_default_script(struct settings *s)
149 if (default_script[0] == '\0')
150 return (0);
151 return (g_strdup(default_script));
155 set_default_script(struct settings *s, char *val)
157 if (val[0] == '~')
158 snprintf(default_script, sizeof default_script, "%s/%s",
159 pwd->pw_dir, &val[1]);
160 else
161 strlcpy(default_script, val, sizeof default_script);
163 return (0);
167 void
168 wl_add(char *str, struct domain_list *wl, int handy)
170 struct domain *d;
171 int add_dot = 0;
172 char *p;
174 if (str == NULL || wl == NULL || strlen(str) < 2)
175 return;
177 DNPRINTF(XT_D_COOKIE, "wl_add in: %s\n", str);
179 /* treat *.moo.com the same as .moo.com */
180 if (str[0] == '*' && str[1] == '.')
181 str = &str[1];
182 else if (str[0] == '.')
183 str = &str[0];
184 else
185 add_dot = 1;
187 /* slice off port number */
188 p = g_strrstr(str, ":");
189 if (p)
190 *p = '\0';
192 d = g_malloc(sizeof *d);
193 if (add_dot)
194 d->d = g_strdup_printf(".%s", str);
195 else
196 d->d = g_strdup(str);
197 d->handy = handy;
199 if (RB_INSERT(domain_list, wl, d))
200 goto unwind;
202 DNPRINTF(XT_D_COOKIE, "wl_add: %s\n", d->d);
203 return;
204 unwind:
205 if (d) {
206 if (d->d)
207 g_free(d->d);
208 g_free(d);
213 add_cookie_wl(struct settings *s, char *entry)
215 wl_add(entry, &c_wl, 1);
216 return (0);
219 void
220 walk_cookie_wl(struct settings *s,
221 void (*cb)(struct settings *, char *, void *), void *cb_args)
223 struct domain *d;
225 if (s == NULL || cb == NULL) {
226 show_oops(NULL, "walk_cookie_wl invalid parameters");
227 return;
230 RB_FOREACH_REVERSE(d, domain_list, &c_wl)
231 cb(s, d->d, cb_args);
234 void
235 walk_js_wl(struct settings *s,
236 void (*cb)(struct settings *, char *, void *), void *cb_args)
238 struct domain *d;
240 if (s == NULL || cb == NULL) {
241 show_oops(NULL, "walk_js_wl invalid parameters");
242 return;
245 RB_FOREACH_REVERSE(d, domain_list, &js_wl)
246 cb(s, d->d, cb_args);
250 add_js_wl(struct settings *s, char *entry)
252 wl_add(entry, &js_wl, 1 /* persistent */);
253 return (0);
256 void
257 walk_pl_wl(struct settings *s,
258 void (*cb)(struct settings *, char *, void *), void *cb_args)
260 struct domain *d;
262 if (s == NULL || cb == NULL) {
263 show_oops(NULL, "walk_pl_wl invalid parameters");
264 return;
267 RB_FOREACH_REVERSE(d, domain_list, &pl_wl)
268 cb(s, d->d, cb_args);
272 add_pl_wl(struct settings *s, char *entry)
274 wl_add(entry, &pl_wl, 1 /* persistent */);
275 return (0);
278 struct domain *
279 wl_find(const gchar *search, struct domain_list *wl)
281 int i;
282 struct domain *d = NULL, dfind;
283 gchar *s = NULL;
285 if (search == NULL || wl == NULL)
286 return (NULL);
287 if (strlen(search) < 2)
288 return (NULL);
290 if (search[0] != '.')
291 s = g_strdup_printf(".%s", search);
292 else
293 s = g_strdup(search);
295 for (i = strlen(s) - 1; i >= 0; i--) {
296 if (s[i] == '.') {
297 dfind.d = &s[i];
298 d = RB_FIND(domain_list, wl, &dfind);
299 if (d)
300 goto done;
304 done:
305 if (s)
306 g_free(s);
308 return (d);
311 struct domain *
312 wl_find_uri(const gchar *s, struct domain_list *wl)
314 int i;
315 char *ss;
316 struct domain *r;
318 if (s == NULL || wl == NULL)
319 return (NULL);
321 if (!strncmp(s, "http://", strlen("http://")))
322 s = &s[strlen("http://")];
323 else if (!strncmp(s, "https://", strlen("https://")))
324 s = &s[strlen("https://")];
326 if (strlen(s) < 2)
327 return (NULL);
329 for (i = 0; i < strlen(s) + 1 /* yes er need this */; i++)
330 /* chop string at first slash */
331 if (s[i] == '/' || s[i] == ':' || s[i] == '\0') {
332 ss = g_strdup(s);
333 ss[i] = '\0';
334 r = wl_find(ss, wl);
335 g_free(ss);
336 return (r);
339 return (NULL);
343 toggle_cwl(struct tab *t, struct karg *args)
345 struct domain *d;
346 const gchar *uri;
347 char *dom = NULL;
348 int es;
350 if (args == NULL)
351 return (1);
353 uri = get_uri(t);
354 dom = find_domain(uri, args->i & XT_WL_TOPLEVEL);
356 if (uri == NULL || dom == NULL ||
357 webkit_web_view_get_load_status(t->wv) == WEBKIT_LOAD_FAILED) {
358 show_oops(t, "Can't toggle domain in cookie white list");
359 goto done;
361 d = wl_find(dom, &c_wl);
363 if (d == NULL)
364 es = 0;
365 else
366 es = 1;
368 if (args->i & XT_WL_TOGGLE)
369 es = !es;
370 else if ((args->i & XT_WL_ENABLE) && es != 1)
371 es = 1;
372 else if ((args->i & XT_WL_DISABLE) && es != 0)
373 es = 0;
375 if (es)
376 /* enable cookies for domain */
377 wl_add(dom, &c_wl, 0);
378 else {
379 /* disable cookies for domain */
380 if (d)
381 RB_REMOVE(domain_list, &c_wl, d);
384 if (args->i & XT_WL_RELOAD)
385 webkit_web_view_reload(t->wv);
387 done:
388 g_free(dom);
389 return (0);
393 toggle_js(struct tab *t, struct karg *args)
395 int es;
396 const gchar *uri;
397 struct domain *d;
398 char *dom = NULL;
400 if (args == NULL)
401 return (1);
403 g_object_get(G_OBJECT(t->settings),
404 "enable-scripts", &es, (char *)NULL);
405 if (args->i & XT_WL_TOGGLE)
406 es = !es;
407 else if ((args->i & XT_WL_ENABLE) && es != 1)
408 es = 1;
409 else if ((args->i & XT_WL_DISABLE) && es != 0)
410 es = 0;
411 else
412 return (1);
414 uri = get_uri(t);
415 dom = find_domain(uri, args->i & XT_WL_TOPLEVEL);
417 if (uri == NULL || dom == NULL ||
418 webkit_web_view_get_load_status(t->wv) == WEBKIT_LOAD_FAILED) {
419 show_oops(t, "Can't toggle domain in JavaScript white list");
420 goto done;
423 if (es) {
424 button_set_stockid(t->js_toggle, GTK_STOCK_MEDIA_PLAY);
425 wl_add(dom, &js_wl, 0 /* session */);
426 } else {
427 d = wl_find(dom, &js_wl);
428 if (d)
429 RB_REMOVE(domain_list, &js_wl, d);
430 button_set_stockid(t->js_toggle, GTK_STOCK_MEDIA_PAUSE);
432 g_object_set(G_OBJECT(t->settings),
433 "enable-scripts", es, (char *)NULL);
434 g_object_set(G_OBJECT(t->settings),
435 "javascript-can-open-windows-automatically", es, (char *)NULL);
436 webkit_web_view_set_settings(t->wv, t->settings);
438 if (args->i & XT_WL_RELOAD)
439 webkit_web_view_reload(t->wv);
440 done:
441 if (dom)
442 g_free(dom);
443 return (0);
446 void
447 js_toggle_cb(GtkWidget *w, struct tab *t)
449 struct karg a;
450 int es, set;
452 g_object_get(G_OBJECT(t->settings),
453 "enable-scripts", &es, (char *)NULL);
454 es = !es;
455 if (es)
456 set = XT_WL_ENABLE;
457 else
458 set = XT_WL_DISABLE;
460 a.i = set | XT_WL_TOPLEVEL;
461 toggle_pl(t, &a);
463 a.i = set | XT_WL_TOPLEVEL;
464 toggle_cwl(t, &a);
466 a.i = XT_WL_TOGGLE | XT_WL_TOPLEVEL | XT_WL_RELOAD;
467 toggle_js(t, &a);
471 wl_show(struct tab *t, struct karg *args, char *title, struct domain_list *wl)
473 struct domain *d;
474 char *tmp, *body;
476 body = g_strdup("");
478 /* p list */
479 if (args->i & XT_WL_PERSISTENT) {
480 tmp = body;
481 body = g_strdup_printf("%s<h2>Persistent</h2>", body);
482 g_free(tmp);
483 RB_FOREACH(d, domain_list, wl) {
484 if (d->handy == 0)
485 continue;
486 tmp = body;
487 body = g_strdup_printf("%s%s<br/>", body, d->d);
488 g_free(tmp);
492 /* s list */
493 if (args->i & XT_WL_SESSION) {
494 tmp = body;
495 body = g_strdup_printf("%s<h2>Session</h2>", body);
496 g_free(tmp);
497 RB_FOREACH(d, domain_list, wl) {
498 if (d->handy == 1)
499 continue;
500 tmp = body;
501 body = g_strdup_printf("%s%s<br/>", body, d->d);
502 g_free(tmp);
506 tmp = get_html_page(title, body, "", 0);
507 g_free(body);
508 if (wl == &js_wl)
509 load_webkit_string(t, tmp, XT_URI_ABOUT_JSWL);
510 else if (wl == &c_wl)
511 load_webkit_string(t, tmp, XT_URI_ABOUT_COOKIEWL);
512 else
513 load_webkit_string(t, tmp, XT_URI_ABOUT_PLUGINWL);
514 g_free(tmp);
515 return (0);
518 #define XT_WL_INVALID (0)
519 #define XT_WL_JAVASCRIPT (1)
520 #define XT_WL_COOKIE (2)
521 #define XT_WL_PLUGIN (3)
523 wl_save(struct tab *t, struct karg *args, int list)
525 char file[PATH_MAX], *lst_str = NULL;
526 FILE *f;
527 char *line = NULL, *lt = NULL, *dom = NULL;
528 size_t linelen;
529 const gchar *uri;
530 struct karg a;
531 struct domain *d;
532 GSList *cf;
533 SoupCookie *ci, *c;
535 if (t == NULL || args == NULL)
536 return (1);
538 if (runtime_settings[0] == '\0')
539 return (1);
541 snprintf(file, sizeof file, "%s/%s", work_dir, runtime_settings);
542 if ((f = fopen(file, "r+")) == NULL)
543 return (1);
545 switch (list) {
546 case XT_WL_JAVASCRIPT:
547 lst_str = "JavaScript";
548 lt = g_strdup_printf("js_wl=%s", dom);
549 break;
550 case XT_WL_COOKIE:
551 lst_str = "Cookie";
552 lt = g_strdup_printf("cookie_wl=%s", dom);
553 break;
554 case XT_WL_PLUGIN:
555 lst_str = "Plugin";
556 lt = g_strdup_printf("pl_wl=%s", dom);
557 break;
558 default:
559 show_oops(t, "Invalid list id: %d", list);
560 return (1);
563 uri = get_uri(t);
564 dom = find_domain(uri, args->i & XT_WL_TOPLEVEL);
565 if (uri == NULL || dom == NULL ||
566 webkit_web_view_get_load_status(t->wv) == WEBKIT_LOAD_FAILED) {
567 show_oops(t, "Can't add domain to %s white list", lst_str);
568 goto done;
571 while (!feof(f)) {
572 line = fparseln(f, &linelen, NULL, NULL, 0);
573 if (line == NULL)
574 continue;
575 if (!strcmp(line, lt))
576 goto done;
577 free(line);
578 line = NULL;
581 fprintf(f, "%s\n", lt);
583 a.i = XT_WL_ENABLE;
584 a.i |= args->i;
585 switch (list) {
586 case XT_WL_JAVASCRIPT:
587 d = wl_find(dom, &js_wl);
588 if (!d) {
589 settings_add("js_wl", dom);
590 d = wl_find(dom, &js_wl);
592 toggle_js(t, &a);
593 break;
595 case XT_WL_COOKIE:
596 d = wl_find(dom, &c_wl);
597 if (!d) {
598 settings_add("cookie_wl", dom);
599 d = wl_find(dom, &c_wl);
601 toggle_cwl(t, &a);
603 /* find and add to persistent jar */
604 cf = soup_cookie_jar_all_cookies(s_cookiejar);
605 for (;cf; cf = cf->next) {
606 ci = cf->data;
607 if (!strcmp(dom, ci->domain) ||
608 !strcmp(&dom[1], ci->domain)) /* deal with leading . */ {
609 c = soup_cookie_copy(ci);
610 _soup_cookie_jar_add_cookie(p_cookiejar, c);
613 soup_cookies_free(cf);
614 break;
616 case XT_WL_PLUGIN:
617 d = wl_find(dom, &pl_wl);
618 if (!d) {
619 settings_add("pl_wl", dom);
620 d = wl_find(dom, &pl_wl);
622 toggle_pl(t, &a);
623 break;
624 default:
625 abort(); /* can't happen */
627 if (d)
628 d->handy = 1;
630 done:
631 if (line)
632 free(line);
633 if (dom)
634 g_free(dom);
635 if (lt)
636 g_free(lt);
637 fclose(f);
639 return (0);
643 js_show_wl(struct tab *t, struct karg *args)
645 args->i = XT_SHOW | XT_WL_PERSISTENT | XT_WL_SESSION;
646 wl_show(t, args, "JavaScript White List", &js_wl);
648 return (0);
652 cookie_show_wl(struct tab *t, struct karg *args)
654 args->i = XT_SHOW | XT_WL_PERSISTENT | XT_WL_SESSION;
655 wl_show(t, args, "Cookie White List", &c_wl);
657 return (0);
661 cookie_cmd(struct tab *t, struct karg *args)
663 if (args->i & XT_SHOW)
664 wl_show(t, args, "Cookie White List", &c_wl);
665 else if (args->i & XT_WL_TOGGLE) {
666 args->i |= XT_WL_RELOAD;
667 toggle_cwl(t, args);
668 } else if (args->i & XT_SAVE) {
669 args->i |= XT_WL_RELOAD;
670 wl_save(t, args, XT_WL_COOKIE);
671 } else if (args->i & XT_DELETE)
672 show_oops(t, "'cookie delete' currently unimplemented");
674 return (0);
678 js_cmd(struct tab *t, struct karg *args)
680 if (args->i & XT_SHOW)
681 wl_show(t, args, "JavaScript White List", &js_wl);
682 else if (args->i & XT_SAVE) {
683 args->i |= XT_WL_RELOAD;
684 wl_save(t, args, XT_WL_JAVASCRIPT);
685 } else if (args->i & XT_WL_TOGGLE) {
686 args->i |= XT_WL_RELOAD;
687 toggle_js(t, args);
688 } else if (args->i & XT_DELETE)
689 show_oops(t, "'js delete' currently unimplemented");
691 return (0);
695 pl_show_wl(struct tab *t, struct karg *args)
697 args->i = XT_SHOW | XT_WL_PERSISTENT | XT_WL_SESSION;
698 wl_show(t, args, "Plugin White List", &pl_wl);
700 return (0);
704 toggle_pl(struct tab *t, struct karg *args)
706 int es;
707 const gchar *uri;
708 struct domain *d;
709 char *dom = NULL;
711 if (args == NULL)
712 return (1);
714 g_object_get(G_OBJECT(t->settings),
715 "enable-plugins", &es, (char *)NULL);
716 if (args->i & XT_WL_TOGGLE)
717 es = !es;
718 else if ((args->i & XT_WL_ENABLE) && es != 1)
719 es = 1;
720 else if ((args->i & XT_WL_DISABLE) && es != 0)
721 es = 0;
722 else
723 return (1);
725 uri = get_uri(t);
726 dom = find_domain(uri, args->i & XT_WL_TOPLEVEL);
728 if (uri == NULL || dom == NULL ||
729 webkit_web_view_get_load_status(t->wv) == WEBKIT_LOAD_FAILED) {
730 show_oops(t, "Can't toggle domain in plugins white list");
731 goto done;
734 if (es)
735 wl_add(dom, &pl_wl, 0 /* session */);
736 else {
737 d = wl_find(dom, &pl_wl);
738 if (d)
739 RB_REMOVE(domain_list, &pl_wl, d);
741 g_object_set(G_OBJECT(t->settings),
742 "enable-plugins", es, (char *)NULL);
743 webkit_web_view_set_settings(t->wv, t->settings);
745 if (args->i & XT_WL_RELOAD)
746 webkit_web_view_reload(t->wv);
747 done:
748 if (dom)
749 g_free(dom);
750 return (0);
754 pl_cmd(struct tab *t, struct karg *args)
756 if (args->i & XT_SHOW)
757 wl_show(t, args, "Plugin White List", &pl_wl);
758 else if (args->i & XT_SAVE) {
759 args->i |= XT_WL_RELOAD;
760 wl_save(t, args, XT_WL_PLUGIN);
761 } else if (args->i & XT_WL_TOGGLE) {
762 args->i |= XT_WL_RELOAD;
763 toggle_pl(t, args);
764 } else if (args->i & XT_DELETE)
765 show_oops(t, "'plugin delete' currently unimplemented");
767 return (0);
771 toplevel_cmd(struct tab *t, struct karg *args)
773 js_toggle_cb(t->js_toggle, t);
775 return (0);