no longer need to run analyze, just use 'scan-build make'
[xombrero.git] / cookie.c
blob8de0fbc6c8301897d2db5d569e65dfbdd4e1423c
1 /*
2 * Copyright (c) 2010, 2011 Marco Peereboom <marco@peereboom.us>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <xombrero.h>
19 #define XT_REJECT_FILE ("rejected.txt")
20 #define XT_COOKIE_FILE ("cookies.txt")
22 /* hooked functions */
23 void (*_soup_cookie_jar_add_cookie)(SoupCookieJar *, SoupCookie *);
24 void (*_soup_cookie_jar_delete_cookie)(SoupCookieJar *,
25 SoupCookie *);
27 void
28 print_cookie(char *msg, SoupCookie *c)
30 if (c == NULL)
31 return;
33 if (msg) {
34 DNPRINTF(XT_D_COOKIE, "%s\n", msg);
37 DNPRINTF(XT_D_COOKIE, "name : %s\n", c->name);
38 DNPRINTF(XT_D_COOKIE, "value : %s\n", c->value);
39 DNPRINTF(XT_D_COOKIE, "domain : %s\n", c->domain);
40 DNPRINTF(XT_D_COOKIE, "path : %s\n", c->path);
41 DNPRINTF(XT_D_COOKIE, "expires : %s\n",
42 c->expires ? soup_date_to_string(c->expires, SOUP_DATE_HTTP) : "");
43 DNPRINTF(XT_D_COOKIE, "secure : %d\n", c->secure);
44 DNPRINTF(XT_D_COOKIE, "http_only: %d\n", c->http_only);
45 DNPRINTF(XT_D_COOKIE, "====================================\n");
48 void
49 set_hook(void **hook, char *name)
51 if (hook == NULL)
52 errx(1, "set_hook");
54 if (*hook == NULL) {
55 *hook = dlsym(RTLD_NEXT, name);
56 if (*hook == NULL)
57 errx(1, "can't hook %s", name);
61 /* override libsoup soup_cookie_equal because it doesn't look at domain */
62 gboolean
63 soup_cookie_equal(SoupCookie *cookie1, SoupCookie *cookie2)
65 g_return_val_if_fail(cookie1, FALSE);
66 g_return_val_if_fail(cookie2, FALSE);
68 return (!strcmp (cookie1->name, cookie2->name) &&
69 !strcmp (cookie1->value, cookie2->value) &&
70 !strcmp (cookie1->path, cookie2->path) &&
71 !strcmp (cookie1->domain, cookie2->domain));
74 void
75 transfer_cookies(void)
77 GSList *cf;
78 SoupCookie *sc, *pc;
80 cf = soup_cookie_jar_all_cookies(p_cookiejar);
82 for (;cf; cf = cf->next) {
83 pc = cf->data;
84 sc = soup_cookie_copy(pc);
85 _soup_cookie_jar_add_cookie(s_cookiejar, sc);
88 soup_cookies_free(cf);
91 void
92 soup_cookie_jar_delete_cookie(SoupCookieJar *jar, SoupCookie *c)
94 GSList *cf;
95 SoupCookie *ci;
97 print_cookie("soup_cookie_jar_delete_cookie", c);
99 if (cookies_enabled == 0)
100 return;
102 if (jar == NULL || c == NULL)
103 return;
105 /* find and remove from persistent jar */
106 cf = soup_cookie_jar_all_cookies(p_cookiejar);
108 for (;cf; cf = cf->next) {
109 ci = cf->data;
110 if (soup_cookie_equal(ci, c)) {
111 _soup_cookie_jar_delete_cookie(p_cookiejar, ci);
112 break;
116 soup_cookies_free(cf);
118 /* delete from session jar */
119 _soup_cookie_jar_delete_cookie(s_cookiejar, c);
122 void
123 soup_cookie_jar_add_cookie(SoupCookieJar *jar, SoupCookie *cookie)
125 struct wl_entry *w = NULL;
126 SoupCookie *c;
127 FILE *r_cookie_f;
128 char *public_suffix;
130 DNPRINTF(XT_D_COOKIE, "soup_cookie_jar_add_cookie: %p %p %p\n",
131 jar, p_cookiejar, s_cookiejar);
133 if (cookies_enabled == 0)
134 return;
136 /* see if we are up and running */
137 if (p_cookiejar == NULL) {
138 _soup_cookie_jar_add_cookie(jar, cookie);
139 return;
141 /* disallow p_cookiejar adds, shouldn't happen */
142 if (jar == p_cookiejar)
143 return;
145 /* sanity */
146 if (jar == NULL || cookie == NULL)
147 return;
149 /* check if domain is valid */
150 public_suffix = tld_get_suffix(cookie->domain[0] == '.' ?
151 cookie->domain + 1 : cookie->domain);
153 if (public_suffix == NULL ||
154 (enable_cookie_whitelist &&
155 (w = wl_find(cookie->domain, &c_wl)) == NULL)) {
156 blocked_cookies++;
157 DNPRINTF(XT_D_COOKIE,
158 "soup_cookie_jar_add_cookie: reject %s\n",
159 cookie->domain);
160 if (save_rejected_cookies) {
161 if ((r_cookie_f = fopen(rc_fname, "a+")) == NULL) {
162 show_oops(NULL, "can't open reject cookie file");
163 return;
165 fseek(r_cookie_f, 0, SEEK_END);
166 fprintf(r_cookie_f, "%s%s\t%s\t%s\t%s\t%lu\t%s\t%s\n",
167 cookie->http_only ? "#HttpOnly_" : "",
168 cookie->domain,
169 *cookie->domain == '.' ? "TRUE" : "FALSE",
170 cookie->path,
171 cookie->secure ? "TRUE" : "FALSE",
172 cookie->expires ?
173 (gulong)soup_date_to_time_t(cookie->expires) :
175 cookie->name,
176 cookie->value);
177 fflush(r_cookie_f);
178 fclose(r_cookie_f);
180 if (!allow_volatile_cookies)
181 return;
184 if (cookie->expires == NULL && session_timeout) {
185 soup_cookie_set_expires(cookie,
186 soup_date_new_from_now(session_timeout));
187 print_cookie("modified add cookie", cookie);
190 /* see if we are white listed for persistence */
191 if ((w && w->handy) || (enable_cookie_whitelist == 0)) {
192 /* add to persistent jar */
193 c = soup_cookie_copy(cookie);
194 print_cookie("soup_cookie_jar_add_cookie p_cookiejar", c);
195 _soup_cookie_jar_add_cookie(p_cookiejar, c);
198 /* add to session jar */
199 print_cookie("soup_cookie_jar_add_cookie s_cookiejar", cookie);
200 _soup_cookie_jar_add_cookie(s_cookiejar, cookie);
203 void
204 setup_cookies(void)
206 char file[PATH_MAX];
208 set_hook((void *)&_soup_cookie_jar_add_cookie,
209 "soup_cookie_jar_add_cookie");
210 set_hook((void *)&_soup_cookie_jar_delete_cookie,
211 "soup_cookie_jar_delete_cookie");
213 if (cookies_enabled == 0)
214 return;
217 * the following code is intricate due to overriding several libsoup
218 * functions.
219 * do not alter order of these operations.
222 /* rejected cookies */
223 if (save_rejected_cookies)
224 snprintf(rc_fname, sizeof file, "%s" PS "%s", work_dir,
225 XT_REJECT_FILE);
227 /* persistent cookies */
228 snprintf(file, sizeof file, "%s" PS "%s", work_dir, XT_COOKIE_FILE);
229 p_cookiejar = soup_cookie_jar_text_new(file, read_only_cookies);
231 /* session cookies */
232 s_cookiejar = soup_cookie_jar_new();
233 g_object_set(G_OBJECT(s_cookiejar), SOUP_COOKIE_JAR_ACCEPT_POLICY,
234 cookie_policy, (void *)NULL);
235 transfer_cookies();
237 soup_session_add_feature(session, (SoupSessionFeature*)s_cookiejar);