278#define NUM_SEARCH_TREES 28
291#define MIN_COOKIE_FILE_VERSION 100
293#define COOKIE_FILE_VERSION 102
298#define MIN_URL_FILE_VERSION 106
300#define URL_FILE_VERSION 107
317#define BLOOM_SIZE (1024 * 32)
334 fprintf(fp,
"%i\n", (
int)val);
336 fprintf(fp,
"%.*s\n", use, op);
366 int len = *path_used + seglen + 1;
368 if (*path_alloc < len) {
370 temp = realloc(*
path,
371 (len > 64) ? len : *path_alloc + 64);
376 *path_alloc = (len > 64) ? len : *path_alloc + 64;
380 memcpy(*
path + *path_used - 1, p->
segment, seglen);
384 (*path)[*path_used + seglen - 1] =
'/';
385 (*path)[*path_used + seglen] =
'\0';
387 (*path)[*path_used + seglen - 1] =
'\0';
401 fprintf(fp,
"%s\n", lwc_string_data(p->
scheme));
404 fprintf(fp,
"%d\n", p->
port);
409 fprintf(fp,
"%s\n", *
path);
420 fprintf(fp,
"%i\n", (
int)p->
urld.
type);
427 for (i = 0; s[i] !=
'\0'; i++)
430 for (--i; ((i > 0) && (s[i] ==
' '));
441 int seglen = p->
segment != NULL
445 *path_used -= seglen;
446 (*path)[*path_used - 1] =
'\0';
448 if (p->
next != NULL) {
456 (*path)[*path_used - 1] =
'\0';
494 if (p->
next != NULL) {
518 unsigned int path_count = 0;
519 char *
path, *p, *end;
520 int path_alloc = 64, path_used = 1;
521 time_t expiry, hsts_expiry = 0;
522 int hsts_include_subdomains = 0;
524 expiry = time(NULL) - ((60 * 60 * 24) *
nsoption_int(expire_url));
531 path = malloc(path_alloc);
537 for (h =
parent->data, p = host, end = host +
sizeof host;
539 int written = snprintf(p, end - p,
"%s%s", h->
part,
556 if (path_count > 0) {
557 fprintf(fp,
"%s %i ", host, hsts_include_subdomains);
559 fprintf(fp,
"%i\n", path_count);
562 &
path, &path_alloc, &path_used, expiry);
563 }
else if (hsts_expiry) {
564 fprintf(fp,
"%s %i ", host, hsts_include_subdomains);
585 bool (*url_callback)(
nsurl *url,
const struct url_data *data),
586 bool (*cookie_callback)(
const struct cookie_data *data))
600 assert(url_callback || cookie_callback);
608 if (!url_callback(p->
url,
613 for (; c != NULL; c = c->
next) {
614 if (!cookie_callback(c))
621 if (p->
next != NULL) {
650 size_t host_len = strlen(host);
651 const char *sane_host;
654 struct in6_addr ipv6;
656 unsigned int ipv6_addr_len;
676 slash = strchr(host,
'/');
680 char *c = strdup(host);
681 c[slash - host] =
'\0';
683 host_len = slash - host;
684 NSLOG(netsurf, INFO,
"WARNING: called with non-host '%s'",
688 if (strspn(sane_host,
"0123456789abcdefABCDEF[].:") < host_len)
700 for (index = 0; index < host_len; index++) {
701 if (sane_host[index] ==
'.')
712 if ((host_len < 6) ||
713 (sane_host[0] !=
'[') ||
714 (sane_host[host_len - 1] !=
']')) {
718 ipv6_addr_len = host_len - 2;
719 if (ipv6_addr_len >=
sizeof(ipv6_addr)) {
720 ipv6_addr_len =
sizeof(ipv6_addr) - 1;
722 strncpy(ipv6_addr, sane_host + 1, ipv6_addr_len);
723 ipv6_addr[ipv6_addr_len] =
'\0';
725 if (
inet_pton(AF_INET6, ipv6_addr, &ipv6) == 1)
730 if (slash != NULL) free((
void *)sane_host);
734 if (slash != NULL) free((
void *)sane_host);
748 const char *end, *dot;
751 assert(a && a != &
db_root && b);
755 return strncasecmp(a->
part, b, strlen(b));
758 end = b + strlen(b) + 1;
760 while (b < end && a && a != &
db_root) {
761 dot = strchr(b,
'.');
768 if ((ret = strncasecmp(a->
part, b, dot - b)) != 0)
776 plen = strlen(a->
part);
777 if (plen > dot - b) {
780 }
else if (plen < dot - b) {
794 if (a && a != &
db_root && b >= end) {
797 }
else if ((!a || a == &
db_root) && b < end) {
822 assert(
root && prefix && callback);
847 if (
root->data->paths.children) {
911 const char *slash, *end = prefix + strlen(prefix);
914 slash = strchr(prefix,
'/');
919 if (slash == prefix && *prefix ==
'/') {
925 if (strncasecmp(p->
segment, prefix, slash - prefix) == 0) {
965 bool (*cookie_callback)(
const struct cookie_data *data))
977 if ((
parent->data->paths.children) ||
978 ((cookie_callback) &&
979 (
parent->data->paths.cookies))) {
1012 d = calloc(1,
sizeof(
struct host_part));
1025 parent->children->prev = d;
1043 return strcasecmp(*((
const char **) a), *((
const char **) b));
1067 temp = realloc(
segment->fragment,
1068 (
segment->frag_cnt + 1) *
sizeof(
char *));
1114 d = calloc(1,
sizeof(
struct path_data));
1124 lwc_string_unref(d->
scheme);
1132 lwc_string_unref(d->
scheme);
1151 }
else if (!
parent->children) {
1206 const char *end, *dot;
1209 assert(a && a != &
db_root && b);
1213 return strcasecmp(a->
part, b);
1216 end = b + strlen(b) + 1;
1218 while (b < end && a && a != &
db_root) {
1219 dot = strchr(b,
'.');
1226 if ((ret = strncasecmp(a->
part, b, dot - b)) != 0)
1231 plen = strlen(a->
part);
1233 if (plen > dot - b) {
1236 }
else if (plen < dot - b) {
1249 if (a && a != &
db_root && b >= end) {
1252 }
else if ((!a || a == &
db_root) && b < end) {
1274 assert(
root && host);
1305 unsigned short port)
1312 assert(
parent->segment == NULL);
1314 if (
path[0] !=
'/') {
1315 NSLOG(netsurf, INFO,
"path is %s",
path);
1318 assert(
path[0] ==
'/');
1324 slash = strchr(
path + 1,
'/');
1330 lwc_string_isequal(p->
scheme,
scheme, &match) == lwc_error_ok &&
1333 if (*slash ==
'\0') {
1364 const char *host_str;
1365 lwc_string *scheme, *host, *port;
1367 unsigned int port_int;
1382 if (lwc_string_isequal(scheme, corestring_lwc_mailto, &match) ==
1383 lwc_error_ok && match ==
true) {
1384 lwc_string_unref(scheme);
1390 host_str = lwc_string_data(host);
1391 lwc_string_unref(host);
1393 }
else if (lwc_string_isequal(scheme, corestring_lwc_file, &match) ==
1394 lwc_error_ok && match ==
true) {
1395 host_str =
"localhost";
1398 lwc_string_unref(scheme);
1405 lwc_string_unref(scheme);
1411 lwc_string_unref(scheme);
1418 port_int = atoi(lwc_string_data(port));
1419 lwc_string_unref(port);
1427 lwc_string_unref(scheme);
1445 NSLOG(netsurf, INFO,
"\t%s : %u",
1450 for (i = 0; i != p->
frag_cnt; i++) {
1451 NSLOG(netsurf, INFO,
"\t\t\t#%s",
1460 if (p->
next != NULL) {
1484 NSLOG(netsurf, INFO,
"\t%s invalid SSL certs",
1485 parent->permit_invalid_certs ?
"Permits" :
"Denies");
1510 int sl =
sizeof(s) - 2;
1517 for (i = 0; i != depth; i++) {
1523 r = snprintf(&s[i], sl - i,
"%s", h->
part);
1527 if ((i + r) >= sl) {
1540 NSLOG(netsurf, INFO,
"%s", s);
1563 if ((ret = strcasecmp(a->
part, b->
part)) != 0) {
1596 if (
root->left->level ==
root->level) {
1619 if (
root->right->right->level ==
root->level) {
1716 assert(c && n && v);
1720 if (*n !=
' ' && *n !=
'\t')
1725 for (vlen = strlen(n); vlen; vlen--) {
1726 if (n[vlen] ==
' ' || n[vlen] ==
'\t')
1734 if (*v !=
' ' && *v !=
'\t')
1739 for (vlen = strlen(v); vlen; vlen--) {
1740 if (v[vlen] ==
' ' || v[vlen] ==
'\t')
1746 if (!c->
comment && strcasecmp(n,
"Comment") == 0) {
1750 }
else if (!c->
domain && strcasecmp(n,
"Domain") == 0) {
1758 }
else if (strcasecmp(n,
"Max-Age") == 0) {
1764 c->
expires = time(NULL) + temp;
1765 }
else if (!c->
path && strcasecmp(n,
"Path") == 0) {
1767 c->
path = strdup(v);
1770 }
else if (strcasecmp(n,
"Version") == 0) {
1772 }
else if (strcasecmp(n,
"Expires") == 0) {
1786 res =
nsc_strntimet(datenoday, strlen(datenoday), &expires);
1792 expires = (time_t)0x7fffffff;
1795 }
else if (strcasecmp(n,
"Secure") == 0) {
1797 }
else if (strcasecmp(n,
"HttpOnly") == 0) {
1799 }
else if (!c->
name) {
1800 c->
name = strdup(n);
1801 c->
value = strdup(v);
1844 bool in_value =
false;
1845 bool had_value_data =
false;
1846 bool value_verbatim =
false;
1847 bool quoted =
false;
1848 bool was_quoted =
false;
1850 assert(url && cookie && *cookie);
1861 for (cur = *cookie; *cur; cur++) {
1862 if (*cur ==
'\r' && *(cur + 1) ==
'\n') {
1873 }
else if (*cur ==
'\r') {
1876 }
else if (*cur ==
'\n') {
1881 if (in_value && !had_value_data) {
1882 if (*cur ==
' ' || *cur ==
'\t') {
1886 had_value_data =
true;
1891 value_verbatim =
true;
1896 if (in_value && !value_verbatim && (*cur ==
'"')) {
1898 if (cur == *cookie || *(cur - 1) !=
'\\') {
1900 was_quoted = quoted;
1907 if (!quoted && !in_value && *cur ==
'=') {
1913 if (!quoted && (was_quoted || *cur ==
';')) {
1931 had_value_data =
false;
1932 value_verbatim =
false;
1973 if (!quoted && *cur ==
',') {
1976 const char *semi = strchr(cur + 1,
';');
1978 semi = cur + strlen(cur) - 2 ;
1981 for (p = cur + 1; p < semi; p++)
2023 c->
domain = strdup(lwc_string_data(host));
2024 lwc_string_unref(host);
2027 if (c->
path == NULL) {
2030 lwc_string *path_lwc;
2033 if (path_lwc == NULL) {
2041 if (slash != NULL) {
2047 if (slash == NULL) {
2048 lwc_string_unref(path_lwc);
2054 lwc_string_unref(path_lwc);
2056 path = strdup(lwc_string_data(path_lwc));
2057 lwc_string_unref(path_lwc);
2094 char *buf = path_query;
2115 lwc_string_isequal(
scheme,
2134 &match) == lwc_error_ok &&
2179 if (strcasecmp(host, e->part) == 0)
2197 strncpy(buf, host,
sizeof buf);
2198 buf[
sizeof buf - 1] =
'\0';
2202 part = strrchr(buf,
'.');
2207 if (strcasecmp(buf, e->part) == 0)
2234 if (strcasecmp(part + 1, e->part) == 0)
2264 time_t now = time(NULL);
2268 if (c->
domain[0] ==
'.') {
2283 assert(
url != NULL);
2434 const char *
const separators =
"()<>@,;:\\\"/[]?={} \t";
2438 assert(c && used && alloc && buf && *buf);
2443 max_len = 2 + strlen(c->
name) + 1 + strlen(c->
value) + 2 +
2445 8 + strlen(c->
path) + 2 : 0) +
2447 10 + strlen(c->
domain) + 2 : 0);
2449 if (*used + max_len >= *alloc) {
2450 char *temp = realloc(*buf, *alloc + 4096);
2460 sprintf(*buf + *used - 1,
"; %s=", c->
name);
2461 *used += 2 + strlen(c->
name) + 1;
2469 sprintf(*buf + *used - 1,
"\"%s\"", c->
value);
2470 *used += 1 + strlen(c->
value) + 1;
2474 sprintf(*buf + *used - 1,
"%s", c->
value);
2475 *used += strlen(c->
value);
2482 sprintf(*buf + *used - 1,
"; %s=", c->
name);
2483 *used += 2 + strlen(c->
name) + 1;
2488 strpbrk(c->
value, separators) != NULL) {
2489 sprintf(*buf + *used - 1,
"\"%s\"", c->
value);
2490 *used += 1 + strlen(c->
value) + 1;
2492 sprintf(*buf + *used - 1,
"%s", c->
value);
2493 *used += strlen(c->
value);
2498 sprintf(*buf + *used - 1,
"; $Path=");
2501 if (strpbrk(c->
path, separators) != NULL) {
2502 sprintf(*buf + *used - 1,
"\"%s\"", c->
path);
2503 *used += 1 + strlen(c->
path) + 1;
2505 sprintf(*buf + *used - 1,
"%s", c->
path);
2506 *used += strlen(c->
path);
2512 sprintf(*buf + *used - 1,
"; $Domain=");
2515 if (strpbrk(c->
domain, separators) != NULL) {
2516 sprintf(*buf + *used - 1,
"\"%s\"", c->
domain);
2517 *used += 1 + strlen(c->
domain) + 1;
2519 sprintf(*buf + *used - 1,
"%s", c->
domain);
2520 *used += strlen(c->
domain);
2550 if (strcmp(c->
domain, domain) == 0 &&
2552 strcmp(c->
name, name) == 0) {
2575 if (p->
next != NULL) {
2621 time_t now = time(NULL);
2636 "%d\t%s\t%d\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t"
2637 "%s\t%s\t%d\t%s\t%s\t%s\n",
2657 if (p->
next != NULL) {
2714 if (node->
url != NULL) {
2718 if (node->
scheme != NULL) {
2719 lwc_string_unref(node->
scheme);
2723 for (i = 0; i < node->
frag_cnt; i++)
2729 for (a = node->
cookies; a; a = b) {
2743 lwc_string_unref(space->
scheme);
2767 if (p->
next != NULL) {
2783 }
while (p !=
root);
2799 for (a =
root->children; a; a = b) {
2805 for (p =
root->paths.children; p; p = q) {
2814 for (s =
root->prot_space; s; s = t) {
2878#define MAXIMUM_URL_LENGTH 4096
2890 NSLOG(netsurf, INFO,
"Loading URL file %s", filename);
2895 fp = fopen(filename,
"r");
2897 NSLOG(netsurf, INFO,
"Failed to open file '%s' for reading",
2909 NSLOG(netsurf, INFO,
"Unsupported URL file version.");
2914 NSLOG(netsurf, INFO,
"Unknown URL file version.");
2919 while (fgets(host,
sizeof host, fp)) {
2920 time_t hsts_expiry = 0;
2921 int hsts_include_sub_domains = 0;
2924 length = strlen(host) - 1;
2925 host[length] =
'\0';
2933 for (i = 0; i < (8 * urls); i++) {
2942 while (*p && *p !=
' ') p++;
2943 while (*p && *p ==
' ') { *p =
'\0'; p++; }
2944 hsts_include_sub_domains = (*p ==
'1');
2945 while (*p && *p !=
' ') p++;
2946 while (*p && *p ==
' ') p++;
2952 NSLOG(netsurf, INFO,
"Failed adding host: '%s'", host);
2966 NSLOG(netsurf, INFO,
"No URLs for '%s'", host);
2971 for (i = 0; i < urls; i++) {
2973 char scheme[64], ports[10];
2974 char url[64 + 3 + 256 + 6 + 4096 + 1 + 1];
2976 bool is_file =
false;
2978 lwc_string *scheme_lwc, *fragment_lwc;
2984 length = strlen(
scheme) - 1;
2987 if (!fgets(ports,
sizeof ports, fp))
2989 length = strlen(ports) - 1;
2990 ports[length] =
'\0';
2995 length = strlen(s) - 1;
2998 if (!strcasecmp(host,
"localhost") &&
2999 !strcasecmp(
scheme,
"file"))
3002 snprintf(
url,
sizeof url,
"%s://%s%s%s%s",
3005 (is_file ?
"" : host),
3007 (
port ? ports :
""),
3016 NSLOG(netsurf, INFO,
"Failed inserting '%s'",
3030 NSLOG(netsurf, INFO,
"Failed inserting '%s'",
3040 fragment_lwc,
nsurl);
3042 NSLOG(netsurf, INFO,
"Failed inserting '%s'",
3048 lwc_string_unref(scheme_lwc);
3049 if (fragment_lwc != NULL)
3050 lwc_string_unref(fragment_lwc);
3076 length = strlen(s) - 1;
3077 if (p && length > 0) {
3087 NSLOG(netsurf, INFO,
"Successfully loaded URL file");
3088#undef MAXIMUM_URL_LENGTH
3101 fp = fopen(filename,
"w");
3103 NSLOG(netsurf, INFO,
"Failed to open file '%s' for writing",
3148 const char *host_str;
3149 char *path_query = NULL;
3152 unsigned int port_int;
3169 assert(path_query != NULL);
3179 host_str = lwc_string_data(host);
3180 lwc_string_unref(host);
3182 }
else if (lwc_string_isequal(
scheme, corestring_lwc_file, &match) ==
3183 lwc_error_ok && match ==
true) {
3184 host_str =
"localhost";
3187 lwc_string_unref(
scheme);
3196 port_int = atoi(lwc_string_data(
port));
3197 lwc_string_unref(
port);
3217 lwc_string_unref(
scheme);
3239 if (title != NULL) {
3240 temp = strdup(title);
3322 return (
const struct url_data *) u;
3347 char *realm_alloc, *auth_alloc;
3367 if (!strcmp(space->
realm, realm) &&
3369 &match) == lwc_error_ok &&
3375 if (space != NULL) {
3378 space->
auth = strdup(auth);
3382 realm_alloc = strdup(realm);
3383 auth_alloc = strdup(auth);
3385 if (!space_alloc || !realm_alloc || !auth_alloc) {
3394 space->
realm = realm_alloc;
3395 space->
auth = auth_alloc;
3421 for (p_cur = p; p_cur != NULL; p_top = p_cur, p_cur = p_cur->
parent) {
3430 if (realm != NULL) {
3437 space = space->
next) {
3439 lwc_string_isequal(space->
scheme,
3507 time_t now = time(NULL);
3509 uint32_t max_age = 0;
3518 lwc_string_unref(host);
3520 }
else if (lwc_string_length(host) == 0) {
3522 lwc_string_unref(host);
3526 lwc_string_unref(host);
3562 }
else if ((time_t) (now + max_age) > h->
hsts.
expires) {
3578 time_t now = time(NULL);
3586 lwc_string_unref(host);
3588 }
else if (lwc_string_length(host) == 0) {
3590 lwc_string_unref(host);
3594 lwc_string_unref(host);
3640 const char *slash, *scheme_sep;
3644 assert(prefix && callback);
3647 scheme_sep = strstr(prefix,
"://");
3649 prefix = scheme_sep + 3;
3651 slash = strchr(prefix,
'/');
3657 snprintf(host,
sizeof host,
"%.*s",
3658 (
int) (slash - prefix), prefix);
3662 int len = slash - prefix;
3664 if (len <= 3 || strncasecmp(host,
"www.", 4) != 0) {
3665 snprintf(buf,
sizeof buf,
"www.%s", host);
3682 int len = strlen(prefix);
3688 if (len <= 3 || strncasecmp(prefix,
"www.", 4) != 0) {
3690 snprintf(buf,
sizeof buf,
"www.%s", prefix);
3736 const char *cur = header, *end;
3737 lwc_string *
path, *host, *scheme;
3741 assert(url && header);
3748 if (scheme == NULL) {
3755 lwc_string_unref(scheme);
3762 lwc_string_unref(
path);
3763 lwc_string_unref(scheme);
3774 if (rhost == NULL) {
3779 if (lwc_string_isequal(host, rhost, &match) == lwc_error_ok &&
3784 const char *host_data = lwc_string_data(host);
3785 const char *rhost_data = lwc_string_data(rhost);
3791 lwc_string_unref(rhost);
3816 hptr = host_data + lwc_string_length(host) - 1;
3817 rptr = rhost_data + lwc_string_length(rhost) - 1;
3820 while (hptr >= host_data && rptr >= rhost_data) {
3832 while (*hptr !=
'\0' && *hptr !=
'.')
3836 if (*hptr ==
'\0' ||
3837 (dot = strchr(hptr + 1,
'.')) == NULL ||
3838 *(dot + 1) ==
'\0') {
3839 lwc_string_unref(rhost);
3844 lwc_string_unref(rhost);
3847 end = cur + strlen(cur) - 2 ;
3872 len = strlen(c->
path);
3873 if (len > lwc_string_length(
path) ||
3874 strncmp(c->
path, lwc_string_data(
path),
3886 suffix = nspsl_getpublicsuffix(dot);
3887 if (suffix == NULL) {
3888 NSLOG(netsurf, INFO,
3889 "domain %s was a public suffix domain", dot);
3895 dot = strchr(c->
domain + 1,
'.');
3896 if (!dot || *(dot + 1) ==
'\0') {
3904 if (strcasecmp(lwc_string_data(host), c->
domain) != 0) {
3920 assert(c->
domain[0] ==
'.');
3929 hlen = lwc_string_length(host);
3930 dlen = strlen(c->
domain);
3932 if (hlen <= dlen && hlen != dlen - 1) {
3938 if (hlen == dlen - 1) {
3945 if (strcasecmp(lwc_string_data(host) + (hlen - dlen),
3977 }
while (cur < end);
3979 lwc_string_unref(host);
3980 lwc_string_unref(
path);
3981 lwc_string_unref(scheme);
3987 lwc_string_unref(host);
3988 lwc_string_unref(
path);
3989 lwc_string_unref(scheme);
4001 lwc_string *path_lwc;
4005 int matched_cookies_size = 20;
4006 int ret_alloc = 4096, ret_used = 1;
4014 assert(url != NULL);
4027 matched_cookies = malloc(matched_cookies_size *
4029 if (!matched_cookies)
4032#define GROW_MATCHED_COOKIES \
4034 if (count == matched_cookies_size) { \
4035 struct cookie_internal_data **temp; \
4036 temp = realloc(matched_cookies, \
4037 (matched_cookies_size + 20) * \
4038 sizeof(struct cookie_internal_data *)); \
4040 if (temp == NULL) { \
4042 free(matched_cookies); \
4046 matched_cookies = temp; \
4047 matched_cookies_size += 20; \
4051 ret = malloc(ret_alloc);
4053 free(matched_cookies);
4060 if (path_lwc == NULL) {
4062 free(matched_cookies);
4065 path = lwc_string_data(path_lwc);
4066 lwc_string_unref(path_lwc);
4084 if (c->
secure && lwc_string_isequal(
4086 corestring_lwc_https,
4097 matched_cookies[
count++] = c;
4124 if (c->
secure && lwc_string_isequal(
4126 corestring_lwc_https,
4133 matched_cookies[
count++] = c;
4170 corestring_lwc_https,
4177 matched_cookies[
count++] = c;
4204 if (c->
secure && lwc_string_isequal(scheme,
4205 corestring_lwc_https,
4211 matched_cookies[
count++] = c;
4227 free(matched_cookies);
4233 sprintf(ret,
"$Version=%d",
version);
4234 ret_used = strlen(ret) + 1;
4237 for (i = 0; i <
count; i++) {
4239 &ret_used, &ret_alloc, &ret)) {
4241 free(matched_cookies);
4248 memmove(ret, ret + 2, ret_used - 2);
4254 char *temp = realloc(ret, ret_used);
4257 free(matched_cookies);
4264 free(matched_cookies);
4268#undef GROW_MATCHED_COOKIES
4288 fp = fopen(filename,
"r");
4293 for (; *p && *p != '\t'; p++) \
4296 NSLOG(netsurf, INFO, "Overran input"); \
4303 for (; *p && *p == '\t'; p++) \
4306 NSLOG(netsurf, INFO, "Overran input"); \
4311 while (fgets(s,
sizeof s, fp)) {
4312 char *p = s, *end = 0,
4315 int version, domain_specified, path_specified,
4320 if(s[0] == 0 || s[0] ==
'#')
4324 s[strlen(s) - 1] =
'\0';
4325 end = s + strlen(s);
4330 if (strncasecmp(s,
"Version:", 8) == 0) {
4335 NSLOG(netsurf, INFO,
4336 "Unsupported Cookie file version");
4377 for (; *p && *p ==
'\t'; p++)
4409 if (c->
domain[0] !=
'.') {
4410 lwc_string *scheme_lwc = NULL;
4411 nsurl *url_nsurl = NULL;
4413 assert(scheme[0] !=
'u');
4426 lwc_string_unref(scheme_lwc);
4430 lwc_string_unref(scheme_lwc);
4456 fp = fopen(filename,
"w");
4460 fprintf(fp,
"# NetSurf cookies file.\n"
4462 "# Lines starting with a '#' are comments, "
4463 "blank lines are ignored.\n"
4465 "# All lines prior to \"Version:\t%d\" are discarded.\n"
4467 "# Version\tDomain\tDomain from Set-Cookie\tPath\t"
4468 "Path from Set-Cookie\tSecure\tHTTP-Only\tExpires\tLast used\t"
4469 "No destroy\tName\tValue\tValue was quoted\tScheme\t"
4471 cookie_file_version);
4472 fprintf(fp,
"Version:\t%d\n", cookie_file_version);
Helpers for ASCII string handling.
static char ascii_to_lower(char c)
Convert an upper case character to lower case.
static bool ascii_is_alpha(char c)
Test whether a character is alphabetical (upper or lower case).
static bool ascii_is_digit(char c)
Test whether a character is a decimal digit.
struct bloom_filter * bloom_create(size_t size)
Create a new bloom filter.
void bloom_destroy(struct bloom_filter *b)
Destroy a previously-created bloom filter.
bool bloom_search_hash(struct bloom_filter *b, uint32_t hash)
Search the filter for the given hash value, assuming it was added by bloom_insert_hash().
void bloom_insert_hash(struct bloom_filter *b, uint32_t hash)
Insert a given hash value into the filter, should you already have one to hand.
static uint32_t count(const http_directive *list, lwc_string *key)
char * strndup(const char *s, size_t n)
Duplicate up to n characters of a string.
Content handling interface.
content_type
The type of a content.
cookie_version
Version of cookie.
bool cookie_manager_add(const struct cookie_data *data)
Add/update a cookie to the viewer.
void cookie_manager_remove(const struct cookie_data *data)
Remove a cookie from viewer.
Cookie Manager (interface).
Useful interned string pointers (interface).
nserror
Enumeration of error codes.
@ NSERROR_SAVE_FAILED
Failed to save data.
@ NSERROR_NOT_FOUND
Requested item not found.
@ NSERROR_NEED_DATA
More data needed.
@ NSERROR_INVALID
Invalid data.
@ NSERROR_NOMEM
Memory exhaustion.
static struct directory * root
HTTP header parsing functions.
Generic bitmap handling interface.
internet structures and defines
int inet_aton(const char *cp, struct in_addr *inp)
int inet_pton(int af, const char *src, void *dst)
#define NSLOG(catname, level, logmsg, args...)
NetSurf URL handling (interface).
nserror nsurl_create(const char *const url_s, nsurl **url)
Create a NetSurf URL object from a URL string.
nserror nsurl_defragment(const nsurl *url, nsurl **no_frag)
Create a NetSurf URL object without a fragment from a NetSurf URL.
void nsurl_unref(nsurl *url)
Drop a reference to a NetSurf URL object.
uint32_t nsurl_hash(const nsurl *url)
Get a URL's hash value.
nserror nsurl_get(const nsurl *url, nsurl_component parts, char **url_s, size_t *url_l)
Get URL (section) as a string, from a NetSurf URL object.
const char * nsurl_access(const nsurl *url)
Access a NetSurf URL object as a string.
lwc_string * nsurl_get_component(const nsurl *url, nsurl_component part)
Get part of a URL as a lwc_string, from a NetSurf URL object.
struct nsurl nsurl
NetSurf URL object.
nserror http_parse_strict_transport_security(const char *header_value, http_strict_transport_security **result)
Parse an HTTP Strict-Transport-Security header value.
void http_strict_transport_security_destroy(http_strict_transport_security *victim)
Destroy a strict transport security object.
bool http_strict_transport_security_include_subdomains(http_strict_transport_security *sts)
Get the value of a strict transport security's includeSubDomains flag.
uint32_t http_strict_transport_security_max_age(http_strict_transport_security *sts)
Get the value of a strict transport security's max-age.
Interface to utility string handling.
const struct cookie_data * next
Next in list.
time_t expires
Expiry timestamp, or -1 for session.
struct cookie_internal_data * prev
Previous in list.
enum cookie_version version
Specification compliance.
time_t last_used
Last used time.
struct cookie_internal_data * next
Next in list.
bool http_only
Only expose to HTTP(S) requests.
bool path_from_set
Path came from Set-Cookie: header.
char * comment
Cookie comment.
bool domain_from_set
Domain came from Set-Cookie: header.
bool no_destroy
Never destroy this cookie, unless it's expired.
bool value_was_quoted
Value was quoted in Set-Cookie:
bool secure
Only send for HTTPS requests.
char * value
Cookie value.
struct host_part * parent
Parent host part.
struct host_part * prev
Previous sibling.
struct host_part * children
Child host parts.
char * part
Part of host string.
struct path_data paths
Known paths on this host.
struct host_part * next
Next sibling.
bool permit_invalid_certs
Allow access to SSL protected resources on this host without verifying certificate authenticity.
struct prot_space_data * prot_space
Linked list of all known proctection spaces known for this host and all its schems and ports.
time_t expires
Expiry time.
bool include_sub_domains
Whether to include subdomains.
Representation of a Strict-Transport-Security.
bool persistent
This entry should persist.
struct url_internal_data urld
URL data for resource.
char * segment
Path segment for this node.
unsigned int frag_cnt
Number of entries in path_data::fragment.
struct path_data * last
Last child.
char ** fragment
Array of fragments.
const struct prot_space_data * prot_space
Protection space to which this resource belongs too.
struct path_data * next
Next sibling.
struct cookie_internal_data * cookies
Cookies associated with resource.
struct cookie_internal_data * cookies_end
Last cookie in list.
struct path_data * children
Child path segments.
struct path_data * prev
Previous sibling.
lwc_string * scheme
URL scheme for data.
unsigned int port
Port number for data.
struct path_data * parent
Parent path segment.
struct prot_space_data * next
Next sibling.
char * auth
Authentication details for this protection space in form username:password.
char * realm
Protection realm.
unsigned int port
Port number of canonical hostname of this protection space.
lwc_string * scheme
URL scheme of canonical hostname of this protection space.
unsigned int level
Node level.
struct search_node * left
Left subtree.
struct search_node * right
Right subtree.
const struct host_part * data
Host tree entry.
content_type type
Type of resource.
char * title
Resource title.
time_t last_visit
Last visit time.
unsigned int visits
Visit count.
int nsc_sntimet(char *str, size_t size, time_t *timep)
Write the time in seconds since epoch to a buffer.
nserror nsc_strntimet(const char *str, size_t size, time_t *timep)
Converts a date string to a number of seconds since epoch.
nserror nsc_snptimet(const char *str, size_t size, time_t *timep)
Parse time in seconds since epoc.
Interface to time operations.
Interface to URL parsing and joining operations.
void urldb_set_cert_permissions(nsurl *url, bool permit)
Set certificate verification permissions.
#define MAXIMUM_URL_LENGTH
static void urldb_destroy_path_tree(struct path_data *root)
Destroy a path tree.
void urldb_destroy(void)
Destroy urldb.
static struct search_node * urldb_search_skew(struct search_node *root)
Rotate a subtree right.
static struct host_part * urldb_add_host_node(const char *part, struct host_part *parent)
Add a host node to the tree.
static struct search_node ** urldb_get_search_tree_direct(const char *host)
Get the search tree for a particular host.
static struct path_data * urldb_add_path_node(lwc_string *scheme, unsigned int port, const char *segment, lwc_string *fragment, struct path_data *parent)
Add a path node to the tree.
#define GROW_MATCHED_COOKIES
static void urldb_save_cookie_hosts(FILE *fp, struct host_part *parent)
Save a host subtree's cookies.
static struct search_node empty
static struct search_node * urldb_search_insert_internal(struct search_node *root, struct search_node *n)
Insert node into search tree.
static struct search_node * urldb_get_search_tree(const char *host)
Get the search tree for a particular host.
static void urldb_destroy_search_tree(struct search_node *root)
Destroy a search tree.
#define NUM_SEARCH_TREES
Search trees - one per letter + 1 for IPs + 1 for Everything Else.
static void urldb_free_cookie(struct cookie_internal_data *c)
Free a cookie.
nserror urldb_set_url_persistence(nsurl *url, bool persist)
Set the cross-session persistence of the entry for an URL.
static bool urldb_insert_cookie(struct cookie_internal_data *c, lwc_string *scheme, nsurl *url)
Insert a cookie into the database.
static void urldb_write_paths(const struct path_data *parent, const char *host, FILE *fp, char **path, int *path_alloc, int *path_used, time_t expiry)
Write paths associated with a host.
bool urldb_set_cookie(const char *header, nsurl *url, nsurl *referer)
Parse Set-Cookie header and insert cookie(s) into database.
static bool urldb_iterate_entries_host(struct search_node *parent, bool(*url_callback)(nsurl *url, const struct url_data *data), bool(*cookie_callback)(const struct cookie_data *data))
Host data iterator (internal)
static int urldb_search_match_prefix(const struct host_part *a, const char *b)
Compare host_part with prefix.
static nserror urldb_write_timet(FILE *fp, time_t val)
write a time_t to a file portably
void urldb_iterate_cookies(bool(*callback)(const struct cookie_data *data))
bool urldb_get_hsts_enabled(struct nsurl *url)
Determine if HSTS policy is enabled for an URL.
#define URL_FILE_VERSION
Current URL database file version.
void urldb_save_cookies(const char *filename)
Save persistent cookies to file.
nsurl * urldb_get_url(nsurl *url)
Extract an URL from the db.
static struct path_data * urldb_add_path_fragment(struct path_data *segment, lwc_string *fragment)
Add a fragment to a path segment.
nserror urldb_set_url_title(nsurl *url, const char *title)
Set an URL's title string, replacing any existing one.
nserror urldb_save(const char *filename)
Export the current database to file.
bool urldb_add_url(nsurl *url)
Insert an URL into the database.
static struct search_node * urldb_search_split(struct search_node *root)
Rotate a node left, increasing the parent's level.
static void urldb_dump_search(struct search_node *parent, int depth)
Dump search tree.
void urldb_dump(void)
Dump URL database to stderr.
static bool urldb_iterate_partial_path(const struct path_data *parent, const char *prefix, bool(*callback)(nsurl *url, const struct url_data *data))
Partial path iterator (internal)
static void urldb_delete_cookie_paths(const char *domain, const char *path, const char *name, struct path_data *parent)
deletes paths from a cookie.
#define MIN_COOKIE_FILE_VERSION
Minimum cookie database file version.
void urldb_set_auth_details(nsurl *url, const char *realm, const char *auth)
Set authentication data for an URL.
#define BLOOM_SIZE
Size of url filter.
bool urldb_get_cert_permissions(nsurl *url)
Retrieve certificate verification permissions from database.
static int loaded_cookie_file_version
loaded cookie file version
bool urldb_set_hsts_policy(struct nsurl *url, const char *header)
Set HSTS policy for an URL.
static bool urldb_iterate_entries_path(const struct path_data *parent, bool(*url_callback)(nsurl *url, const struct url_data *data), bool(*cookie_callback)(const struct cookie_data *data))
Path data iterator (internal)
static void urldb_dump_paths(struct path_data *parent)
Dump URL database paths to stderr.
static void urldb_delete_cookie_hosts(const char *domain, const char *path, const char *name, struct host_part *parent)
Deletes cookie hosts and their assoicated paths.
nserror urldb_load(const char *filename)
Import an URL database from file, replacing any existing database.
static struct path_data * urldb_add_path(lwc_string *scheme, unsigned int port, const struct host_part *host, char *path_query, lwc_string *fragment, nsurl *url)
Add a path to the database, creating any intermediate entries.
void urldb_iterate_entries(bool(*callback)(nsurl *url, const struct url_data *data))
static struct host_part db_root
Root database handle.
static struct path_data * urldb_find_url(nsurl *url)
Find an URL in the database.
static struct host_part * urldb_add_host(const char *host)
Add a host to the database, creating any intermediate entries.
const struct url_data * urldb_get_url_data(nsurl *url)
Find data for an URL.
static void urldb_destroy_prot_space(struct prot_space_data *space)
Destroy protection space data.
const char * urldb_get_auth_details(nsurl *url, const char *realm)
Look up authentication details in database.
static void urldb_destroy_path_node_content(struct path_data *node)
Destroy the contents of a path node.
static void urldb_save_search_tree(struct search_node *parent, FILE *fp)
Save a search (sub)tree.
static const struct host_part * urldb_search_find(struct search_node *root, const char *host)
Find a node in a search tree.
static struct search_node * search_trees[NUM_SEARCH_TREES]
nserror urldb_update_url_visit_data(nsurl *url)
Update an URL's visit data.
static void urldb_destroy_host_tree(struct host_part *root)
Destroy a host tree.
static struct bloom_filter * url_bloom
filter for url presence in database
static int urldb_add_path_fragment_cmp(const void *a, const void *b)
Fragment comparator callback for qsort.
void urldb_reset_url_visit_data(nsurl *url)
Reset an URL's visit statistics.
static struct search_node * urldb_search_insert(struct search_node *root, const struct host_part *data)
Insert a node into the search tree.
#define MIN_URL_FILE_VERSION
Minimum URL database file version.
static bool urldb_concat_cookie(struct cookie_internal_data *c, int version, int *used, int *alloc, char **buf)
Concatenate a cookie into the provided buffer.
static int urldb_search_match_host(const struct host_part *a, const struct host_part *b)
Compare a pair of host parts.
nserror urldb_set_url_content_type(nsurl *url, content_type type)
Set an URL's content type.
static struct cookie_internal_data * urldb_parse_cookie(nsurl *url, const char **cookie)
Parse a cookie.
void urldb_delete_cookie(const char *domain, const char *path, const char *name)
Delete a cookie.
static void urldb_dump_hosts(struct host_part *parent)
Dump URL database hosts to stderr.
static void urldb_destroy_cookie(struct cookie_internal_data *c)
Destroy a cookie node.
static void urldb_count_urls(const struct path_data *root, time_t expiry, unsigned int *count)
Count number of URLs associated with a host.
char * urldb_get_cookie(nsurl *url, bool include_http_only)
Retrieve cookies for an URL.
static bool urldb_parse_avpair(struct cookie_internal_data *c, char *n, char *v, bool was_quoted)
Parse a cookie avpair.
static struct path_data * urldb_match_path(const struct path_data *parent, const char *path, lwc_string *scheme, unsigned short port)
Match a path string.
static void urldb_save_cookie_paths(FILE *fp, struct path_data *parent)
Save a path subtree's cookies.
void urldb_iterate_partial(const char *prefix, bool(*callback)(nsurl *url, const struct url_data *data))
void urldb_load_cookies(const char *filename)
Load a cookie file into the database.
static bool urldb_iterate_partial_host(struct search_node *root, const char *prefix, bool(*callback)(nsurl *url, const struct url_data *data))
Partial host iterator (internal)
#define COOKIE_FILE_VERSION
Current cookie database file version.
static bool urldb__host_is_ip_address(const char *host)
Check whether a host string is an IP address.
static int urldb_search_match_string(const struct host_part *a, const char *b)
Compare host part with a string.
Unified URL information database internal interface.
Option reading and saving interface.
#define nsoption_int(OPTION)
Get the value of an integer option.
Interface to a number of general purpose functionality.
static nserror path(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, const float transform[6])
Plots a path.