9 #include "libsoup/soup-uri.h"
11 #include "test-utils.h"
14 const char *uri_string, *result;
17 { "file:/dev/null", "file:/dev/null" },
18 { "file:///dev/null", "file:///dev/null" },
19 { "ftp://user@host/path", "ftp://user@host/path" },
20 { "ftp://user@host:9999/path", "ftp://user@host:9999/path" },
21 { "ftp://user:password@host/path", "ftp://user@host/path" },
22 { "ftp://user:password@host:9999/path", "ftp://user@host:9999/path" },
23 { "ftp://user:password@host", "ftp://user@host" },
24 { "http://us%65r@host", "http://user@host/" },
25 { "http://us%40r@host", "http://us%40r@host/" },
26 { "http://us%3ar@host", "http://us%3Ar@host/" },
27 { "http://us%2fr@host", "http://us%2Fr@host/" },
28 { "http://us%3fr@host", "http://us%3Fr@host/" },
29 { "http://host?query", "http://host/?query" },
30 { "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value",
31 "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value" },
32 { "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F",
33 "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F"},
36 { "http://delims/%3C%3E%23%25%22",
37 "http://delims/%3C%3E%23%25%22" },
38 { "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60",
39 "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60" },
42 { "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html",
43 "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]/index.html" },
44 { "http://[1080:0:0:0:8:800:200C:417A]/index.html",
45 "http://[1080:0:0:0:8:800:200C:417A]/index.html" },
46 { "http://[3ffe:2a00:100:7031::1]",
47 "http://[3ffe:2a00:100:7031::1]/" },
48 { "http://[1080::8:800:200C:417A]/foo",
49 "http://[1080::8:800:200C:417A]/foo" },
50 { "http://[::192.9.5.5]/ipng",
51 "http://[::192.9.5.5]/ipng" },
52 { "http://[::FFFF:129.144.52.38]:80/index.html",
53 "http://[::FFFF:129.144.52.38]/index.html" },
54 { "http://[2010:836B:4179::836B:4179]",
55 "http://[2010:836B:4179::836B:4179]/" },
57 /* Try to recover certain kinds of invalid URIs */
58 { "http://host/path with spaces",
59 "http://host/path%20with%20spaces" },
60 { " http://host/path", "http://host/path" },
61 { "http://host/path ", "http://host/path" },
62 { "http://host ", "http://host/" },
63 { "http://host:999 ", "http://host:999/" },
64 { "http://host/pa\nth", "http://host/path" },
65 { "http:\r\n//host/path", "http://host/path" },
66 { "http://\thost/path", "http://host/path" },
68 /* Bug 594405; 0-length is different from not-present */
69 { "http://host/path?", "http://host/path?" },
70 { "http://host/path#", "http://host/path#" },
72 /* Bug 590524; ignore badly-%-encoding */
73 { "http://host/path%", "http://host/path%" },
74 { "http://h%ost/path", "http://h%25ost/path" },
75 { "http://host/path%%", "http://host/path%%" },
76 { "http://host/path%%%", "http://host/path%%%" },
77 { "http://host/path%/x/", "http://host/path%/x/" },
78 { "http://host/path%0x/", "http://host/path%0x/" },
79 { "http://host/path%ax", "http://host/path%ax" }
81 static int num_abs_tests = G_N_ELEMENTS(abs_tests);
84 static const char *base = "http://a/b/c/d;p?q";
86 const char *uri_string, *result;
89 { "g", "http://a/b/c/g" },
90 { "./g", "http://a/b/c/g" },
91 { "g/", "http://a/b/c/g/" },
92 { "/g", "http://a/g" },
93 { "//g", "http://g/" },
94 { "?y", "http://a/b/c/d;p?y" },
95 { "g?y", "http://a/b/c/g?y" },
96 { "#s", "http://a/b/c/d;p?q#s" },
97 { "g#s", "http://a/b/c/g#s" },
98 { "g?y#s", "http://a/b/c/g?y#s" },
99 { ";x", "http://a/b/c/;x" },
100 { "g;x", "http://a/b/c/g;x" },
101 { "g;x?y#s", "http://a/b/c/g;x?y#s" },
102 { ".", "http://a/b/c/" },
103 { "./", "http://a/b/c/" },
104 { "..", "http://a/b/" },
105 { "../", "http://a/b/" },
106 { "../g", "http://a/b/g" },
107 { "../..", "http://a/" },
108 { "../../", "http://a/" },
109 { "../../g", "http://a/g" },
110 { "", "http://a/b/c/d;p?q" },
111 { "../../../g", "http://a/g" },
112 { "../../../../g", "http://a/g" },
113 { "/./g", "http://a/g" },
114 { "/../g", "http://a/g" },
115 { "g.", "http://a/b/c/g." },
116 { ".g", "http://a/b/c/.g" },
117 { "g..", "http://a/b/c/g.." },
118 { "..g", "http://a/b/c/..g" },
119 { "./../g", "http://a/b/g" },
120 { "./g/.", "http://a/b/c/g/" },
121 { "g/./h", "http://a/b/c/g/h" },
122 { "g/../h", "http://a/b/c/h" },
123 { "g;x=1/./y", "http://a/b/c/g;x=1/y" },
124 { "g;x=1/../y", "http://a/b/c/y" },
125 { "g?y/./x", "http://a/b/c/g?y/./x" },
126 { "g?y/../x", "http://a/b/c/g?y/../x" },
127 { "g#s/./x", "http://a/b/c/g#s/./x" },
128 { "g#s/../x", "http://a/b/c/g#s/../x" },
130 /* RFC 3986 notes that some old parsers will parse this as
131 * a relative URL ("http://a/b/c/g"), but it should be
132 * interpreted as absolute. libsoup should parse it
133 * correctly as being absolute, but then reject it since it's
134 * an http URL with no host.
138 static int num_rel_tests = G_N_ELEMENTS(rel_tests);
141 const char *one, *two;
143 { "example://a/b/c/%7Bfoo%7D", "eXAMPLE://a/./b/../b/%63/%7Bfoo%7D" },
144 { "http://example.com", "http://example.com/" },
146 { "http://abc.com:80/~smith/home.html", "http://abc.com:80/~smith/home.html" },
147 { "http://abc.com:80/~smith/home.html", "http://ABC.com/%7Esmith/home.html" },
148 { "http://abc.com:80/~smith/home.html", "http://ABC.com:/%7esmith/home.html" },
150 static int num_eq_tests = G_N_ELEMENTS(eq_tests);
153 do_uri (SoupURI *base_uri, const char *base_str,
154 const char *in_uri, const char *out_uri)
160 debug_printf (1, "<%s> + <%s> = <%s>? ", base_str, in_uri,
161 out_uri ? out_uri : "ERR");
162 uri = soup_uri_new_with_base (base_uri, in_uri);
164 debug_printf (1, "<%s> => <%s>? ", in_uri,
165 out_uri ? out_uri : "ERR");
166 uri = soup_uri_new (in_uri);
171 debug_printf (1, "ERR\n Could not parse %s\n", in_uri);
174 debug_printf (1, "OK\n");
179 uri_string = soup_uri_to_string (uri, FALSE);
183 debug_printf (1, "ERR\n Got %s\n", uri_string);
187 if (strcmp (uri_string, out_uri) != 0) {
188 debug_printf (1, "NO\n Unparses to <%s>\n", uri_string);
194 debug_printf (1, "OK\n");
199 main (int argc, char **argv)
201 SoupURI *base_uri, *uri1, *uri2;
205 test_init (argc, argv, NULL);
207 debug_printf (1, "Absolute URI parsing\n");
208 for (i = 0; i < num_abs_tests; i++) {
209 if (!do_uri (NULL, NULL, abs_tests[i].uri_string,
210 abs_tests[i].result))
214 debug_printf (1, "\nRelative URI parsing\n");
215 base_uri = soup_uri_new (base);
217 fprintf (stderr, "Could not parse %s!\n", base);
221 uri_string = soup_uri_to_string (base_uri, FALSE);
222 if (strcmp (uri_string, base) != 0) {
223 fprintf (stderr, "URI <%s> unparses to <%s>\n",
229 for (i = 0; i < num_rel_tests; i++) {
230 if (!do_uri (base_uri, base, rel_tests[i].uri_string,
231 rel_tests[i].result))
234 soup_uri_free (base_uri);
236 debug_printf (1, "\nURI equality testing\n");
237 for (i = 0; i < num_eq_tests; i++) {
238 uri1 = soup_uri_new (eq_tests[i].one);
239 uri2 = soup_uri_new (eq_tests[i].two);
240 debug_printf (1, "<%s> == <%s>? ", eq_tests[i].one, eq_tests[i].two);
241 if (soup_uri_equal (uri1, uri2))
242 debug_printf (1, "OK\n");
244 debug_printf (1, "NO\n");
245 debug_printf (1, "%s : %s : %s\n%s : %s : %s\n",
246 uri1->scheme, uri1->host, uri1->path,
247 uri2->scheme, uri2->host, uri2->path);
250 soup_uri_free (uri1);
251 soup_uri_free (uri2);