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.
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
*,
28 print_cookie(char *msg
, SoupCookie
*c
)
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");
49 set_hook(void **hook
, char *name
)
55 *hook
= dlsym(RTLD_NEXT
, name
);
57 errx(1, "can't hook %s", name
);
61 /* override libsoup soup_cookie_equal because it doesn't look at domain */
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
));
75 transfer_cookies(void)
80 cf
= soup_cookie_jar_all_cookies(p_cookiejar
);
82 for (;cf
; cf
= cf
->next
) {
84 sc
= soup_cookie_copy(pc
);
85 _soup_cookie_jar_add_cookie(s_cookiejar
, sc
);
88 soup_cookies_free(cf
);
92 soup_cookie_jar_delete_cookie(SoupCookieJar
*jar
, SoupCookie
*c
)
97 print_cookie("soup_cookie_jar_delete_cookie", c
);
99 if (cookies_enabled
== 0)
102 if (jar
== NULL
|| c
== NULL
)
105 /* find and remove from persistent jar */
106 cf
= soup_cookie_jar_all_cookies(p_cookiejar
);
108 for (;cf
; cf
= cf
->next
) {
110 if (soup_cookie_equal(ci
, c
)) {
111 _soup_cookie_jar_delete_cookie(p_cookiejar
, ci
);
116 soup_cookies_free(cf
);
118 /* delete from session jar */
119 _soup_cookie_jar_delete_cookie(s_cookiejar
, c
);
123 soup_cookie_jar_add_cookie(SoupCookieJar
*jar
, SoupCookie
*cookie
)
125 struct domain
*d
= NULL
;
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)
136 /* see if we are up and running */
137 if (p_cookiejar
== NULL
) {
138 _soup_cookie_jar_add_cookie(jar
, cookie
);
141 /* disallow p_cookiejar adds, shouldn't happen */
142 if (jar
== p_cookiejar
)
146 if (jar
== NULL
|| cookie
== NULL
)
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 (d
= wl_find(cookie
->domain
, &c_wl
)) == NULL
)) {
157 DNPRINTF(XT_D_COOKIE
,
158 "soup_cookie_jar_add_cookie: reject %s\n",
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");
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_" : "",
169 *cookie
->domain
== '.' ? "TRUE" : "FALSE",
171 cookie
->secure
? "TRUE" : "FALSE",
173 (gulong
)soup_date_to_time_t(cookie
->expires
) :
180 if (!allow_volatile_cookies
)
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 ((d
&& d
->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
);
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)
217 * the following code is intricate due to overriding several libsoup
219 * do not alter order of these operations.
222 /* rejected cookies */
223 if (save_rejected_cookies
)
224 snprintf(rc_fname
, sizeof file
, "%s/%s", work_dir
,
227 /* persistent cookies */
228 snprintf(file
, sizeof file
, "%s/%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
);
237 soup_session_add_feature(session
, (SoupSessionFeature
*)s_cookiejar
);