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.
20 int enable_plugin_whitelist
= 0;
21 int enable_cookie_whitelist
= 0;
22 int enable_js_whitelist
= 0;
24 RB_HEAD(domain_list
, domain
);
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
;
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
;
52 enable_cookie_whitelist
= 1;
53 enable_plugin_whitelist
= 1;
55 read_only_cookies
= 0;
56 save_rejected_cookies
= 0;
57 session_timeout
= 3600;
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
;
66 enable_cookie_whitelist
= 0;
67 enable_plugin_whitelist
= 0;
69 read_only_cookies
= 0;
70 save_rejected_cookies
= 0;
71 session_timeout
= 3600;
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
;
80 enable_cookie_whitelist
= 0;
81 enable_plugin_whitelist
= 0;
83 read_only_cookies
= 0;
84 save_rejected_cookies
= 0;
85 session_timeout
= 3600;
87 enable_js_whitelist
= 0;
88 enable_localstorage
= 1;
98 get_browser_mode(struct settings
*s
)
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");
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
;
130 get_cookie_policy(struct settings
*s
)
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");
147 get_default_script(struct settings
*s
)
149 if (default_script
[0] == '\0')
151 return (g_strdup(default_script
));
155 set_default_script(struct settings
*s
, char *val
)
158 snprintf(default_script
, sizeof default_script
, "%s/%s",
159 pwd
->pw_dir
, &val
[1]);
161 strlcpy(default_script
, val
, sizeof default_script
);
168 wl_add(char *str
, struct domain_list
*wl
, int handy
)
174 if (str
== NULL
|| wl
== NULL
|| strlen(str
) < 2)
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] == '.')
182 else if (str
[0] == '.')
187 /* slice off port number */
188 p
= g_strrstr(str
, ":");
192 d
= g_malloc(sizeof *d
);
194 d
->d
= g_strdup_printf(".%s", str
);
196 d
->d
= g_strdup(str
);
199 if (RB_INSERT(domain_list
, wl
, d
))
202 DNPRINTF(XT_D_COOKIE
, "wl_add: %s\n", d
->d
);
213 add_cookie_wl(struct settings
*s
, char *entry
)
215 wl_add(entry
, &c_wl
, 1);
220 walk_cookie_wl(struct settings
*s
,
221 void (*cb
)(struct settings
*, char *, void *), void *cb_args
)
225 if (s
== NULL
|| cb
== NULL
) {
226 show_oops(NULL
, "walk_cookie_wl invalid parameters");
230 RB_FOREACH_REVERSE(d
, domain_list
, &c_wl
)
231 cb(s
, d
->d
, cb_args
);
235 walk_js_wl(struct settings
*s
,
236 void (*cb
)(struct settings
*, char *, void *), void *cb_args
)
240 if (s
== NULL
|| cb
== NULL
) {
241 show_oops(NULL
, "walk_js_wl invalid parameters");
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 */);
257 walk_pl_wl(struct settings
*s
,
258 void (*cb
)(struct settings
*, char *, void *), void *cb_args
)
262 if (s
== NULL
|| cb
== NULL
) {
263 show_oops(NULL
, "walk_pl_wl invalid parameters");
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 */);
279 wl_find(const gchar
*search
, struct domain_list
*wl
)
282 struct domain
*d
= NULL
, dfind
;
285 if (search
== NULL
|| wl
== NULL
)
287 if (strlen(search
) < 2)
290 if (search
[0] != '.')
291 s
= g_strdup_printf(".%s", search
);
293 s
= g_strdup(search
);
295 for (i
= strlen(s
) - 1; i
>= 0; i
--) {
298 d
= RB_FIND(domain_list
, wl
, &dfind
);
312 wl_find_uri(const gchar
*s
, struct domain_list
*wl
)
318 if (s
== NULL
|| wl
== 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://")];
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') {
343 toggle_cwl(struct tab
*t
, struct karg
*args
)
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");
361 d
= wl_find(dom
, &c_wl
);
368 if (args
->i
& XT_WL_TOGGLE
)
370 else if ((args
->i
& XT_WL_ENABLE
) && es
!= 1)
372 else if ((args
->i
& XT_WL_DISABLE
) && es
!= 0)
376 /* enable cookies for domain */
377 wl_add(dom
, &c_wl
, 0);
379 /* disable cookies for domain */
381 RB_REMOVE(domain_list
, &c_wl
, d
);
384 if (args
->i
& XT_WL_RELOAD
)
385 webkit_web_view_reload(t
->wv
);
393 toggle_js(struct tab
*t
, struct karg
*args
)
403 g_object_get(G_OBJECT(t
->settings
),
404 "enable-scripts", &es
, (char *)NULL
);
405 if (args
->i
& XT_WL_TOGGLE
)
407 else if ((args
->i
& XT_WL_ENABLE
) && es
!= 1)
409 else if ((args
->i
& XT_WL_DISABLE
) && es
!= 0)
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");
424 button_set_stockid(t
->js_toggle
, GTK_STOCK_MEDIA_PLAY
);
425 wl_add(dom
, &js_wl
, 0 /* session */);
427 d
= wl_find(dom
, &js_wl
);
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
);
447 js_toggle_cb(GtkWidget
*w
, struct tab
*t
)
452 g_object_get(G_OBJECT(t
->settings
),
453 "enable-scripts", &es
, (char *)NULL
);
460 a
.i
= set
| XT_WL_TOPLEVEL
;
463 a
.i
= set
| XT_WL_TOPLEVEL
;
466 a
.i
= XT_WL_TOGGLE
| XT_WL_TOPLEVEL
| XT_WL_RELOAD
;
471 wl_show(struct tab
*t
, struct karg
*args
, char *title
, struct domain_list
*wl
)
479 if (args
->i
& XT_WL_PERSISTENT
) {
481 body
= g_strdup_printf("%s<h2>Persistent</h2>", body
);
483 RB_FOREACH(d
, domain_list
, wl
) {
487 body
= g_strdup_printf("%s%s<br/>", body
, d
->d
);
493 if (args
->i
& XT_WL_SESSION
) {
495 body
= g_strdup_printf("%s<h2>Session</h2>", body
);
497 RB_FOREACH(d
, domain_list
, wl
) {
501 body
= g_strdup_printf("%s%s<br/>", body
, d
->d
);
506 tmp
= get_html_page(title
, body
, "", 0);
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
);
513 load_webkit_string(t
, tmp
, XT_URI_ABOUT_PLUGINWL
);
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
;
527 char *line
= NULL
, *lt
= NULL
, *dom
= NULL
;
535 if (t
== NULL
|| args
== NULL
)
538 if (runtime_settings
[0] == '\0')
541 snprintf(file
, sizeof file
, "%s/%s", work_dir
, runtime_settings
);
542 if ((f
= fopen(file
, "r+")) == NULL
)
546 case XT_WL_JAVASCRIPT
:
547 lst_str
= "JavaScript";
548 lt
= g_strdup_printf("js_wl=%s", dom
);
552 lt
= g_strdup_printf("cookie_wl=%s", dom
);
556 lt
= g_strdup_printf("pl_wl=%s", dom
);
559 show_oops(t
, "Invalid list id: %d", list
);
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
);
572 line
= fparseln(f
, &linelen
, NULL
, NULL
, 0);
575 if (!strcmp(line
, lt
))
581 fprintf(f
, "%s\n", lt
);
586 case XT_WL_JAVASCRIPT
:
587 d
= wl_find(dom
, &js_wl
);
589 settings_add("js_wl", dom
);
590 d
= wl_find(dom
, &js_wl
);
596 d
= wl_find(dom
, &c_wl
);
598 settings_add("cookie_wl", dom
);
599 d
= wl_find(dom
, &c_wl
);
603 /* find and add to persistent jar */
604 cf
= soup_cookie_jar_all_cookies(s_cookiejar
);
605 for (;cf
; cf
= cf
->next
) {
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
);
617 d
= wl_find(dom
, &pl_wl
);
619 settings_add("pl_wl", dom
);
620 d
= wl_find(dom
, &pl_wl
);
625 abort(); /* can't happen */
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
);
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
);
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
;
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");
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
;
688 } else if (args
->i
& XT_DELETE
)
689 show_oops(t
, "'js delete' currently unimplemented");
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
);
704 toggle_pl(struct tab
*t
, struct karg
*args
)
714 g_object_get(G_OBJECT(t
->settings
),
715 "enable-plugins", &es
, (char *)NULL
);
716 if (args
->i
& XT_WL_TOGGLE
)
718 else if ((args
->i
& XT_WL_ENABLE
) && es
!= 1)
720 else if ((args
->i
& XT_WL_DISABLE
) && es
!= 0)
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");
735 wl_add(dom
, &pl_wl
, 0 /* session */);
737 d
= wl_find(dom
, &pl_wl
);
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
);
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
;
764 } else if (args
->i
& XT_DELETE
)
765 show_oops(t
, "'plugin delete' currently unimplemented");
771 toplevel_cmd(struct tab
*t
, struct karg
*args
)
773 js_toggle_cb(t
->js_toggle
, t
);