add enable_cache example to xombrero.conf
[xombrero.git] / whitelist.c
blobf9862f322ac2f1db0a24fa8eb2bc47759887a42f
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)
37 return (NULL);
38 if (!SOUP_URI_VALID_FOR_HTTP(uri)) {
39 soup_uri_free(uri);
40 return (NULL);
43 if (flags & XT_WL_TOPLEVEL &&
44 !isdigit(uri->host[strlen(uri->host) - 1]))
45 p = tld_get_suffix(uri->host);
46 else
47 p = uri->host;
49 if (flags & XT_WL_TOPLEVEL)
50 ret = g_strdup_printf(".%s", p);
51 else /* assume FQDN */
52 ret = g_strdup(p);
54 soup_uri_free(uri);
56 return (ret);
59 struct wl_entry *
60 wl_find(const gchar *s, struct wl_list *wl)
62 struct wl_entry *w;
64 if (s == NULL || strlen(s) == 0 || wl == NULL)
65 return (NULL);
67 TAILQ_FOREACH(w, wl, entry) {
68 if (w->re == NULL)
69 continue;
70 if (!regexec(w->re, s, 0, 0, 0))
71 return (w);
74 return (NULL);
77 int
78 wl_save(struct tab *t, struct karg *args, int list)
80 char file[PATH_MAX], *lst_str = NULL;
81 FILE *f = NULL;
82 char *line = NULL, *lt = NULL, *dom;
83 size_t linelen;
84 const gchar *uri;
85 struct karg a;
86 struct wl_entry *w;
87 GSList *cf;
88 SoupCookie *ci, *c;
90 if (t == NULL || args == NULL)
91 return (1);
93 if (runtime_settings[0] == '\0')
94 return (1);
96 switch (list) {
97 case XT_WL_JAVASCRIPT:
98 lst_str = "JavaScript";
99 break;
100 case XT_WL_COOKIE:
101 lst_str = "Cookie";
102 break;
103 case XT_WL_PLUGIN:
104 lst_str = "Plugin";
105 break;
106 case XT_WL_HTTPS:
107 lst_str = "HTTPS";
108 break;
109 default:
110 show_oops(t, "Invalid list id: %d", list);
111 return (1);
114 uri = get_uri(t);
115 dom = find_domain(uri, args->i);
116 if (uri == NULL || dom == NULL ||
117 webkit_web_view_get_load_status(t->wv) == WEBKIT_LOAD_FAILED) {
118 show_oops(t, "Can't add domain to %s white list", lst_str);
119 goto done;
122 switch (list) {
123 case XT_WL_JAVASCRIPT:
124 lt = g_strdup_printf("js_wl=%s", dom);
125 break;
126 case XT_WL_COOKIE:
127 lt = g_strdup_printf("cookie_wl=%s", dom);
128 break;
129 case XT_WL_PLUGIN:
130 lt = g_strdup_printf("pl_wl=%s", dom);
131 break;
132 case XT_WL_HTTPS:
133 lt = g_strdup_printf("force_https=%s", dom);
134 break;
135 default:
136 /* can't happen */
137 show_oops(t, "Invalid list id: %d", list);
138 goto done;
141 snprintf(file, sizeof file, "%s" PS "%s", work_dir, runtime_settings);
142 if ((f = fopen(file, "r+")) == NULL) {
143 show_oops(t, "can't open file %s");
144 goto done;
147 while (!feof(f)) {
148 line = fparseln(f, &linelen, NULL, NULL, 0);
149 if (line == NULL)
150 continue;
151 if (!strcmp(line, lt))
152 goto done;
153 free(line);
154 line = NULL;
157 fprintf(f, "%s\n", lt);
159 a.i = XT_WL_ENABLE;
160 a.i |= args->i;
161 switch (list) {
162 case XT_WL_JAVASCRIPT:
163 w = wl_find(dom, &js_wl);
164 if (w == NULL) {
165 settings_add("js_wl", dom);
166 w = wl_find(dom, &js_wl);
168 toggle_js(t, &a);
169 break;
171 case XT_WL_COOKIE:
172 w = wl_find(dom, &c_wl);
173 if (w == NULL) {
174 settings_add("cookie_wl", dom);
175 w = wl_find(dom, &c_wl);
177 toggle_cwl(t, &a);
179 /* find and add to persistent jar */
180 cf = soup_cookie_jar_all_cookies(s_cookiejar);
181 for (;cf; cf = cf->next) {
182 ci = cf->data;
183 if (!strcmp(dom, ci->domain) ||
184 !strcmp(&dom[1], ci->domain)) /* deal with leading . */ {
185 c = soup_cookie_copy(ci);
186 _soup_cookie_jar_add_cookie(p_cookiejar, c);
189 soup_cookies_free(cf);
190 break;
192 case XT_WL_PLUGIN:
193 w = wl_find(dom, &pl_wl);
194 if (w == NULL) {
195 settings_add("pl_wl", dom);
196 w = wl_find(dom, &pl_wl);
198 toggle_pl(t, &a);
199 break;
200 case XT_WL_HTTPS:
201 w = wl_find(dom, &force_https);
202 if (w == NULL) {
203 settings_add("force_https", dom);
204 w = wl_find(dom, &force_https);
206 toggle_force_https(t, &a);
207 break;
208 default:
209 abort(); /* can't happen */
211 if (w != NULL)
212 w->handy = 1;
214 done:
215 if (line)
216 free(line);
217 if (dom)
218 g_free(dom);
219 if (lt)
220 g_free(lt);
221 if (f)
222 fclose(f);
224 return (0);
228 wl_show(struct tab *t, struct karg *args, char *title, struct wl_list *wl)
230 struct wl_entry *w;
231 char *tmp, *body;
233 body = g_strdup("");
235 /* p list */
236 if (args->i & XT_WL_PERSISTENT) {
237 tmp = body;
238 body = g_strdup_printf("%s<h2>Persistent</h2>", body);
239 g_free(tmp);
240 TAILQ_FOREACH(w, wl, entry) {
241 if (w->handy == 0)
242 continue;
243 tmp = body;
244 body = g_strdup_printf("%s%s<br/>", body, w->pat);
245 g_free(tmp);
249 /* s list */
250 if (args->i & XT_WL_SESSION) {
251 tmp = body;
252 body = g_strdup_printf("%s<h2>Session</h2>", body);
253 g_free(tmp);
254 TAILQ_FOREACH(w, wl, entry) {
255 if (w->handy == 1)
256 continue;
257 tmp = body;
258 body = g_strdup_printf("%s%s<br/>", body, w->pat);
259 g_free(tmp);
263 tmp = get_html_page(title, body, "", 0);
264 g_free(body);
265 if (wl == &js_wl)
266 load_webkit_string(t, tmp, XT_URI_ABOUT_JSWL, 0);
267 else if (wl == &c_wl)
268 load_webkit_string(t, tmp, XT_URI_ABOUT_COOKIEWL, 0);
269 else if (wl == &pl_wl)
270 load_webkit_string(t, tmp, XT_URI_ABOUT_PLUGINWL, 0);
271 else if (wl == &force_https)
272 load_webkit_string(t, tmp, XT_URI_ABOUT_HTTPS, 0);
273 g_free(tmp);
274 return (0);
277 void
278 wl_add(const char *str, struct wl_list *wl, int flags)
280 struct wl_entry *w;
281 int add_dot = 0, chopped = 0;
282 const char *s = str;
283 char *escstr, *p, *pat;
284 char **sv;
286 if (str == NULL || wl == NULL || strlen(str) < 2)
287 return;
289 DNPRINTF(XT_D_COOKIE, "wl_add in: %s\n", str);
291 /* slice off port number */
292 p = g_strrstr(str, ":");
293 if (p)
294 *p = '\0';
296 w = g_malloc(sizeof *w);
297 w->re = g_malloc(sizeof *w->re);
298 if (flags & XT_WL_REGEX) {
299 w->pat = g_strdup_printf("re:%s", str);
300 regcomp(w->re, str, REG_EXTENDED | REG_NOSUB);
301 DNPRINTF(XT_D_COOKIE, "wl_add: %s\n", str);
302 } else {
303 /* treat *.moo.com the same as .moo.com */
304 if (s[0] == '*' && s[1] == '.')
305 s = &s[1];
306 else if (s[0] != '.' && (flags & XT_WL_TOPLEVEL))
307 add_dot = 1;
309 if (s[0] == '.') {
310 s = &s[1];
311 chopped = 1;
313 sv = g_strsplit(s, ".", 0);
314 escstr = g_strjoinv("\\.", sv);
315 g_strfreev(sv);
317 if (add_dot) {
318 w->pat = g_strdup_printf(".%s", str);
319 pat = g_strdup_printf("^(.*\\.)*%s$", escstr);
320 regcomp(w->re, pat, REG_EXTENDED | REG_NOSUB);
321 } else {
322 w->pat = g_strdup(str);
323 if (chopped)
324 pat = g_strdup_printf("^(.*\\.)*%s$", escstr);
325 else
326 pat = g_strdup_printf("^%s$", escstr);
327 regcomp(w->re, pat, REG_EXTENDED | REG_NOSUB);
329 DNPRINTF(XT_D_COOKIE, "wl_add: %s\n", pat);
330 g_free(escstr);
331 g_free(pat);
334 w->handy = (flags & XT_WL_PERSISTENT) ? 1 : 0;
336 TAILQ_INSERT_HEAD(wl, w, entry);
338 return;
342 add_cookie_wl(struct settings *s, char *entry)
344 if (g_str_has_prefix(entry, "re:")) {
345 entry = &entry[3];
346 wl_add(entry, &c_wl, XT_WL_PERSISTENT | XT_WL_REGEX);
347 } else
348 wl_add(entry, &c_wl, XT_WL_PERSISTENT);
349 return (0);
353 add_js_wl(struct settings *s, char *entry)
355 if (g_str_has_prefix(entry, "re:")) {
356 entry = &entry[3];
357 wl_add(entry, &js_wl, XT_WL_PERSISTENT | XT_WL_REGEX);
358 } else
359 wl_add(entry, &js_wl, XT_WL_PERSISTENT);
360 return (0);
364 add_pl_wl(struct settings *s, char *entry)
366 if (g_str_has_prefix(entry, "re:")) {
367 entry = &entry[3];
368 wl_add(entry, &pl_wl, XT_WL_PERSISTENT | XT_WL_REGEX);
369 } else
370 wl_add(entry, &pl_wl, XT_WL_PERSISTENT);
371 return (0);
375 toggle_cwl(struct tab *t, struct karg *args)
377 struct wl_entry *w;
378 const gchar *uri;
379 char *dom = NULL;
380 int es;
382 if (args == NULL)
383 return (1);
385 uri = get_uri(t);
386 dom = find_domain(uri, args->i);
388 if (uri == NULL || dom == NULL ||
389 webkit_web_view_get_load_status(t->wv) == WEBKIT_LOAD_FAILED) {
390 show_oops(t, "Can't toggle domain in cookie white list");
391 goto done;
393 w = wl_find(dom, &c_wl);
395 if (w == NULL)
396 es = 0;
397 else
398 es = 1;
400 if (args->i & XT_WL_TOGGLE)
401 es = !es;
402 else if ((args->i & XT_WL_ENABLE) && es != 1)
403 es = 1;
404 else if ((args->i & XT_WL_DISABLE) && es != 0)
405 es = 0;
407 if (es) {
408 /* enable cookies for domain */
409 args->i |= !XT_WL_PERSISTENT;
410 wl_add(dom, &c_wl, args->i);
411 } else {
412 /* disable cookies for domain */
413 if (w != NULL) {
414 TAILQ_REMOVE(&c_wl, w, entry);
415 g_free(w->re);
416 g_free(w->pat);
420 if (args->i & XT_WL_RELOAD)
421 webkit_web_view_reload(t->wv);
423 done:
424 g_free(dom);
425 return (0);
429 toggle_js(struct tab *t, struct karg *args)
431 int es;
432 const gchar *uri;
433 struct wl_entry *w;
434 char *dom = NULL;
436 if (args == NULL)
437 return (1);
439 g_object_get(G_OBJECT(t->settings),
440 "enable-scripts", &es, (char *)NULL);
441 if (args->i & XT_WL_TOGGLE)
442 es = !es;
443 else if ((args->i & XT_WL_ENABLE) && es != 1)
444 es = 1;
445 else if ((args->i & XT_WL_DISABLE) && es != 0)
446 es = 0;
447 else
448 return (1);
450 uri = get_uri(t);
451 dom = find_domain(uri, args->i);
453 if (uri == NULL || dom == NULL ||
454 webkit_web_view_get_load_status(t->wv) == WEBKIT_LOAD_FAILED) {
455 show_oops(t, "Can't toggle domain in JavaScript white list");
456 goto done;
459 if (es) {
460 button_set_stockid(t->js_toggle, GTK_STOCK_MEDIA_PLAY);
461 args->i |= !XT_WL_PERSISTENT;
462 wl_add(dom, &js_wl, args->i);
463 } else {
464 w = wl_find(dom, &js_wl);
465 if (w != NULL) {
466 TAILQ_REMOVE(&js_wl, w, entry);
467 g_free(w->re);
468 g_free(w->pat);
470 button_set_stockid(t->js_toggle, GTK_STOCK_MEDIA_PAUSE);
472 g_object_set(G_OBJECT(t->settings),
473 "enable-scripts", es, (char *)NULL);
474 g_object_set(G_OBJECT(t->settings),
475 "javascript-can-open-windows-automatically", es, (char *)NULL);
476 webkit_web_view_set_settings(t->wv, t->settings);
478 if (args->i & XT_WL_RELOAD)
479 webkit_web_view_reload(t->wv);
480 done:
481 if (dom)
482 g_free(dom);
483 return (0);
487 toggle_pl(struct tab *t, struct karg *args)
489 int es;
490 const gchar *uri;
491 struct wl_entry *w;
492 char *dom = NULL;
494 if (args == NULL)
495 return (1);
497 g_object_get(G_OBJECT(t->settings),
498 "enable-plugins", &es, (char *)NULL);
499 if (args->i & XT_WL_TOGGLE)
500 es = !es;
501 else if ((args->i & XT_WL_ENABLE) && es != 1)
502 es = 1;
503 else if ((args->i & XT_WL_DISABLE) && es != 0)
504 es = 0;
505 else
506 return (1);
508 uri = get_uri(t);
509 dom = find_domain(uri, args->i);
511 if (uri == NULL || dom == NULL ||
512 webkit_web_view_get_load_status(t->wv) == WEBKIT_LOAD_FAILED) {
513 show_oops(t, "Can't toggle domain in plugins white list");
514 goto done;
517 if (es) {
518 args->i |= !XT_WL_PERSISTENT;
519 wl_add(dom, &pl_wl, args->i);
520 } else {
521 w = wl_find(dom, &pl_wl);
522 if (w != NULL) {
523 TAILQ_REMOVE(&pl_wl, w, entry);
524 g_free(w->re);
525 g_free(w->pat);
528 g_object_set(G_OBJECT(t->settings),
529 "enable-plugins", es, (char *)NULL);
530 webkit_web_view_set_settings(t->wv, t->settings);
532 if (args->i & XT_WL_RELOAD)
533 webkit_web_view_reload(t->wv);
534 done:
535 if (dom)
536 g_free(dom);
537 return (0);
541 toggle_force_https(struct tab *t, struct karg *args)
543 int es;
544 const gchar *uri;
545 struct wl_entry *w;
546 char *dom = NULL;
548 if (args == NULL)
549 return (1);
551 uri = get_uri(t);
552 dom = find_domain(uri, args->i);
554 if (uri == NULL || dom == NULL ||
555 webkit_web_view_get_load_status(t->wv) == WEBKIT_LOAD_FAILED) {
556 show_oops(t, "Can't toggle domain in https force list");
557 goto done;
559 w = wl_find(dom, &force_https);
561 if (w == NULL)
562 es = 0;
563 else
564 es = 1;
566 if (args->i & XT_WL_TOGGLE)
567 es = !es;
568 else if ((args->i & XT_WL_ENABLE) && es != 1)
569 es = 1;
570 else if ((args->i & XT_WL_DISABLE) && es != 0)
571 es = 0;
573 uri = get_uri(t);
574 dom = find_domain(uri, args->i);
576 if (es) {
577 args->i |= !XT_WL_PERSISTENT;
578 wl_add(dom, &force_https, args->i);
579 } else {
580 w = wl_find(dom, &force_https);
581 if (w != NULL) {
582 TAILQ_REMOVE(&force_https, w, entry);
583 g_free(w->re);
584 g_free(w->pat);
588 if (args->i & XT_WL_RELOAD)
589 webkit_web_view_reload(t->wv);
590 done:
591 if (dom)
592 g_free(dom);
593 return (0);