Git init
[profile/ivi/libsoup2.4.git] / tests / uri-parsing.c
1 #include <config.h>
2
3 #include <ctype.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8
9 #include "libsoup/soup-uri.h"
10
11 #include "test-utils.h"
12
13 static struct {
14         const char *uri_string, *result;
15 } abs_tests[] = {
16         { "foo:", "foo:" },
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&param=value",
31           "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue&param=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"},
34         { "http://space/%20",
35           "http://space/%20" },
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" },
40
41         /* From RFC 2732 */
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]/" },
56
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" },
67
68         /* Bug 594405; 0-length is different from not-present */
69         { "http://host/path?", "http://host/path?" },
70         { "http://host/path#", "http://host/path#" },
71
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" }
80 };
81 static int num_abs_tests = G_N_ELEMENTS(abs_tests);
82
83 /* From RFC 3986. */
84 static const char *base = "http://a/b/c/d;p?q";
85 static struct {
86         const char *uri_string, *result;
87 } rel_tests[] = {
88         { "g:h", "g:h" },
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" },
129
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.
135          */
136         { "http:g", NULL }
137 };
138 static int num_rel_tests = G_N_ELEMENTS(rel_tests);
139
140 static struct {
141         const char *one, *two;
142 } eq_tests[] = {
143         { "example://a/b/c/%7Bfoo%7D", "eXAMPLE://a/./b/../b/%63/%7Bfoo%7D" },
144         { "http://example.com", "http://example.com/" },
145         /* From RFC 2616 */
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" },
149 };
150 static int num_eq_tests = G_N_ELEMENTS(eq_tests);
151
152 static gboolean
153 do_uri (SoupURI *base_uri, const char *base_str,
154         const char *in_uri, const char *out_uri)
155 {
156         SoupURI *uri;
157         char *uri_string;
158
159         if (base_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);
163         } else {
164                 debug_printf (1, "<%s> => <%s>? ", in_uri,
165                               out_uri ? out_uri : "ERR");
166                 uri = soup_uri_new (in_uri);
167         }
168
169         if (!uri) {
170                 if (out_uri) {
171                         debug_printf (1, "ERR\n  Could not parse %s\n", in_uri);
172                         return FALSE;
173                 } else {
174                         debug_printf (1, "OK\n");
175                         return TRUE;
176                 }
177         }
178
179         uri_string = soup_uri_to_string (uri, FALSE);
180         soup_uri_free (uri);
181
182         if (!out_uri) {
183                 debug_printf (1, "ERR\n  Got %s\n", uri_string);
184                 return FALSE;
185         }
186
187         if (strcmp (uri_string, out_uri) != 0) {
188                 debug_printf (1, "NO\n  Unparses to <%s>\n", uri_string);
189                 g_free (uri_string);
190                 return FALSE;
191         }
192         g_free (uri_string);
193
194         debug_printf (1, "OK\n");
195         return TRUE;
196 }
197
198 int
199 main (int argc, char **argv)
200 {
201         SoupURI *base_uri, *uri1, *uri2;
202         char *uri_string;
203         int i;
204
205         test_init (argc, argv, NULL);
206
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))
211                         errors++;
212         }
213
214         debug_printf (1, "\nRelative URI parsing\n");
215         base_uri = soup_uri_new (base);
216         if (!base_uri) {
217                 fprintf (stderr, "Could not parse %s!\n", base);
218                 exit (1);
219         }
220
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",
224                          base, uri_string);
225                 errors++;
226         }
227         g_free (uri_string);
228
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))
232                         errors++;
233         }
234         soup_uri_free (base_uri);
235
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");
243                 else {
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);
248                         errors++;
249                 }
250                 soup_uri_free (uri1);
251                 soup_uri_free (uri2);
252         }
253
254         test_cleanup ();
255         return errors != 0;
256 }