Initialize cookie whitelist. Fixes FS388.
[xombrero.git] / whitelist.c
blob47ca9d7400e4a4265e7bbadf59ff7d052b9dcd4c
1 /*
2 * Copyright (c) 2010, 2011 Marco Peereboom <marco@peereboom.us>
3 * Copyright (c) 2011 Stevan Andjelkovic <stevan@student.chalmers.se>
4 * Copyright (c) 2010, 2011 Edd Barrett <vext01@gmail.com>
5 * Copyright (c) 2011 Todd T. Fries <todd@fries.net>
6 * Copyright (c) 2011 Raphael Graf <r@undefined.ch>
7 * Copyright (c) 2011 Michal Mazurek <akfaew@jasminek.net>
8 * Copyright (c) 2012 Josh Rickmar <jrick@devio.us>
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 #include <xombrero.h>
25 gchar *
26 find_domain(const gchar *s, int flags)
28 SoupURI *uri;
29 gchar *ret, *p;
31 if (s == NULL)
32 return (NULL);
34 uri = soup_uri_new(s);
36 if (uri == NULL || !SOUP_URI_VALID_FOR_HTTP(uri))
37 return (NULL);
39 if (flags & XT_WL_TOPLEVEL &&
40 !isdigit(uri->host[strlen(uri->host) - 1]))
41 p = tld_get_suffix(uri->host);
42 else
43 p = uri->host;
45 if (flags & XT_WL_TOPLEVEL)
46 ret = g_strdup_printf(".%s", p);
47 else /* assume FQDN */
48 ret = g_strdup(p);
50 soup_uri_free(uri);
52 return (ret);
55 struct wl_entry *
56 wl_find(const gchar *s, struct wl_list *wl)
58 struct wl_entry *w;
60 if (s == NULL || strlen(s) == 0 || wl == NULL)
61 return (NULL);
63 TAILQ_FOREACH(w, wl, entry) {
64 if (w->re == NULL)
65 continue;
66 if (!regexec(w->re, s, 0, 0, 0))
67 return (w);
70 return (NULL);
73 int
74 wl_save(struct tab *t, struct karg *args, int list)
76 char file[PATH_MAX], *lst_str = NULL;
77 FILE *f = NULL;
78 char *line = NULL, *lt = NULL, *dom;
79 size_t linelen;
80 const gchar *uri;
81 struct karg a;
82 struct wl_entry *w;
83 GSList *cf;
84 SoupCookie *ci, *c;
86 if (t == NULL || args == NULL)
87 return (1);
89 if (runtime_settings[0] == '\0')
90 return (1);
92 switch (list) {
93 case XT_WL_JAVASCRIPT:
94 lst_str = "JavaScript";
95 break;
96 case XT_WL_COOKIE:
97 lst_str = "Cookie";
98 break;
99 case XT_WL_PLUGIN:
100 lst_str = "Plugin";
101 break;
102 case XT_WL_HTTPS:
103 lst_str = "HTTPS";
104 break;
105 default:
106 show_oops(t, "Invalid list id: %d", list);
107 return (1);
110 uri = get_uri(t);
111 dom = find_domain(uri, args->i);
112 if (uri == NULL || dom == NULL ||
113 webkit_web_view_get_load_status(t->wv) == WEBKIT_LOAD_FAILED) {
114 show_oops(t, "Can't add domain to %s white list", lst_str);
115 goto done;
118 switch (list) {
119 case XT_WL_JAVASCRIPT:
120 lt = g_strdup_printf("js_wl=%s", dom);
121 break;
122 case XT_WL_COOKIE:
123 lt = g_strdup_printf("cookie_wl=%s", dom);
124 break;
125 case XT_WL_PLUGIN:
126 lt = g_strdup_printf("pl_wl=%s", dom);
127 break;
128 case XT_WL_HTTPS:
129 lt = g_strdup_printf("force_https=%s", dom);
130 break;
131 default:
132 /* can't happen */
133 show_oops(t, "Invalid list id: %d", list);
134 goto done;
137 snprintf(file, sizeof file, "%s" PS "%s", work_dir, runtime_settings);
138 if ((f = fopen(file, "r+")) == NULL) {
139 show_oops(t, "can't open file %s");
140 goto done;
143 while (!feof(f)) {
144 line = fparseln(f, &linelen, NULL, NULL, 0);
145 if (line == NULL)
146 continue;
147 if (!strcmp(line, lt))
148 goto done;
149 free(line);
150 line = NULL;
153 fprintf(f, "%s\n", lt);
155 a.i = XT_WL_ENABLE;
156 a.i |= args->i;
157 switch (list) {
158 case XT_WL_JAVASCRIPT:
159 w = wl_find(dom, &js_wl);
160 if (w == NULL) {
161 settings_add("js_wl", dom);
162 w = wl_find(dom, &js_wl);
164 toggle_js(t, &a);
165 break;
167 case XT_WL_COOKIE:
168 w = wl_find(dom, &c_wl);
169 if (w == NULL) {
170 settings_add("cookie_wl", dom);
171 w = wl_find(dom, &c_wl);
173 toggle_cwl(t, &a);
175 /* find and add to persistent jar */
176 cf = soup_cookie_jar_all_cookies(s_cookiejar);
177 for (;cf; cf = cf->next) {
178 ci = cf->data;
179 if (!strcmp(dom, ci->domain) ||
180 !strcmp(&dom[1], ci->domain)) /* deal with leading . */ {
181 c = soup_cookie_copy(ci);
182 _soup_cookie_jar_add_cookie(p_cookiejar, c);
185 soup_cookies_free(cf);
186 break;
188 case XT_WL_PLUGIN:
189 w = wl_find(dom, &pl_wl);
190 if (w == NULL) {
191 settings_add("pl_wl", dom);
192 w = wl_find(dom, &pl_wl);
194 toggle_pl(t, &a);
195 break;
196 case XT_WL_HTTPS:
197 w = wl_find(dom, &force_https);
198 if (w == NULL) {
199 settings_add("force_https", dom);
200 w = wl_find(dom, &force_https);
202 toggle_force_https(t, &a);
203 break;
204 default:
205 abort(); /* can't happen */
207 if (w != NULL)
208 w->handy = 1;
210 done:
211 if (line)
212 free(line);
213 if (dom)
214 g_free(dom);
215 if (lt)
216 g_free(lt);
217 if (f)
218 fclose(f);
220 return (0);
224 wl_show(struct tab *t, struct karg *args, char *title, struct wl_list *wl)
226 struct wl_entry *w;
227 char *tmp, *body;
229 body = g_strdup("");
231 /* p list */
232 if (args->i & XT_WL_PERSISTENT) {
233 tmp = body;
234 body = g_strdup_printf("%s<h2>Persistent</h2>", body);
235 g_free(tmp);
236 TAILQ_FOREACH(w, wl, entry) {
237 if (w->handy == 0)
238 continue;
239 tmp = body;
240 body = g_strdup_printf("%s%s<br/>", body, w->pat);
241 g_free(tmp);
245 /* s list */
246 if (args->i & XT_WL_SESSION) {
247 tmp = body;
248 body = g_strdup_printf("%s<h2>Session</h2>", body);
249 g_free(tmp);
250 TAILQ_FOREACH(w, wl, entry) {
251 if (w->handy == 1)
252 continue;
253 tmp = body;
254 body = g_strdup_printf("%s%s<br/>", body, w->pat);
255 g_free(tmp);
259 tmp = get_html_page(title, body, "", 0);
260 g_free(body);
261 if (wl == &js_wl)
262 load_webkit_string(t, tmp, XT_URI_ABOUT_JSWL, 0);
263 else if (wl == &c_wl)
264 load_webkit_string(t, tmp, XT_URI_ABOUT_COOKIEWL, 0);
265 else if (wl == &pl_wl)
266 load_webkit_string(t, tmp, XT_URI_ABOUT_PLUGINWL, 0);
267 else if (wl == &force_https)
268 load_webkit_string(t, tmp, XT_URI_ABOUT_HTTPS, 0);
269 g_free(tmp);
270 return (0);
273 void
274 wl_add(const char *str, struct wl_list *wl, int flags)
276 struct wl_entry *w;
277 int add_dot = 0, chopped = 0;
278 const char *s = str;
279 char *escstr, *p, *pat;
280 char **sv;
282 if (str == NULL || wl == NULL || strlen(str) < 2)
283 return;
285 DNPRINTF(XT_D_COOKIE, "wl_add in: %s\n", str);
287 /* slice off port number */
288 p = g_strrstr(str, ":");
289 if (p)
290 *p = '\0';
292 w = g_malloc(sizeof *w);
293 w->re = g_malloc(sizeof *w->re);
294 if (flags & XT_WL_REGEX) {
295 w->pat = g_strdup_printf("re:%s", str);
296 regcomp(w->re, str, REG_EXTENDED | REG_NOSUB);
297 DNPRINTF(XT_D_COOKIE, "wl_add: %s\n", str);
298 } else {
299 /* treat *.moo.com the same as .moo.com */
300 if (s[0] == '*' && s[1] == '.')
301 s = &s[1];
302 else if (s[0] != '.' && (flags & XT_WL_TOPLEVEL))
303 add_dot = 1;
305 if (s[0] == '.') {
306 s = &s[1];
307 chopped = 1;
309 sv = g_strsplit(s, ".", 0);
310 escstr = g_strjoinv("\\.", sv);
311 g_strfreev(sv);
313 if (add_dot) {
314 w->pat = g_strdup_printf(".%s", str);
315 pat = g_strdup_printf("^(.*\\.)*%s$", escstr);
316 regcomp(w->re, pat, REG_EXTENDED | REG_NOSUB);
317 } else {
318 w->pat = g_strdup(str);
319 if (chopped)
320 pat = g_strdup_printf("^(.*\\.)*%s$", escstr);
321 else
322 pat = g_strdup_printf("^%s$", escstr);
323 regcomp(w->re, pat, REG_EXTENDED | REG_NOSUB);
325 DNPRINTF(XT_D_COOKIE, "wl_add: %s\n", pat);
326 g_free(escstr);
327 g_free(pat);
330 w->handy = (flags & XT_WL_PERSISTENT) ? 1 : 0;
332 TAILQ_INSERT_HEAD(wl, w, entry);
334 return;
338 add_cookie_wl(struct settings *s, char *entry)
340 if (g_str_has_prefix(entry, "re:")) {
341 entry = &entry[3];
342 wl_add(entry, &c_wl, XT_WL_PERSISTENT | XT_WL_REGEX);
343 } else
344 wl_add(entry, &c_wl, XT_WL_PERSISTENT);
345 return (0);
349 add_js_wl(struct settings *s, char *entry)
351 if (g_str_has_prefix(entry, "re:")) {
352 entry = &entry[3];
353 wl_add(entry, &js_wl, XT_WL_PERSISTENT | XT_WL_REGEX);
354 } else
355 wl_add(entry, &js_wl, XT_WL_PERSISTENT);
356 return (0);
360 add_pl_wl(struct settings *s, char *entry)
362 if (g_str_has_prefix(entry, "re:")) {
363 entry = &entry[3];
364 wl_add(entry, &pl_wl, XT_WL_PERSISTENT | XT_WL_REGEX);
365 } else
366 wl_add(entry, &pl_wl, XT_WL_PERSISTENT);
367 return (0);
371 toggle_cwl(struct tab *t, struct karg *args)
373 struct wl_entry *w;
374 const gchar *uri;
375 char *dom = NULL;
376 int es;
378 if (args == NULL)
379 return (1);
381 uri = get_uri(t);
382 dom = find_domain(uri, args->i);
384 if (uri == NULL || dom == NULL ||
385 webkit_web_view_get_load_status(t->wv) == WEBKIT_LOAD_FAILED) {
386 show_oops(t, "Can't toggle domain in cookie white list");
387 goto done;
389 w = wl_find(dom, &c_wl);
391 if (w == NULL)
392 es = 0;
393 else
394 es = 1;
396 if (args->i & XT_WL_TOGGLE)
397 es = !es;
398 else if ((args->i & XT_WL_ENABLE) && es != 1)
399 es = 1;
400 else if ((args->i & XT_WL_DISABLE) && es != 0)
401 es = 0;
403 if (es) {
404 /* enable cookies for domain */
405 args->i |= !XT_WL_PERSISTENT;
406 wl_add(dom, &c_wl, args->i);
407 } else {
408 /* disable cookies for domain */
409 if (w != NULL) {
410 TAILQ_REMOVE(&c_wl, w, entry);
411 g_free(w->re);
412 g_free(w->pat);
416 if (args->i & XT_WL_RELOAD)
417 webkit_web_view_reload(t->wv);
419 done:
420 g_free(dom);
421 return (0);
425 toggle_js(struct tab *t, struct karg *args)
427 int es;
428 const gchar *uri;
429 struct wl_entry *w;
430 char *dom = NULL;
432 if (args == NULL)
433 return (1);
435 g_object_get(G_OBJECT(t->settings),
436 "enable-scripts", &es, (char *)NULL);
437 if (args->i & XT_WL_TOGGLE)
438 es = !es;
439 else if ((args->i & XT_WL_ENABLE) && es != 1)
440 es = 1;
441 else if ((args->i & XT_WL_DISABLE) && es != 0)
442 es = 0;
443 else
444 return (1);
446 uri = get_uri(t);
447 dom = find_domain(uri, args->i);
449 if (uri == NULL || dom == NULL ||
450 webkit_web_view_get_load_status(t->wv) == WEBKIT_LOAD_FAILED) {
451 show_oops(t, "Can't toggle domain in JavaScript white list");
452 goto done;
455 if (es) {
456 button_set_stockid(t->js_toggle, GTK_STOCK_MEDIA_PLAY);
457 args->i |= !XT_WL_PERSISTENT;
458 wl_add(dom, &js_wl, args->i);
459 } else {
460 w = wl_find(dom, &js_wl);
461 if (w != NULL) {
462 TAILQ_REMOVE(&js_wl, w, entry);
463 g_free(w->re);
464 g_free(w->pat);
466 button_set_stockid(t->js_toggle, GTK_STOCK_MEDIA_PAUSE);
468 g_object_set(G_OBJECT(t->settings),
469 "enable-scripts", es, (char *)NULL);
470 g_object_set(G_OBJECT(t->settings),
471 "javascript-can-open-windows-automatically", es, (char *)NULL);
472 webkit_web_view_set_settings(t->wv, t->settings);
474 if (args->i & XT_WL_RELOAD)
475 webkit_web_view_reload(t->wv);
476 done:
477 if (dom)
478 g_free(dom);
479 return (0);
483 toggle_pl(struct tab *t, struct karg *args)
485 int es;
486 const gchar *uri;
487 struct wl_entry *w;
488 char *dom = NULL;
490 if (args == NULL)
491 return (1);
493 g_object_get(G_OBJECT(t->settings),
494 "enable-plugins", &es, (char *)NULL);
495 if (args->i & XT_WL_TOGGLE)
496 es = !es;
497 else if ((args->i & XT_WL_ENABLE) && es != 1)
498 es = 1;
499 else if ((args->i & XT_WL_DISABLE) && es != 0)
500 es = 0;
501 else
502 return (1);
504 uri = get_uri(t);
505 dom = find_domain(uri, args->i);
507 if (uri == NULL || dom == NULL ||
508 webkit_web_view_get_load_status(t->wv) == WEBKIT_LOAD_FAILED) {
509 show_oops(t, "Can't toggle domain in plugins white list");
510 goto done;
513 if (es) {
514 args->i |= !XT_WL_PERSISTENT;
515 wl_add(dom, &pl_wl, args->i);
516 } else {
517 w = wl_find(dom, &pl_wl);
518 if (w != NULL) {
519 TAILQ_REMOVE(&pl_wl, w, entry);
520 g_free(w->re);
521 g_free(w->pat);
524 g_object_set(G_OBJECT(t->settings),
525 "enable-plugins", es, (char *)NULL);
526 webkit_web_view_set_settings(t->wv, t->settings);
528 if (args->i & XT_WL_RELOAD)
529 webkit_web_view_reload(t->wv);
530 done:
531 if (dom)
532 g_free(dom);
533 return (0);
537 toggle_force_https(struct tab *t, struct karg *args)
539 int es;
540 const gchar *uri;
541 struct wl_entry *w;
542 char *dom = NULL;
544 if (args == NULL)
545 return (1);
547 uri = get_uri(t);
548 dom = find_domain(uri, args->i);
550 if (uri == NULL || dom == NULL ||
551 webkit_web_view_get_load_status(t->wv) == WEBKIT_LOAD_FAILED) {
552 show_oops(t, "Can't toggle domain in https force list");
553 goto done;
555 w = wl_find(dom, &force_https);
557 if (w == NULL)
558 es = 0;
559 else
560 es = 1;
562 if (args->i & XT_WL_TOGGLE)
563 es = !es;
564 else if ((args->i & XT_WL_ENABLE) && es != 1)
565 es = 1;
566 else if ((args->i & XT_WL_DISABLE) && es != 0)
567 es = 0;
569 uri = get_uri(t);
570 dom = find_domain(uri, args->i);
572 if (es) {
573 args->i |= !XT_WL_PERSISTENT;
574 wl_add(dom, &force_https, args->i);
575 } else {
576 w = wl_find(dom, &force_https);
577 if (w != NULL) {
578 TAILQ_REMOVE(&force_https, w, entry);
579 g_free(w->re);
580 g_free(w->pat);
584 if (args->i & XT_WL_RELOAD)
585 webkit_web_view_reload(t->wv);
586 done:
587 if (dom)
588 g_free(dom);
589 return (0);