/* * Copyright (c) 2010-2013 Stefan Bolte * Copyright (c) 2013 Elias Norberg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "dwb.h" #include "util.h" #include "domain.h" #include "tlds.h" static GHashTable *s_tld_table; GSList * domain_get_cookie_domains(WebKitWebView *wv) { GSList *ret = NULL; WebKitWebFrame *frame = webkit_web_view_get_main_frame(wv); WebKitWebDataSource *data = webkit_web_frame_get_data_source(frame); if (data == NULL) return NULL; WebKitNetworkRequest *request = webkit_web_data_source_get_request(data); if (request == NULL) return NULL; SoupMessage *msg = webkit_network_request_get_message(request); if (msg == NULL) return NULL; SoupURI *uri = soup_message_get_uri(msg); if (uri == NULL) return NULL; const char *host = soup_uri_get_host(uri); char *base_host = g_strconcat(".", host, NULL); const char *base_domain = domain_get_base_for_host(base_host); char *cur = base_host; char *nextdot; while (cur != base_domain) { nextdot = strchr(cur, '.'); ret = g_slist_append(ret, nextdot); cur = nextdot+1; ret = g_slist_append(ret, cur); } return ret; } gboolean domain_match(char **domains, const char *host, const char *base_domain) { g_return_val_if_fail(domains != NULL, false); g_return_val_if_fail(host != NULL, false); g_return_val_if_fail(base_domain != NULL, false); g_return_val_if_fail(g_str_has_suffix(host, base_domain), false); const char *subdomains[SUBDOMAIN_MAX]; int sdc = 0; gboolean domain_exc = false; gboolean has_positive = false; gboolean has_exception = false; gboolean found_positive = false; gboolean found_exception = false; char *real_domain; char *nextdot; /* extract subdomains */ subdomains[sdc++] = host; while (g_strcmp0(host, base_domain)) { nextdot = strchr(host, '.'); host = nextdot + 1; subdomains[sdc++] = host; if (sdc == SUBDOMAIN_MAX-1) break; } subdomains[sdc++] = NULL; for (int k=0; domains[k]; k++) { for (int j=0; subdomains[j]; j++) { real_domain = domains[k]; if (*real_domain == '~') { domain_exc = true; real_domain++; has_exception = true; } else { domain_exc = false; has_positive = true; } if (!g_strcmp0(subdomains[j], real_domain)) { if (domain_exc) found_exception = true; else found_positive = true; } } } if ((has_positive && found_positive && !found_exception) || (has_exception && !has_positive && !found_exception)) return true; return false; }/*}}}*/ int count_char(const char *str, char ch) { int count = 0; if (str == NULL) return 0; for (; *str != '\0'; str++) if (*str == ch) count ++; return count; } const char * domain_get_tld(const char *host) { g_return_val_if_fail(host != NULL, NULL); g_return_val_if_fail(s_tld_table != NULL, NULL); const char *cur_domain = host; const char *prev_domain = host; const char *pprev_domain = host; const char *ret = NULL; char *nextdot = strchr(cur_domain, '.'); char *entry = NULL; /* check if hostname is valid * - cannot start with . * - must only contain A-Za-z0-9.-_ */ if (*cur_domain == '.' || strspn(cur_domain, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrustuvwxyz" "0123456789._-") != strlen(cur_domain)) { return NULL; } while (1) { entry = g_hash_table_lookup(s_tld_table, cur_domain); if (entry != NULL) { if (*entry == '*') { /* check that we have enough to build * a domain that satisfies the rule */ if (count_char(pprev_domain, '.') >= count_char(entry, '.') + 1) { ret = pprev_domain; } break; } else if (*entry == '!') { ret = cur_domain; break; } else if(strcmp(entry, prev_domain) == 0) break; else { ret = prev_domain; break; } } if (nextdot == NULL) break; pprev_domain = prev_domain; prev_domain = cur_domain; cur_domain = nextdot + 1; PRINT_DEBUG(nextdot); nextdot = strchr(cur_domain, '.'); } return ret; } const char * domain_get_base_for_host(const char *host) { const char *base; base = domain_get_tld(host); if (base == NULL) return host; return base; } void domain_end() { if (s_tld_table) { g_hash_table_unref(s_tld_table); s_tld_table = NULL; } } void domain_init() { s_tld_table = g_hash_table_new((GHashFunc)g_str_hash, (GEqualFunc)g_str_equal); char *eff_tld; for (int i=0; (eff_tld = TLDS_EFFECTIVE[i]); i++) { if (*eff_tld == '*' || *eff_tld == '!') eff_tld++; if (*eff_tld == '.') eff_tld++; g_hash_table_insert(s_tld_table, eff_tld, TLDS_EFFECTIVE[i]); } }