Dillo v3.2.0-151-g90488cbf
Loading...
Searching...
No Matches
url.c
Go to the documentation of this file.
1/*
2 * File: url.c
3 *
4 * Copyright (C) 2001-2009 Jorge Arellano Cid <jcid@dillo.org>
5 * Copyright (C) 2024 Rodrigo Arias Mallo <rodarima@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 */
12
20/*
21 * Regular Expression as given in RFC3986 for URL parsing.
22 *
23 * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
24 * 12 3 4 5 6 7 8 9
25 *
26 * scheme = $2
27 * authority = $4
28 * path = $5
29 * query = $7
30 * fragment = $9
31 *
32 *
33 * RFC-2396 BNF:
34 *
35 * absoluteURI = scheme ":" (hier_part | opaque_part)
36 * hier_part = (net_path | abs_path) ["?" query]
37 * net_path = "//" authority[abs_path]
38 * abs_path = "/" path_segments
39 *
40 * Notes:
41 * - "undefined" means "preceding separator does not appear".
42 * - path is never "undefined" though it may be "empty".
43 */
44
45#include <stdlib.h>
46#include <string.h>
47
48#include "url.h"
49#include "hsts.h"
50#include "msg.h"
51#include "dlib/dlib.h" /* dIsascii */
52
53static const char *HEX = "0123456789ABCDEF";
54
55/* URL-field compare methods */
56#define URL_STR_FIELD_CMP(s1,s2) \
57 (s1) && (s2) ? strcmp(s1,s2) : !(s1) && !(s2) ? 0 : (s1) ? 1 : -1
58#define URL_STR_FIELD_I_CMP(s1,s2) \
59 (s1) && (s2) ? dStrAsciiCasecmp(s1,s2) : !(s1) && !(s2) ? 0 : (s1) ? 1 : -1
60
65char *a_Url_str(const DilloUrl *u)
66{
67 /* Internal url handling IS transparent to the caller */
68 DilloUrl *url = (DilloUrl *) u;
69
70 dReturn_val_if_fail (url != NULL, NULL);
71
72 if (!url->url_string) {
73 url->url_string = dStr_sized_new(60);
75 url->url_string, "%s%s%s%s%s%s%s%s%s%s",
76 url->scheme ? url->scheme : "",
77 url->scheme ? ":" : "",
78 url->authority ? "//" : "",
79 url->authority ? url->authority : "",
80 // (url->path && url->path[0] != '/' && url->authority) ? "/" : "",
81 (url->authority && (!url->path || *url->path != '/')) ? "/" : "",
82 url->path ? url->path : "",
83 url->query ? "?" : "",
84 url->query ? url->query : "",
85 url->fragment ? "#" : "",
86 url->fragment ? url->fragment : "");
87 }
88
89 return url->url_string->str;
90}
91
97const char *a_Url_hostname(const DilloUrl *u)
98{
99 char *p;
100 /* Internal url handling IS transparent to the caller */
101 DilloUrl *url = (DilloUrl *) u;
102
103 if (!url->hostname && url->authority) {
104 if (url->authority[0] == '[' && (p = strchr(url->authority, ']'))) {
105 /* numeric ipv6 address, strip the brackets */
106 url->hostname = dStrndup(url->authority + 1,
107 (uint_t)(p - url->authority - 1));
108 if ((p = strchr(p, ':'))) {
109 url->port = strtol(p + 1, NULL, 10);
110 }
111 } else {
112 /* numeric ipv4 or hostname */
113 if ((p = strchr(url->authority, ':'))) {
114 url->port = strtol(p + 1, NULL, 10);
115 url->hostname = dStrndup(url->authority,
116 (uint_t)(p - url->authority));
117 } else {
118 url->hostname = url->authority;
119 }
120 }
121 }
122
123 if (!url->port) {
124 if (!dStrAsciiCasecmp(url->scheme, "http"))
125 url->port = URL_HTTP_PORT;
126 else if (!dStrAsciiCasecmp(url->scheme, "https"))
127 url->port = URL_HTTPS_PORT;
128 }
129 return url->hostname;
130}
131
136static DilloUrl *Url_object_new(const char *uri_str)
137{
138 DilloUrl *url;
139 char *s, *p;
140
141 dReturn_val_if_fail (uri_str != NULL, NULL);
142
143 url = dNew0(DilloUrl, 1);
144
145 /* url->buffer is given a little extra room in case HSTS needs to transform
146 * a URL string ending in ":80" to ":443".
147 */
148 int len = strlen(uri_str)+2;
149 s = dNew(char, len);
150 memcpy(s, uri_str, len-1);
151 s = dStrstrip(s);
152
153 /* remove leading & trailing space from buffer */
154 url->buffer = s;
155
156 p = strpbrk(s, ":/?#");
157 if (p && p[0] == ':' && p > s) { /* scheme */
158 *p = 0;
159 url->scheme = s;
160 s = ++p;
161 }
162 /* p = strpbrk(s, "/"); */
163 if (p == s && p[0] == '/' && p[1] == '/') { /* authority */
164 s = p + 2;
165 p = strpbrk(s, "/?#");
166 if (p) {
167 memmove(s - 2, s, (size_t)MAX(p - s, 1));
168 url->authority = s - 2;
169 p[-2] = 0;
170 s = p;
171 } else if (*s) {
172 url->authority = s;
173 return url;
174 }
175 }
176
177 p = strpbrk(s, "?#");
178 if (p) { /* path */
179 url->path = (p > s) ? s : NULL;
180 s = p;
181 } else if (*s) {
182 url->path = s;
183 return url;
184 }
185
186 p = strpbrk(s, "?#");
187 if (p && p[0] == '?') { /* query */
188 *p = 0;
189 s = p + 1;
190 url->query = s;
191 p = strpbrk(s, "#");
192 url->flags |= URL_Get;
193 }
194 if (p && p[0] == '#') { /* fragment */
195 *p = 0;
196 s = p + 1;
197 url->fragment = s;
198 }
199
200 return url;
201}
202
208{
209 if (url) {
210 if (url->url_string)
212 if (url->hostname != url->authority)
213 dFree((char *)url->hostname);
214 dFree((char *)url->buffer);
215 dStr_free(url->data, 1);
216 dFree(url);
217 }
218}
219
223static Dstr *Url_resolve_relative(const char *RelStr,
224 const char *BaseStr)
225{
226 char *p, *s, *e;
227 int i;
228 Dstr *SolvedUrl, *Path;
229 DilloUrl *RelUrl, *BaseUrl = NULL;
230
231 /* parse relative URL */
232 RelUrl = Url_object_new(RelStr);
233
234 if (RelUrl->scheme == NULL) {
235 /* only required when there's no <scheme> in RelStr */
236 BaseUrl = Url_object_new(BaseStr);
237 }
238
239 SolvedUrl = dStr_sized_new(64);
240 Path = dStr_sized_new(64);
241
242 /* path empty && scheme and authority undefined */
243 if (!RelUrl->path && !RelUrl->scheme && !RelUrl->authority) {
244 dStr_append(SolvedUrl, BaseStr);
245 if ((p = strchr(SolvedUrl->str, '#')))
246 dStr_truncate(SolvedUrl, p - SolvedUrl->str);
247 if (!BaseUrl->path)
248 dStr_append_c(SolvedUrl, '/');
249
250 if (RelUrl->query) { /* query */
251 if (BaseUrl->query)
252 dStr_truncate(SolvedUrl, BaseUrl->query - BaseUrl->buffer - 1);
253 dStr_append_c(SolvedUrl, '?');
254 dStr_append(SolvedUrl, RelUrl->query);
255 }
256 if (RelUrl->fragment) { /* fragment */
257 dStr_append_c(SolvedUrl, '#');
258 dStr_append(SolvedUrl, RelUrl->fragment);
259 }
260 goto done;
261
262 } else if (RelUrl->scheme) { /* scheme */
263 dStr_append(SolvedUrl, RelStr);
264 goto done;
265
266 } else if (RelUrl->authority) { /* authority */
267 // Set the Path buffer and goto "STEP 7";
268 if (RelUrl->path)
269 dStr_append(Path, RelUrl->path);
270
271 } else {
272 if (RelUrl->path && RelUrl->path[0] == '/') { /* absolute path */
273 ; /* Ignore BaseUrl path */
274 } else if (BaseUrl->path) { /* relative path */
275 dStr_append(Path, BaseUrl->path);
276 for (i = Path->len; --i >= 0 && Path->str[i] != '/'; ) ;
277 if (i >= 0 && Path->str[i] == '/')
278 dStr_truncate(Path, ++i);
279 }
280 if (RelUrl->path)
281 dStr_append(Path, RelUrl->path);
282
283 // erase "./"
284 while ((p=strstr(Path->str, "./")) &&
285 (p == Path->str || p[-1] == '/'))
286 dStr_erase(Path, p - Path->str, 2);
287 // erase last "."
288 if (Path->len && Path->str[Path->len - 1] == '.' &&
289 (Path->len == 1 || Path->str[Path->len - 2] == '/'))
290 dStr_truncate(Path, Path->len - 1);
291
292 // erase "<segment>/../" and "<segment>/.."
293 s = p = Path->str;
294 while ( (p = strstr(p, "/..")) != NULL ) {
295 if (p[3] == '/' || !p[3]) { // "/../" | "/.."
296 for (e = p + 3 ; p > s && p[-1] != '/'; --p) ;
297 dStr_erase(Path, p - Path->str, e - p + (p > s && *e != 0));
298 p -= (p > Path->str);
299 } else
300 p += 3;
301 }
302 }
303
304 /* STEP 7
305 */
306
307 /* scheme */
308 if (BaseUrl->scheme) {
309 dStr_append(SolvedUrl, BaseUrl->scheme);
310 dStr_append_c(SolvedUrl, ':');
311 }
312
313 /* authority */
314 if (RelUrl->authority) {
315 dStr_append(SolvedUrl, "//");
316 dStr_append(SolvedUrl, RelUrl->authority);
317 } else if (BaseUrl->authority) {
318 dStr_append(SolvedUrl, "//");
319 dStr_append(SolvedUrl, BaseUrl->authority);
320 }
321
322 /* path */
323 if ((RelUrl->authority || BaseUrl->authority) &&
324 ((Path->len == 0 && (RelUrl->query || RelUrl->fragment)) ||
325 (Path->len && Path->str[0] != '/')))
326 dStr_append_c(SolvedUrl, '/'); /* hack? */
327 dStr_append(SolvedUrl, Path->str);
328
329 /* query */
330 if (RelUrl->query) {
331 dStr_append_c(SolvedUrl, '?');
332 dStr_append(SolvedUrl, RelUrl->query);
333 }
334
335 /* fragment */
336 if (RelUrl->fragment) {
337 dStr_append_c(SolvedUrl, '#');
338 dStr_append(SolvedUrl, RelUrl->fragment);
339 }
340
341done:
342 dStr_free(Path, TRUE);
343 a_Url_free(RelUrl);
344 a_Url_free(BaseUrl);
345 return SolvedUrl;
346}
347
370DilloUrl* a_Url_new(const char *url_str, const char *base_url)
371{
372 DilloUrl *url;
373 char *urlstr = (char *)url_str; /* auxiliary variable, don't free */
374 char *p, *str1 = NULL, *str2 = NULL;
375 Dstr *SolvedUrl;
376 int i, n_ic, n_ic_spc;
377
378 if (!url_str)
379 return NULL;
380
381 /* Empty URL without base_url is not valid.
382 * They are used for action="" in forms with base_url set. */
383 if (url_str[0] == '\0' && base_url == NULL)
384 return NULL;
385
386 /* Count illegal characters (0x00-0x1F, 0x7F-0xFF and space) */
387 n_ic = n_ic_spc = 0;
388 for (p = (char*)url_str; *p; p++) {
389 n_ic_spc += (*p == ' ') ? 1 : 0;
390 n_ic += (*p != ' ' && *p > 0x1F && *p < 0x7F) ? 0 : 1;
391 }
392 if (n_ic) {
393 /* Encode illegal characters (they could also be stripped).
394 * There's no standard for illegal chars; we chose to encode. */
395 p = str1 = dNew(char, strlen(url_str) + 2*n_ic + 1);
396 for (i = 0; url_str[i]; ++i)
397 if (url_str[i] > 0x1F && url_str[i] < 0x7F && url_str[i] != ' ')
398 *p++ = url_str[i];
399 else {
400 *p++ = '%';
401 *p++ = HEX[(url_str[i] >> 4) & 15];
402 *p++ = HEX[url_str[i] & 15];
403 }
404 *p = 0;
405 urlstr = str1;
406 }
407
408 /* let's use a heuristic to set http: as default */
409 if (!base_url) {
410 base_url = "http:";
411 if (urlstr[0] != '/') {
412 p = strpbrk(urlstr, "/#?:");
413 if (!p || *p != ':')
414 urlstr = str2 = dStrconcat("//", urlstr, NULL);
415 } else if (urlstr[1] != '/')
416 urlstr = str2 = dStrconcat("/", urlstr, NULL);
417 }
418
419 /* Resolve the URL */
420 SolvedUrl = Url_resolve_relative(urlstr, base_url);
421 _MSG("SolvedUrl = %s\n", SolvedUrl->str);
422
423 /* Fill url data */
424 url = Url_object_new(SolvedUrl->str);
425 url->data = dStr_new("");
426 url->url_string = SolvedUrl;
427 url->illegal_chars = n_ic;
428 url->illegal_chars_spc = n_ic_spc;
429
430 dFree(str1);
431 dFree(str2);
432
433 bool_t switch_to_https = FALSE;
434
435 if (url->scheme && !dStrAsciiCasecmp(url->scheme, "http")) {
436 /*
437 * A site's HTTP Strict Transport Security policy may direct us to transform
438 * URLs like "http://en.wikipedia.org:80" to "https://en.wikipedia.org:443".
439 */
442 _MSG("url: HSTS transformation for %s.\n", url->url_string->str);
443 switch_to_https = TRUE;
444 } else if (prefs.http_force_https) {
445 _MSG("url: Force HTTPS transformation for %s.\n", url->url_string->str);
446 switch_to_https = TRUE;
447 }
448 }
449
450 if (switch_to_https) {
451 const char *const scheme = "https";
452
453 url->scheme = scheme;
454 if (url->port == URL_HTTP_PORT)
455 url->port = URL_HTTPS_PORT;
456
457 if (url->authority) {
458 int len = strlen(url->authority);
459
460 if (len >= 3 && !strcmp(url->authority + len-3, ":80")) {
461 strcpy((char *)url->authority + len-2, "443");
462 }
463 }
464
466 url->url_string = NULL;
467 }
468
469 return url;
470}
471
472
477{
478 DilloUrl *url;
479
480 url = Url_object_new(URL_STR_(ori));
481 dReturn_val_if_fail (url != NULL, NULL);
482
483 url->url_string = dStr_new(URL_STR(ori));
484 url->port = ori->port;
485 url->flags = ori->flags;
486 url->ismap_url_len = ori->ismap_url_len;
487 url->illegal_chars = ori->illegal_chars;
489 url->data = dStr_sized_new(URL_DATA(ori)->len);
490 dStr_append_l(url->data, URL_DATA(ori)->str, URL_DATA(ori)->len);
491 return url;
492}
493
505int a_Url_cmp(const DilloUrl *A, const DilloUrl *B)
506{
507 int st;
508
509 dReturn_val_if_fail(A && B, 1);
510
511 if (A == B ||
512 ((st = URL_STR_FIELD_I_CMP(A->authority, B->authority)) == 0 &&
513 (st = strcmp(A->path ? A->path + (*A->path == '/') : "",
514 B->path ? B->path + (*B->path == '/') : "")) == 0 &&
515 //(st = URL_STR_FIELD_CMP(A->path, B->path)) == 0 &&
516 (st = URL_STR_FIELD_CMP(A->query, B->query)) == 0 &&
517 (st = dStr_cmp(A->data, B->data)) == 0 &&
518 (st = URL_STR_FIELD_I_CMP(A->scheme, B->scheme)) == 0))
519 return 0;
520 return st;
521}
522
526void a_Url_set_flags(DilloUrl *u, int flags)
527{
528 if (u)
529 u->flags = flags;
530}
531
536{
537 if (u) {
538 dStr_free(u->data, 1);
539 u->data = *data;
540 *data = NULL;
541 }
542}
543
548void a_Url_set_ismap_coords(DilloUrl *u, char *coord_str)
549{
550 dReturn_if_fail (u && coord_str);
551
552 if (!u->ismap_url_len) {
553 /* Save base-url length (without coords) */
554 u->ismap_url_len = URL_STR_(u) ? u->url_string->len : 0;
555 }
556 if (u->url_string) {
558 dStr_append(u->url_string, coord_str);
559 u->query = u->url_string->str + u->ismap_url_len + 1;
560 }
561}
562
567static int Url_decode_hex_octet(const char *s)
568{
569 int hex_value;
570 char *tail, hex[3];
571
572 if (s && (hex[0] = s[0]) && (hex[1] = s[1])) {
573 hex[2] = 0;
574 hex_value = strtol(hex, &tail, 16);
575 if (tail - hex == 2)
576 return hex_value;
577 }
578 return -1;
579}
580
585char *a_Url_decode_hex_str(const char *str)
586{
587 char *new_str, *dest;
588 int i, val;
589
590 if (!str)
591 return NULL;
592
593 /* most cases won't have hex octets */
594 if (!strchr(str, '%'))
595 return dStrdup(str);
596
597 dest = new_str = dNew(char, strlen(str) + 1);
598
599 for (i = 0; str[i]; i++) {
600 *dest++ = (str[i] == '%' && (val = Url_decode_hex_octet(str+i+1)) >= 0) ?
601 i+=2, val : str[i];
602 }
603 *dest++ = 0;
604
605 new_str = dRealloc(new_str, sizeof(char) * (dest - new_str));
606 return new_str;
607}
608
619char *a_Url_encode_hex_str(const char *str)
620{
621 static const char *const verbatim = "-_.*";
622 char *newstr, *c;
623
624 if (!str)
625 return NULL;
626
627 newstr = dNew(char, 6*strlen(str)+1);
628
629 for (c = newstr; *str; str++)
630 if ((dIsalnum(*str) && dIsascii(*str)) || strchr(verbatim, *str))
631 *c++ = *str;
632 else if (*str == ' ')
633 *c++ = '+';
634 else if (*str == '\n') {
635 *c++ = '%';
636 *c++ = '0';
637 *c++ = 'D';
638 *c++ = '%';
639 *c++ = '0';
640 *c++ = 'A';
641 } else {
642 *c++ = '%';
643 *c++ = HEX[(*str >> 4) & 15];
644 *c++ = HEX[*str & 15];
645 }
646 *c = 0;
647
648 return newstr;
649}
650
651
657char *a_Url_string_strip_delimiters(const char *str)
658{
659 char *p, *new_str, *text;
660
661 new_str = text = dStrdup(str);
662
663 if (new_str) {
664 if (strncmp(new_str, "URL:", 4) == 0)
665 text += 4;
666 if (*text == '<')
667 text++;
668
669 for (p = new_str; *text; text++)
670 if (*text > 0x1F && *text < 0x7F && *text != ' ')
671 *p++ = *text;
672 if (p > new_str && p[-1] == '>')
673 --p;
674 *p = 0;
675 }
676 return new_str;
677}
678
682int a_Url_host_type(const char *host)
683{
684 uint_t len;
685
686 if (!host || !*host)
687 return URL_HOST_ERROR;
688
689 len = strlen(host);
690
691 if (len == strspn(host, "0123456789.")) {
692 return URL_HOST_IPV4;
693 }
694 if (strchr(host, ':') &&
695 (len == strspn(host, "0123456789abcdefABCDEF:."))) {
696 /* The precise format is shown in section 3.2.2 of rfc 3986 */
697 return URL_HOST_IPV6;
698 }
699 return URL_HOST_NAME;
700}
701
710static uint_t Url_host_public_internal_dots(const char *host)
711{
712 uint_t ret = 1;
713
714 if (host) {
715 int start, after, tld_len;
716
717 /* We may be able to trust the format of the host string more than
718 * I am here. Trailing dots and no dots are real possibilities, though.
719 */
720 after = strlen(host);
721 if (after > 0 && host[after - 1] == '.')
722 after--;
723 start = after;
724 while (start > 0 && host[start - 1] != '.')
725 start--;
726 tld_len = after - start;
727
728 if (tld_len > 0) {
729 /* These TLDs were chosen by examining the current publicsuffix list
730 * in July 2016 and picking out those where it was simplest for
731 * them to describe the situation by beginning with a "*.[tld]" rule
732 * or every rule was "[something].[tld]".
733 *
734 * TODO: Consider the old publicsuffix code again. This TLD list has
735 * shrunk and shrunk over the years, and has become a poorer and
736 * poorer approximation of administrative boundaries.
737 */
738 const char *const tlds[] = {"bd","bn","ck","cy","er","fj","fk",
739 "gu","jm","ke","kh","kw","mm","mz",
740 "ni","np","pg","ye","za","zw"};
741 uint_t i, tld_num = sizeof(tlds) / sizeof(tlds[0]);
742
743 for (i = 0; i < tld_num; i++) {
744 if (strlen(tlds[i]) == (uint_t) tld_len &&
745 !dStrnAsciiCasecmp(tlds[i], host + start, tld_len)) {
746 _MSG("TLD code matched %s\n", tlds[i]);
747 ret++;
748 break;
749 }
750 }
751 }
752 }
753 return ret;
754}
755
761static const char *Url_host_find_public_suffix(const char *host)
762{
763 const char *s;
764 uint_t dots;
765
766 if (a_Url_host_type(host) != URL_HOST_NAME)
767 return host;
768
769 s = host;
770
771 while (s[1])
772 s++;
773
774 if (s > host && *s == '.') {
775 /* don't want to deal with trailing dot */
776 s--;
777 }
778
780
781 /* With a proper host string, we should not be pointing to a dot now. */
782
783 while (s > host) {
784 if (s[-1] == '.') {
785 if (dots == 0)
786 break;
787 else
788 dots--;
789 }
790 s--;
791 }
792
793 _MSG("public suffix of %s is %s\n", host, s);
794 return s;
795}
796
798{
799 if (!u1 || !u2)
800 return FALSE;
801
804 ? FALSE : TRUE;
805}
#define _MSG(...)
Definition bookmarks.c:44
unsigned int uint_t
Definition d_size.h:20
unsigned char bool_t
Definition d_size.h:21
char * dStrconcat(const char *s1,...)
Concatenate a NULL-terminated list of strings.
Definition dlib.c:101
int dStr_cmp(Dstr *ds1, Dstr *ds2)
Compare two dStrs.
Definition dlib.c:477
void dFree(void *mem)
Definition dlib.c:67
int dStrAsciiCasecmp(const char *s1, const char *s2)
Definition dlib.c:202
char * dStrstrip(char *s)
Remove leading and trailing whitespace.
Definition dlib.c:121
void dStr_append(Dstr *ds, const char *s)
Append a C string to a Dstr.
Definition dlib.c:315
char * dStrdup(const char *s)
Definition dlib.c:76
Dstr * dStr_sized_new(int sz)
Create a new string with a given size.
Definition dlib.c:253
int dStrnAsciiCasecmp(const char *s1, const char *s2, size_t n)
Definition dlib.c:214
void dStr_erase(Dstr *ds, int pos_0, int len)
Erase a substring.
Definition dlib.c:387
void dStr_free(Dstr *ds, int all)
Free a dillo string.
Definition dlib.c:336
void dStr_append_l(Dstr *ds, const char *s, int l)
Append a C string to a Dstr (providing length).
Definition dlib.c:307
void dStr_append_c(Dstr *ds, int c)
Append one character.
Definition dlib.c:348
char * dStrndup(const char *s, size_t sz)
Definition dlib.c:87
void dStr_sprintf(Dstr *ds, const char *format,...)
Printf-like function.
Definition dlib.c:449
Dstr * dStr_new(const char *s)
Create a new string.
Definition dlib.c:324
void * dRealloc(void *mem, size_t size)
Definition dlib.c:52
void dStr_truncate(Dstr *ds, int len)
Truncate a Dstr to be 'len' bytes long.
Definition dlib.c:367
#define dReturn_if_fail(expr)
Definition dlib.h:101
#define dNew0(type, count)
Definition dlib.h:80
#define dReturn_val_if_fail(expr, val)
Definition dlib.h:105
static int dIsascii(unsigned char c)
Definition dlib.h:57
static int dIsalnum(unsigned char c)
Definition dlib.h:47
#define TRUE
Definition dlib.h:36
#define FALSE
Definition dlib.h:32
#define MAX(a, b)
Definition dlib.h:40
#define dNew(type, count)
Definition dlib.h:78
bool_t a_Hsts_require_https(const char *host)
Definition hsts.c:270
DilloPrefs prefs
Global Data.
Definition prefs.c:33
bool_t http_strict_transport_security
Definition prefs.h:106
bool_t http_force_https
Definition prefs.h:107
Definition url.h:88
int illegal_chars_spc
number of illegal space chars
Definition url.h:102
const char * buffer
Definition url.h:90
Dstr * data
POST.
Definition url.h:99
int ismap_url_len
Used by server side image maps.
Definition url.h:100
const char * fragment
Definition url.h:95
const char * query
Definition url.h:94
int illegal_chars
number of illegal chars
Definition url.h:101
const char * path
Definition url.h:93
Dstr * url_string
Definition url.h:89
const char * hostname
Definition url.h:96
int port
Definition url.h:97
const char * scheme
Definition url.h:91
const char * authority
Definition url.h:92
int flags
Definition url.h:98
Definition dlib.h:131
Dstr_char_t * str
Definition dlib.h:134
int len
Definition dlib.h:133
char * a_Url_string_strip_delimiters(const char *str)
RFC-3986 suggests this stripping when "importing" URLs from other media.
Definition url.c:657
static uint_t Url_host_public_internal_dots(const char *host)
How many internal dots are in the public portion of this hostname?.
Definition url.c:710
static const char * Url_host_find_public_suffix(const char *host)
Given a URL host string, return the portion that is public.
Definition url.c:761
void a_Url_set_flags(DilloUrl *u, int flags)
Set DilloUrl flags.
Definition url.c:526
char * a_Url_encode_hex_str(const char *str)
Urlencode 'str'.
Definition url.c:619
int a_Url_cmp(const DilloUrl *A, const DilloUrl *B)
Compare two Url's to check if they're the same, or which one is bigger.
Definition url.c:505
static int Url_decode_hex_octet(const char *s)
Given an hex octet (e.g., e3, 2F, 20), return the corresponding character if the octet is valid,...
Definition url.c:567
void a_Url_free(DilloUrl *url)
Free a DilloUrl.
Definition url.c:207
bool_t a_Url_same_organization(const DilloUrl *u1, const DilloUrl *u2)
Definition url.c:797
void a_Url_set_ismap_coords(DilloUrl *u, char *coord_str)
Set DilloUrl ismap coordinates.
Definition url.c:548
static const char * HEX
Definition url.c:53
void a_Url_set_data(DilloUrl *u, Dstr **data)
Set DilloUrl data (like POST info, etc.)
Definition url.c:535
static Dstr * Url_resolve_relative(const char *RelStr, const char *BaseStr)
Resolve the URL as RFC3986 suggests.
Definition url.c:223
const char * a_Url_hostname(const DilloUrl *u)
Return the hostname as a string.
Definition url.c:97
#define URL_STR_FIELD_I_CMP(s1, s2)
Definition url.c:58
char * a_Url_decode_hex_str(const char *str)
Parse possible hexadecimal octets in the URI path.
Definition url.c:585
DilloUrl * a_Url_new(const char *url_str, const char *base_url)
Transform (and resolve) an URL string into the respective DilloURL.
Definition url.c:370
char * a_Url_str(const DilloUrl *u)
Return the url as a string.
Definition url.c:65
static DilloUrl * Url_object_new(const char *uri_str)
Create a DilloUrl object and initialize it.
Definition url.c:136
#define URL_STR_FIELD_CMP(s1, s2)
Definition url.c:56
int a_Url_host_type(const char *host)
What type of host is this?
Definition url.c:682
DilloUrl * a_Url_dup(const DilloUrl *ori)
Duplicate a Url structure.
Definition url.c:476
Parse and normalize all URL's inside Dillo.
#define URL_HOST_ERROR
Definition url.h:23
#define URL_HOST_NAME
Definition url.h:24
#define URL_DATA(u)
Definition url.h:77
#define URL_HOST_IPV4
Definition url.h:25
#define URL_STR(u)
Definition url.h:76
#define URL_HTTP_PORT
Definition url.h:19
#define URL_STR_(u)
Definition url.h:55
#define URL_HOST_IPV6
Definition url.h:26
#define URL_Get
Definition url.h:32
#define URL_HTTPS_PORT
Definition url.h:20
#define URL_HOST(u)
Definition url.h:75