1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 * SPDX-License-Identifier: curl
22 *
23 ***************************************************************************/
24
25 /*
26 * Note:
27 *
28 * Since the URL parser by default only accepts schemes that *this instance*
29 * of libcurl supports, make sure that the test1560 file lists all the schemes
30 * that this test will assume to be present!
31 */
32
33 #include "test.h"
34 #if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
35 #define USE_IDN
36 #endif
37
38 #include "testutil.h"
39 #include "warnless.h"
40 #include "memdebug.h" /* LAST include file */
41
42 struct part {
43 CURLUPart part;
44 const char *name;
45 };
46
47
checkparts(CURLU *u, const char *in, const char *wanted, unsigned int getflags)48 static int checkparts(CURLU *u, const char *in, const char *wanted,
49 unsigned int getflags)
50 {
51 int i;
52 CURLUcode rc;
53 char buf[256];
54 char *bufp = &buf[0];
55 size_t len = sizeof(buf);
56 struct part parts[] = {
57 {CURLUPART_SCHEME, "scheme"},
58 {CURLUPART_USER, "user"},
59 {CURLUPART_PASSWORD, "password"},
60 {CURLUPART_OPTIONS, "options"},
61 {CURLUPART_HOST, "host"},
62 {CURLUPART_PORT, "port"},
63 {CURLUPART_PATH, "path"},
64 {CURLUPART_QUERY, "query"},
65 {CURLUPART_FRAGMENT, "fragment"},
66 {CURLUPART_URL, NULL}
67 };
68 memset(buf, 0, sizeof(buf));
69
70 for(i = 0; parts[i].name; i++) {
71 char *p = NULL;
72 size_t n;
73 rc = curl_url_get(u, parts[i].part, &p, getflags);
74 if(!rc && p) {
75 msnprintf(bufp, len, "%s%s", buf[0]?" | ":"", p);
76 }
77 else
78 msnprintf(bufp, len, "%s[%d]", buf[0]?" | ":"", (int)rc);
79
80 n = strlen(bufp);
81 bufp += n;
82 len -= n;
83 curl_free(p);
84 }
85 if(strcmp(buf, wanted)) {
86 fprintf(stderr, "in: %s\nwanted: %s\ngot: %s\n", in, wanted, buf);
87 return 1;
88 }
89 return 0;
90 }
91
92 struct redircase {
93 const char *in;
94 const char *set;
95 const char *out;
96 unsigned int urlflags;
97 unsigned int setflags;
98 CURLUcode ucode;
99 };
100
101 struct setcase {
102 const char *in;
103 const char *set;
104 const char *out;
105 unsigned int urlflags;
106 unsigned int setflags;
107 CURLUcode ucode; /* for the main URL set */
108 CURLUcode pcode; /* for updating parts */
109 };
110
111 struct setgetcase {
112 const char *in;
113 const char *set;
114 const char *out;
115 unsigned int urlflags; /* for setting the URL */
116 unsigned int setflags; /* for updating parts */
117 unsigned int getflags; /* for getting parts */
118 CURLUcode pcode; /* for updating parts */
119 };
120
121 struct testcase {
122 const char *in;
123 const char *out;
124 unsigned int urlflags;
125 unsigned int getflags;
126 CURLUcode ucode;
127 };
128
129 struct urltestcase {
130 const char *in;
131 const char *out;
132 unsigned int urlflags; /* pass to curl_url() */
133 unsigned int getflags; /* pass to curl_url_get() */
134 CURLUcode ucode;
135 };
136
137 struct querycase {
138 const char *in;
139 const char *q;
140 const char *out;
141 unsigned int urlflags; /* pass to curl_url() */
142 unsigned int qflags; /* pass to curl_url_get() */
143 CURLUcode ucode;
144 };
145
146 struct clearurlcase {
147 CURLUPart part;
148 const char *in;
149 const char *out;
150 CURLUcode ucode;
151 };
152
153 static const struct testcase get_parts_list[] ={
154 {"https://curl.se/# ",
155 "https | [11] | [12] | [13] | curl.se | [15] | / | [16] | %20%20",
156 CURLU_URLENCODE|CURLU_ALLOW_SPACE, 0, CURLUE_OK},
157 {"", "", 0, 0, CURLUE_MALFORMED_INPUT},
158 {" ", "", 0, 0, CURLUE_MALFORMED_INPUT},
159 {"1h://example.net", "", 0, 0, CURLUE_BAD_SCHEME},
160 {"..://example.net", "", 0, 0, CURLUE_BAD_SCHEME},
161 {"-ht://example.net", "", 0, 0, CURLUE_BAD_SCHEME},
162 {"+ftp://example.net", "", 0, 0, CURLUE_BAD_SCHEME},
163 {"hej.hej://example.net",
164 "hej.hej | [11] | [12] | [13] | example.net | [15] | / | [16] | [17]",
165 CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
166 {"ht-tp://example.net",
167 "ht-tp | [11] | [12] | [13] | example.net | [15] | / | [16] | [17]",
168 CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
169 {"ftp+more://example.net",
170 "ftp+more | [11] | [12] | [13] | example.net | [15] | / | [16] | [17]",
171 CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
172 {"f1337://example.net",
173 "f1337 | [11] | [12] | [13] | example.net | [15] | / | [16] | [17]",
174 CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
175 {"https://user@example.net?hello# space ",
176 "https | user | [12] | [13] | example.net | [15] | / | hello | %20space%20",
177 CURLU_ALLOW_SPACE|CURLU_URLENCODE, 0, CURLUE_OK},
178 {"https://test%test", "", 0, 0, CURLUE_BAD_HOSTNAME},
179 {"https://example.com%252f%40@example.net",
180 "https | example.com%2f@ | [12] | [13] | example.net | [15] | / "
181 "| [16] | [17]",
182 0, CURLU_URLDECODE, CURLUE_OK },
183 #ifdef USE_IDN
184 {"https://räksmörgås.se",
185 "https | [11] | [12] | [13] | xn--rksmrgs-5wao1o.se | "
186 "[15] | / | [16] | [17]", 0, CURLU_PUNYCODE, CURLUE_OK},
187 {"https://xn--rksmrgs-5wao1o.se",
188 "https | [11] | [12] | [13] | räksmörgås.se | "
189 "[15] | / | [16] | [17]", 0, CURLU_PUNY2IDN, CURLUE_OK},
190 #else
191 {"https://räksmörgås.se",
192 "https | [11] | [12] | [13] | [30] | [15] | / | [16] | [17]",
193 0, CURLU_PUNYCODE, CURLUE_OK},
194 #endif
195 /* https://ℂᵤⓇℒ。 */
196 {"https://"
197 "%e2%84%82%e1%b5%a4%e2%93%87%e2%84%92%e3%80%82%f0%9d%90%92%f0%9f%84%b4",
198 "https | [11] | [12] | [13] | ℂᵤⓇℒ。 | [15] |"
199 " / | [16] | [17]",
200 0, 0, CURLUE_OK},
201 {"https://"
202 "%e2%84%82%e1%b5%a4%e2%93%87%e2%84%92%e3%80%82%f0%9d%90%92%f0%9f%84%b4",
203 "https | [11] | [12] | [13] | "
204 "%e2%84%82%e1%b5%a4%e2%93%87%e2%84%92%e3%80%82%f0%9d%90%92%f0%9f%84%b4 "
205 "| [15] | / | [16] | [17]",
206 0, CURLU_URLENCODE, CURLUE_OK},
207 {"https://"
208 "\xe2\x84\x82\xe1\xb5\xa4\xe2\x93\x87\xe2\x84\x92"
209 "\xe3\x80\x82\xf0\x9d\x90\x92\xf0\x9f\x84\xb4",
210 "https | [11] | [12] | [13] | "
211 "%e2%84%82%e1%b5%a4%e2%93%87%e2%84%92%e3%80%82%f0%9d%90%92%f0%9f%84%b4 "
212 "| [15] | / | [16] | [17]",
213 0, CURLU_URLENCODE, CURLUE_OK},
214 {"https://user@example.net?he l lo",
215 "https | user | [12] | [13] | example.net | [15] | / | he+l+lo | [17]",
216 CURLU_ALLOW_SPACE, CURLU_URLENCODE, CURLUE_OK},
217 {"https://user@example.net?he l lo",
218 "https | user | [12] | [13] | example.net | [15] | / | he l lo | [17]",
219 CURLU_ALLOW_SPACE, 0, CURLUE_OK},
220 {"https://exam{}[]ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
221 {"https://exam{ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
222 {"https://exam}ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
223 {"https://exam]ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
224 {"https://exam\\ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
225 {"https://exam$ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
226 {"https://exam'ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
227 {"https://exam\"ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
228 {"https://exam^ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
229 {"https://exam`ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
230 {"https://exam*ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
231 {"https://exam<ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
232 {"https://exam>ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
233 {"https://exam=ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
234 {"https://exam;ple.net", "", 0, 0, CURLUE_BAD_HOSTNAME},
235 {"https://example,net", "", 0, 0, CURLUE_BAD_HOSTNAME},
236 {"https://example&net", "", 0, 0, CURLUE_BAD_HOSTNAME},
237 {"https://example+net", "", 0, 0, CURLUE_BAD_HOSTNAME},
238 {"https://example(net", "", 0, 0, CURLUE_BAD_HOSTNAME},
239 {"https://example)net", "", 0, 0, CURLUE_BAD_HOSTNAME},
240 {"https://example.net/}",
241 "https | [11] | [12] | [13] | example.net | [15] | /} | [16] | [17]",
242 0, 0, CURLUE_OK},
243
244 /* blank user is blank */
245 {"https://:password@example.net",
246 "https | | password | [13] | example.net | [15] | / | [16] | [17]",
247 0, 0, CURLUE_OK},
248 /* blank user + blank password */
249 {"https://:@example.net",
250 "https | | | [13] | example.net | [15] | / | [16] | [17]",
251 0, 0, CURLUE_OK},
252 /* user-only (no password) */
253 {"https://user@example.net",
254 "https | user | [12] | [13] | example.net | [15] | / | [16] | [17]",
255 0, 0, CURLUE_OK},
256 #ifdef USE_WEBSOCKETS
257 {"ws://example.com/color/?green",
258 "ws | [11] | [12] | [13] | example.com | [15] | /color/ | green |"
259 " [17]",
260 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
261 {"wss://example.com/color/?green",
262 "wss | [11] | [12] | [13] | example.com | [15] | /color/ | green |"
263 " [17]",
264 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
265 #endif
266
267 {"https://user:password@example.net/get?this=and#but frag then", "",
268 CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
269 {"https://user:password@example.net/get?this=and what", "",
270 CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
271 {"https://user:password@example.net/ge t?this=and-what", "",
272 CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
273 {"https://user:pass word@example.net/get?this=and-what", "",
274 CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
275 {"https://u ser:password@example.net/get?this=and-what", "",
276 CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
277 {"imap://user:pass;opt ion@server/path", "",
278 CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
279 /* no space allowed in scheme */
280 {"htt ps://user:password@example.net/get?this=and-what", "",
281 CURLU_NON_SUPPORT_SCHEME|CURLU_ALLOW_SPACE, 0, CURLUE_BAD_SCHEME},
282 {"https://user:password@example.net/get?this=and what",
283 "https | user | password | [13] | example.net | [15] | /get | "
284 "this=and what | [17]",
285 CURLU_ALLOW_SPACE, 0, CURLUE_OK},
286 {"https://user:password@example.net/ge t?this=and-what",
287 "https | user | password | [13] | example.net | [15] | /ge t | "
288 "this=and-what | [17]",
289 CURLU_ALLOW_SPACE, 0, CURLUE_OK},
290 {"https://user:pass word@example.net/get?this=and-what",
291 "https | user | pass word | [13] | example.net | [15] | /get | "
292 "this=and-what | [17]",
293 CURLU_ALLOW_SPACE, 0, CURLUE_OK},
294 {"https://u ser:password@example.net/get?this=and-what",
295 "https | u ser | password | [13] | example.net | [15] | /get | "
296 "this=and-what | [17]",
297 CURLU_ALLOW_SPACE, 0, CURLUE_OK},
298 {"https://user:password@example.net/ge t?this=and-what",
299 "https | user | password | [13] | example.net | [15] | /ge%20t | "
300 "this=and-what | [17]",
301 CURLU_ALLOW_SPACE | CURLU_URLENCODE, 0, CURLUE_OK},
302 {"[0:0:0:0:0:0:0:1]",
303 "http | [11] | [12] | [13] | [::1] | [15] | / | [16] | [17]",
304 CURLU_GUESS_SCHEME, 0, CURLUE_OK },
305 {"[::1]",
306 "http | [11] | [12] | [13] | [::1] | [15] | / | [16] | [17]",
307 CURLU_GUESS_SCHEME, 0, CURLUE_OK },
308 {"[::]",
309 "http | [11] | [12] | [13] | [::] | [15] | / | [16] | [17]",
310 CURLU_GUESS_SCHEME, 0, CURLUE_OK },
311 {"https://[::1]",
312 "https | [11] | [12] | [13] | [::1] | [15] | / | [16] | [17]",
313 0, 0, CURLUE_OK },
314 {"user:moo@ftp.example.com/color/#green?no-red",
315 "ftp | user | moo | [13] | ftp.example.com | [15] | /color/ | [16] | "
316 "green?no-red",
317 CURLU_GUESS_SCHEME, 0, CURLUE_OK },
318 {"ftp.user:moo@example.com/color/#green?no-red",
319 "http | ftp.user | moo | [13] | example.com | [15] | /color/ | [16] | "
320 "green?no-red",
321 CURLU_GUESS_SCHEME, 0, CURLUE_OK },
322 #ifdef _WIN32
323 {"file:/C:\\programs\\foo",
324 "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
325 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
326 {"file://C:\\programs\\foo",
327 "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
328 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
329 {"file:///C:\\programs\\foo",
330 "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
331 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
332 {"file://host.example.com/Share/path/to/file.txt",
333 "file | [11] | [12] | [13] | host.example.com | [15] | "
334 "//host.example.com/Share/path/to/file.txt | [16] | [17]",
335 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
336 #endif
337 {"https://example.com/color/#green?no-red",
338 "https | [11] | [12] | [13] | example.com | [15] | /color/ | [16] | "
339 "green?no-red",
340 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
341 {"https://example.com/color/#green#no-red",
342 "https | [11] | [12] | [13] | example.com | [15] | /color/ | [16] | "
343 "green#no-red",
344 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
345 {"https://example.com/color/?green#no-red",
346 "https | [11] | [12] | [13] | example.com | [15] | /color/ | green | "
347 "no-red",
348 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
349 {"https://example.com/#color/?green#no-red",
350 "https | [11] | [12] | [13] | example.com | [15] | / | [16] | "
351 "color/?green#no-red",
352 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
353 {"https://example.#com/color/?green#no-red",
354 "https | [11] | [12] | [13] | example. | [15] | / | [16] | "
355 "com/color/?green#no-red",
356 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
357 {"http://[ab.be:1]/x", "",
358 CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_IPV6},
359 {"http://[ab.be]/x", "",
360 CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_IPV6},
361 /* URL without host name */
362 {"http://a:b@/x", "",
363 CURLU_DEFAULT_SCHEME, 0, CURLUE_NO_HOST},
364 {"boing:80",
365 "https | [11] | [12] | [13] | boing | 80 | / | [16] | [17]",
366 CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME, 0, CURLUE_OK},
367 {"http://[fd00:a41::50]:8080",
368 "http | [11] | [12] | [13] | [fd00:a41::50] | 8080 | / | [16] | [17]",
369 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
370 {"http://[fd00:a41::50]/",
371 "http | [11] | [12] | [13] | [fd00:a41::50] | [15] | / | [16] | [17]",
372 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
373 {"http://[fd00:a41::50]",
374 "http | [11] | [12] | [13] | [fd00:a41::50] | [15] | / | [16] | [17]",
375 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
376 {"https://[::1%252]:1234",
377 "https | [11] | [12] | [13] | [::1] | 1234 | / | [16] | [17]",
378 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
379
380 /* here's "bad" zone id */
381 {"https://[fe80::20c:29ff:fe9c:409b%eth0]:1234",
382 "https | [11] | [12] | [13] | [fe80::20c:29ff:fe9c:409b] | 1234 "
383 "| / | [16] | [17]",
384 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
385 {"https://127.0.0.1:443",
386 "https | [11] | [12] | [13] | 127.0.0.1 | [15] | / | [16] | [17]",
387 0, CURLU_NO_DEFAULT_PORT, CURLUE_OK},
388 {"http://%3a:%3a@ex4mple/%3f+?+%3f+%23#+%23%3f%g7",
389 "http | : | : | [13] | ex4mple | [15] | /?+ | ? # | +#?%g7",
390 0, CURLU_URLDECODE, CURLUE_OK},
391 {"http://%3a:%3a@ex4mple/%3f?%3f%35#%35%3f%g7",
392 "http | %3a | %3a | [13] | ex4mple | [15] | /%3f | %3f%35 | %35%3f%g7",
393 0, 0, CURLUE_OK},
394 {"http://HO0_-st%41/",
395 "http | [11] | [12] | [13] | HO0_-stA | [15] | / | [16] | [17]",
396 0, 0, CURLUE_OK},
397 {"file://hello.html",
398 "",
399 0, 0, CURLUE_BAD_FILE_URL},
400 {"http://HO0_-st/",
401 "http | [11] | [12] | [13] | HO0_-st | [15] | / | [16] | [17]",
402 0, 0, CURLUE_OK},
403 {"imap://user:pass;option@server/path",
404 "imap | user | pass | option | server | [15] | /path | [16] | [17]",
405 0, 0, CURLUE_OK},
406 {"http://user:pass;option@server/path",
407 "http | user | pass;option | [13] | server | [15] | /path | [16] | [17]",
408 0, 0, CURLUE_OK},
409 {"file:/hello.html",
410 "file | [11] | [12] | [13] | [14] | [15] | /hello.html | [16] | [17]",
411 0, 0, CURLUE_OK},
412 {"file:/h",
413 "file | [11] | [12] | [13] | [14] | [15] | /h | [16] | [17]",
414 0, 0, CURLUE_OK},
415 {"file:/",
416 "file | [11] | [12] | [13] | [14] | [15] | | [16] | [17]",
417 0, 0, CURLUE_BAD_FILE_URL},
418 {"file://127.0.0.1/hello.html",
419 "file | [11] | [12] | [13] | [14] | [15] | /hello.html | [16] | [17]",
420 0, 0, CURLUE_OK},
421 {"file:////hello.html",
422 "file | [11] | [12] | [13] | [14] | [15] | //hello.html | [16] | [17]",
423 0, 0, CURLUE_OK},
424 {"file:///hello.html",
425 "file | [11] | [12] | [13] | [14] | [15] | /hello.html | [16] | [17]",
426 0, 0, CURLUE_OK},
427 {"https://127.0.0.1",
428 "https | [11] | [12] | [13] | 127.0.0.1 | 443 | / | [16] | [17]",
429 0, CURLU_DEFAULT_PORT, CURLUE_OK},
430 {"https://127.0.0.1",
431 "https | [11] | [12] | [13] | 127.0.0.1 | [15] | / | [16] | [17]",
432 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
433 {"https://[::1]:1234",
434 "https | [11] | [12] | [13] | [::1] | 1234 | / | [16] | [17]",
435 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
436 {"https://127abc.com",
437 "https | [11] | [12] | [13] | 127abc.com | [15] | / | [16] | [17]",
438 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
439 {"https:// example.com?check", "",
440 CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
441 {"https://e x a m p l e.com?check", "",
442 CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
443 {"https://example.com?check",
444 "https | [11] | [12] | [13] | example.com | [15] | / | check | [17]",
445 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
446 {"https://example.com:65536",
447 "",
448 CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PORT_NUMBER},
449 {"https://example.com:-1#moo",
450 "",
451 CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PORT_NUMBER},
452 {"https://example.com:0#moo",
453 "https | [11] | [12] | [13] | example.com | 0 | / | "
454 "[16] | moo",
455 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
456 {"https://example.com:01#moo",
457 "https | [11] | [12] | [13] | example.com | 1 | / | "
458 "[16] | moo",
459 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
460 {"https://example.com:1#moo",
461 "https | [11] | [12] | [13] | example.com | 1 | / | "
462 "[16] | moo",
463 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
464 {"http://example.com#moo",
465 "http | [11] | [12] | [13] | example.com | [15] | / | "
466 "[16] | moo",
467 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
468 {"http://example.com",
469 "http | [11] | [12] | [13] | example.com | [15] | / | "
470 "[16] | [17]",
471 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
472 {"http://example.com/path/html",
473 "http | [11] | [12] | [13] | example.com | [15] | /path/html | "
474 "[16] | [17]",
475 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
476 {"http://example.com/path/html?query=name",
477 "http | [11] | [12] | [13] | example.com | [15] | /path/html | "
478 "query=name | [17]",
479 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
480 {"http://example.com/path/html?query=name#anchor",
481 "http | [11] | [12] | [13] | example.com | [15] | /path/html | "
482 "query=name | anchor",
483 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
484 {"http://example.com:1234/path/html?query=name#anchor",
485 "http | [11] | [12] | [13] | example.com | 1234 | /path/html | "
486 "query=name | anchor",
487 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
488 {"http:///user:password@example.com:1234/path/html?query=name#anchor",
489 "http | user | password | [13] | example.com | 1234 | /path/html | "
490 "query=name | anchor",
491 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
492 {"https://user:password@example.com:1234/path/html?query=name#anchor",
493 "https | user | password | [13] | example.com | 1234 | /path/html | "
494 "query=name | anchor",
495 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
496 {"http://user:password@example.com:1234/path/html?query=name#anchor",
497 "http | user | password | [13] | example.com | 1234 | /path/html | "
498 "query=name | anchor",
499 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
500 {"http:/user:password@example.com:1234/path/html?query=name#anchor",
501 "http | user | password | [13] | example.com | 1234 | /path/html | "
502 "query=name | anchor",
503 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
504 {"http:////user:password@example.com:1234/path/html?query=name#anchor",
505 "",
506 CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_SLASHES},
507 {NULL, NULL, 0, 0, CURLUE_OK},
508 };
509
510 static const struct urltestcase get_url_list[] = {
511 {"https://1.0x1000000", "https://1.0x1000000/", 0, 0, CURLUE_OK},
512 {"https://0x7f.1", "https://127.0.0.1/", 0, 0, CURLUE_OK},
513 {"https://1.2.3.256.com", "https://1.2.3.256.com/", 0, 0, CURLUE_OK},
514 {"https://10.com", "https://10.com/", 0, 0, CURLUE_OK},
515 {"https://1.2.com", "https://1.2.com/", 0, 0, CURLUE_OK},
516 {"https://1.2.3.com", "https://1.2.3.com/", 0, 0, CURLUE_OK},
517 {"https://1.2.com.99", "https://1.2.com.99/", 0, 0, CURLUE_OK},
518 {"https://[fe80::0000:20c:29ff:fe9c:409b]:80/moo",
519 "https://[fe80::20c:29ff:fe9c:409b]:80/moo",
520 0, 0, CURLUE_OK},
521 {"https://[fe80::020c:29ff:fe9c:409b]:80/moo",
522 "https://[fe80::20c:29ff:fe9c:409b]:80/moo",
523 0, 0, CURLUE_OK},
524 {"https://[fe80:0000:0000:0000:020c:29ff:fe9c:409b]:80/moo",
525 "https://[fe80::20c:29ff:fe9c:409b]:80/moo",
526 0, 0, CURLUE_OK},
527 {"https://[fe80:0:0:0:409b::]:80/moo",
528 "https://[fe80::409b:0:0:0]:80/moo",
529 0, 0, CURLUE_OK},
530 {"https://[::%25fakeit];80/moo",
531 "",
532 0, 0, CURLUE_BAD_PORT_NUMBER},
533 {"https://[fe80::20c:29ff:fe9c:409b]-80/moo",
534 "",
535 0, 0, CURLUE_BAD_PORT_NUMBER},
536 #ifdef USE_IDN
537 {"https://räksmörgås.se/path?q#frag",
538 "https://xn--rksmrgs-5wao1o.se/path?q#frag", 0, CURLU_PUNYCODE, CURLUE_OK},
539 #endif
540 /* unsupported schemes with no guessing enabled */
541 {"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIEhUTUw+PG1ldGEgY",
542 "", 0, 0, CURLUE_UNSUPPORTED_SCHEME},
543 {"d:anything-really", "", 0, 0, CURLUE_UNSUPPORTED_SCHEME},
544 {"about:config", "", 0, 0, CURLUE_UNSUPPORTED_SCHEME},
545 {"example://foo", "", 0, 0, CURLUE_UNSUPPORTED_SCHEME},
546 {"mailto:infobot@example.com?body=send%20current-issue", "", 0, 0,
547 CURLUE_UNSUPPORTED_SCHEME},
548 {"about:80", "https://about:80/", CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
549 /* percent encoded host names */
550 {"http://example.com%40127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
551 {"http://example.com%21127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
552 {"http://example.com%3f127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
553 {"http://example.com%23127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
554 {"http://example.com%3a127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
555 {"http://example.com%09127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
556 {"http://example.com%2F127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
557 {"https://%41", "https://A/", 0, 0, CURLUE_OK},
558 {"https://%20", "", 0, 0, CURLUE_BAD_HOSTNAME},
559 {"https://%41%0d", "", 0, 0, CURLUE_BAD_HOSTNAME},
560 {"https://%25", "", 0, 0, CURLUE_BAD_HOSTNAME},
561 {"https://_%c0_", "https://_\xC0_/", 0, 0, CURLUE_OK},
562 {"https://_%c0_", "https://_%C0_/", 0, CURLU_URLENCODE, CURLUE_OK},
563
564 /* IPv4 trickeries */
565 {"https://16843009", "https://1.1.1.1/", 0, 0, CURLUE_OK},
566 {"https://0177.1", "https://127.0.0.1/", 0, 0, CURLUE_OK},
567 {"https://0111.02.0x3", "https://73.2.0.3/", 0, 0, CURLUE_OK},
568 {"https://0111.02.0x3.", "https://0111.02.0x3./", 0, 0, CURLUE_OK},
569 {"https://0111.02.030", "https://73.2.0.24/", 0, 0, CURLUE_OK},
570 {"https://0111.02.030.", "https://0111.02.030./", 0, 0, CURLUE_OK},
571 {"https://0xff.0xff.0377.255", "https://255.255.255.255/", 0, 0, CURLUE_OK},
572 {"https://1.0xffffff", "https://1.255.255.255/", 0, 0, CURLUE_OK},
573 /* IPv4 numerical overflows or syntax errors will not normalize */
574 {"https://a127.0.0.1", "https://a127.0.0.1/", 0, 0, CURLUE_OK},
575 {"https://\xff.127.0.0.1", "https://%FF.127.0.0.1/", 0, CURLU_URLENCODE,
576 CURLUE_OK},
577 {"https://127.-0.0.1", "https://127.-0.0.1/", 0, 0, CURLUE_OK},
578 {"https://127.0. 1", "https://127.0.0.1/", 0, 0, CURLUE_MALFORMED_INPUT},
579 {"https://1.2.3.256", "https://1.2.3.256/", 0, 0, CURLUE_OK},
580 {"https://1.2.3.256.", "https://1.2.3.256./", 0, 0, CURLUE_OK},
581 {"https://1.2.3.4.5", "https://1.2.3.4.5/", 0, 0, CURLUE_OK},
582 {"https://1.2.0x100.3", "https://1.2.0x100.3/", 0, 0, CURLUE_OK},
583 {"https://4294967296", "https://4294967296/", 0, 0, CURLUE_OK},
584 {"https://123host", "https://123host/", 0, 0, CURLUE_OK},
585 /* 40 bytes scheme is the max allowed */
586 {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA://hostname/path",
587 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa://hostname/path",
588 CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
589 /* 41 bytes scheme is not allowed */
590 {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA://hostname/path",
591 "",
592 CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_BAD_SCHEME},
593 {"https://[fe80::20c:29ff:fe9c:409b%]:1234",
594 "",
595 0, 0, CURLUE_BAD_IPV6},
596 {"https://[fe80::20c:29ff:fe9c:409b%25]:1234",
597 "https://[fe80::20c:29ff:fe9c:409b%2525]:1234/",
598 0, 0, CURLUE_OK},
599 {"https://[fe80::20c:29ff:fe9c:409b%eth0]:1234",
600 "https://[fe80::20c:29ff:fe9c:409b%25eth0]:1234/",
601 0, 0, CURLUE_OK},
602 {"https://[::%25fakeit]/moo",
603 "https://[::%25fakeit]/moo",
604 0, 0, CURLUE_OK},
605 {"smtp.example.com/path/html",
606 "smtp://smtp.example.com/path/html",
607 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
608 {"https.example.com/path/html",
609 "http://https.example.com/path/html",
610 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
611 {"dict.example.com/path/html",
612 "dict://dict.example.com/path/html",
613 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
614 {"pop3.example.com/path/html",
615 "pop3://pop3.example.com/path/html",
616 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
617 {"ldap.example.com/path/html",
618 "ldap://ldap.example.com/path/html",
619 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
620 {"imap.example.com/path/html",
621 "imap://imap.example.com/path/html",
622 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
623 {"ftp.example.com/path/html",
624 "ftp://ftp.example.com/path/html",
625 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
626 {"example.com/path/html",
627 "http://example.com/path/html",
628 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
629 {"smtp.com/path/html",
630 "smtp://smtp.com/path/html",
631 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
632 {"dict.com/path/html",
633 "dict://dict.com/path/html",
634 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
635 {"pop3.com/path/html",
636 "pop3://pop3.com/path/html",
637 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
638 {"ldap.com/path/html",
639 "ldap://ldap.com/path/html",
640 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
641 {"imap.com/path/html",
642 "imap://imap.com/path/html",
643 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
644 {"ftp.com/path/html",
645 "ftp://ftp.com/path/html",
646 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
647 {"smtp/path/html",
648 "http://smtp/path/html",
649 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
650 {"dict/path/html",
651 "http://dict/path/html",
652 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
653 {"pop3/path/html",
654 "http://pop3/path/html",
655 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
656 {"ldap/path/html",
657 "http://ldap/path/html",
658 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
659 {"imap/path/html",
660 "http://imap/path/html",
661 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
662 {"ftp/path/html",
663 "http://ftp/path/html",
664 CURLU_GUESS_SCHEME, 0, CURLUE_OK},
665 {"HTTP://test/", "http://test/", 0, 0, CURLUE_OK},
666 {"http://HO0_-st..~./", "http://HO0_-st..~./", 0, 0, CURLUE_OK},
667 {"http:/@example.com: 123/", "", 0, 0, CURLUE_MALFORMED_INPUT},
668 {"http:/@example.com:123 /", "", 0, 0, CURLUE_MALFORMED_INPUT},
669 {"http:/@example.com:123a/", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
670 {"http://host/file\r", "", 0, 0, CURLUE_MALFORMED_INPUT},
671 {"http://host/file\n\x03", "", 0, 0, CURLUE_MALFORMED_INPUT},
672 {"htt\x02://host/file", "",
673 CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
674 {" http://host/file", "", 0, 0, CURLUE_MALFORMED_INPUT},
675 /* here the password ends at the semicolon and options is 'word' */
676 {"imap://user:pass;word@host/file",
677 "imap://user:pass;word@host/file",
678 0, 0, CURLUE_OK},
679 /* here the password has the semicolon */
680 {"http://user:pass;word@host/file",
681 "http://user:pass;word@host/file", 0, 0, CURLUE_OK},
682 {"file:///file.txt#moo", "file:///file.txt#moo", 0, 0, CURLUE_OK},
683 {"file:////file.txt", "file:////file.txt", 0, 0, CURLUE_OK},
684 {"file:///file.txt", "file:///file.txt", 0, 0, CURLUE_OK},
685 {"file:./", "file://", 0, 0, CURLUE_OK},
686 {"http://example.com/hello/../here",
687 "http://example.com/hello/../here",
688 CURLU_PATH_AS_IS, 0, CURLUE_OK},
689 {"http://example.com/hello/../here",
690 "http://example.com/here",
691 0, 0, CURLUE_OK},
692 {"http://example.com:80",
693 "http://example.com/",
694 0, CURLU_NO_DEFAULT_PORT, CURLUE_OK},
695 {"tp://example.com/path/html",
696 "",
697 0, 0, CURLUE_UNSUPPORTED_SCHEME},
698 {"http://hello:fool@example.com",
699 "",
700 CURLU_DISALLOW_USER, 0, CURLUE_USER_NOT_ALLOWED},
701 {"http:/@example.com:123",
702 "http://@example.com:123/",
703 0, 0, CURLUE_OK},
704 {"http:/:password@example.com",
705 "http://:password@example.com/",
706 0, 0, CURLUE_OK},
707 {"http://user@example.com?#",
708 "http://user@example.com/",
709 0, 0, CURLUE_OK},
710 {"http://user@example.com?",
711 "http://user@example.com/",
712 0, 0, CURLUE_OK},
713 {"http://user@example.com#anchor",
714 "http://user@example.com/#anchor",
715 0, 0, CURLUE_OK},
716 {"example.com/path/html",
717 "https://example.com/path/html",
718 CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
719 {"example.com/path/html",
720 "",
721 0, 0, CURLUE_BAD_SCHEME},
722 {"http://user:password@example.com:1234/path/html?query=name#anchor",
723 "http://user:password@example.com:1234/path/html?query=name#anchor",
724 0, 0, CURLUE_OK},
725 {"http://example.com:1234/path/html?query=name#anchor",
726 "http://example.com:1234/path/html?query=name#anchor",
727 0, 0, CURLUE_OK},
728 {"http://example.com/path/html?query=name#anchor",
729 "http://example.com/path/html?query=name#anchor",
730 0, 0, CURLUE_OK},
731 {"http://example.com/path/html?query=name",
732 "http://example.com/path/html?query=name",
733 0, 0, CURLUE_OK},
734 {"http://example.com/path/html",
735 "http://example.com/path/html",
736 0, 0, CURLUE_OK},
737 {"tp://example.com/path/html",
738 "tp://example.com/path/html",
739 CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
740 {"custom-scheme://host?expected=test-good",
741 "custom-scheme://host/?expected=test-good",
742 CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
743 {"custom-scheme://?expected=test-bad",
744 "",
745 CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_NO_HOST},
746 {"custom-scheme://?expected=test-new-good",
747 "custom-scheme:///?expected=test-new-good",
748 CURLU_NON_SUPPORT_SCHEME | CURLU_NO_AUTHORITY, 0, CURLUE_OK},
749 {"custom-scheme://host?expected=test-still-good",
750 "custom-scheme://host/?expected=test-still-good",
751 CURLU_NON_SUPPORT_SCHEME | CURLU_NO_AUTHORITY, 0, CURLUE_OK},
752 {NULL, NULL, 0, 0, CURLUE_OK}
753 };
754
checkurl(const char *org, const char *url, const char *out)755 static int checkurl(const char *org, const char *url, const char *out)
756 {
757 if(strcmp(out, url)) {
758 fprintf(stderr,
759 "Org: %s\n"
760 "Wanted: %s\n"
761 "Got : %s\n",
762 org, out, url);
763 return 1;
764 }
765 return 0;
766 }
767
768 /* 1. Set the URL
769 2. Set components
770 3. Extract all components (not URL)
771 */
772 static const struct setgetcase setget_parts_list[] = {
773 {"https://example.com",
774 "path=get,",
775 "https | [11] | [12] | [13] | example.com | [15] | /get | [16] | [17]",
776 0, 0, 0, CURLUE_OK},
777 {"https://example.com",
778 "path=/get,",
779 "https | [11] | [12] | [13] | example.com | [15] | /get | [16] | [17]",
780 0, 0, 0, CURLUE_OK},
781 {"https://example.com",
782 "path=g e t,",
783 "https | [11] | [12] | [13] | example.com | [15] | /g%20e%20t | "
784 "[16] | [17]",
785 0, CURLU_URLENCODE, 0, CURLUE_OK},
786 {NULL, NULL, NULL, 0, 0, 0, CURLUE_OK}
787 };
788
789 /* !checksrc! disable SPACEBEFORECOMMA 1 */
790 static const struct setcase set_parts_list[] = {
791 {"https://example.com/?param=value",
792 "query=\"\",",
793 "https://example.com/",
794 0, CURLU_APPENDQUERY | CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
795 {"https://example.com/",
796 "host=\"\",",
797 "https://example.com/",
798 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_BAD_HOSTNAME},
799 {"https://example.com/",
800 "host=\"\",",
801 "https://example.com/",
802 0, 0, CURLUE_OK, CURLUE_BAD_HOSTNAME},
803 {"https://example.com",
804 "path=get,",
805 "https://example.com/get",
806 0, 0, CURLUE_OK, CURLUE_OK},
807 {"https://example.com/",
808 "scheme=ftp+-.123,",
809 "ftp+-.123://example.com/",
810 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_OK},
811 {"https://example.com/",
812 "scheme=1234,",
813 "https://example.com/",
814 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
815 {"https://example.com/",
816 "scheme=1http,",
817 "https://example.com/",
818 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
819 {"https://example.com/",
820 "scheme=-ftp,",
821 "https://example.com/",
822 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
823 {"https://example.com/",
824 "scheme=+ftp,",
825 "https://example.com/",
826 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
827 {"https://example.com/",
828 "scheme=.ftp,",
829 "https://example.com/",
830 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
831 {"https://example.com/",
832 "host=example.com%2fmoo,",
833 "",
834 0, /* get */
835 0, /* set */
836 CURLUE_OK, CURLUE_BAD_HOSTNAME},
837 {"https://example.com/",
838 "host=http://fake,",
839 "",
840 0, /* get */
841 0, /* set */
842 CURLUE_OK, CURLUE_BAD_HOSTNAME},
843 {"https://example.com/",
844 "host=test%,",
845 "",
846 0, /* get */
847 0, /* set */
848 CURLUE_OK, CURLUE_BAD_HOSTNAME},
849 {"https://example.com/",
850 "host=te st,",
851 "",
852 0, /* get */
853 0, /* set */
854 CURLUE_OK, CURLUE_BAD_HOSTNAME},
855 {"https://example.com/",
856 "host=0xff,", /* '++' there's no automatic URL decode when setting this
857 part */
858 "https://0xff/",
859 0, /* get */
860 0, /* set */
861 CURLUE_OK, CURLUE_OK},
862
863 {"https://example.com/",
864 "query=Al2cO3tDkcDZ3EWE5Lh+LX8TPHs,", /* contains '+' */
865 "https://example.com/?Al2cO3tDkcDZ3EWE5Lh%2bLX8TPHs",
866 CURLU_URLDECODE, /* decode on get */
867 CURLU_URLENCODE, /* encode on set */
868 CURLUE_OK, CURLUE_OK},
869
870 {"https://example.com/",
871 /* Set a bad scheme *including* :// */
872 "scheme=https://,",
873 "https://example.com/",
874 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
875 {"https://example.com/",
876 /* Set a 41 bytes scheme. That's too long so the old scheme remains set. */
877 "scheme=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc,",
878 "https://example.com/",
879 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
880 {"https://example.com/",
881 /* set a 40 bytes scheme */
882 "scheme=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,",
883 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb://example.com/",
884 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_OK},
885 {"https://[::1%25fake]:1234/",
886 "zoneid=NULL,",
887 "https://[::1]:1234/",
888 0, 0, CURLUE_OK, CURLUE_OK},
889 {"https://host:1234/",
890 "port=NULL,",
891 "https://host/",
892 0, 0, CURLUE_OK, CURLUE_OK},
893 {"https://host:1234/",
894 "port=\"\",",
895 "https://host:1234/",
896 0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
897 {"https://host:1234/",
898 "port=56 78,",
899 "https://host:1234/",
900 0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
901 {"https://host:1234/",
902 "port=0,",
903 "https://host:1234/",
904 0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
905 {"https://host:1234/",
906 "port=65535,",
907 "https://host:65535/",
908 0, 0, CURLUE_OK, CURLUE_OK},
909 {"https://host:1234/",
910 "port=65536,",
911 "https://host:1234/",
912 0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
913 {"https://host/",
914 "path=%4A%4B%4C,",
915 "https://host/%4a%4b%4c",
916 0, 0, CURLUE_OK, CURLUE_OK},
917 {"https://host/mooo?q#f",
918 "path=NULL,query=NULL,fragment=NULL,",
919 "https://host/",
920 0, 0, CURLUE_OK, CURLUE_OK},
921 {"https://user:secret@host/",
922 "user=NULL,password=NULL,",
923 "https://host/",
924 0, 0, CURLUE_OK, CURLUE_OK},
925 {NULL,
926 "scheme=https,user= @:,host=foobar,",
927 "https://%20%20%20%40%3a@foobar/",
928 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
929 /* Setting a host name with spaces is not OK: */
930 {NULL,
931 "scheme=https,host= ,path= ,user= ,password= ,query= ,fragment= ,",
932 "[nothing]",
933 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_BAD_HOSTNAME},
934 {NULL,
935 "scheme=https,host=foobar,path=/this /path /is /here,",
936 "https://foobar/this%20/path%20/is%20/here",
937 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
938 {NULL,
939 "scheme=https,host=foobar,path=\xc3\xa4\xc3\xb6\xc3\xbc,",
940 "https://foobar/%c3%a4%c3%b6%c3%bc",
941 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
942 {"imap://user:secret;opt@host/",
943 "options=updated,scheme=imaps,password=p4ssw0rd,",
944 "imaps://user:p4ssw0rd;updated@host/",
945 0, 0, CURLUE_NO_HOST, CURLUE_OK},
946 {"imap://user:secret;optit@host/",
947 "scheme=https,",
948 "https://user:secret@host/",
949 0, 0, CURLUE_NO_HOST, CURLUE_OK},
950 {"file:///file#anchor",
951 "scheme=https,host=example,",
952 "https://example/file#anchor",
953 0, 0, CURLUE_NO_HOST, CURLUE_OK},
954 {NULL, /* start fresh! */
955 "scheme=file,host=127.0.0.1,path=/no,user=anonymous,",
956 "file:///no",
957 0, 0, CURLUE_OK, CURLUE_OK},
958 {NULL, /* start fresh! */
959 "scheme=ftp,host=127.0.0.1,path=/no,user=anonymous,",
960 "ftp://anonymous@127.0.0.1/no",
961 0, 0, CURLUE_OK, CURLUE_OK},
962 {NULL, /* start fresh! */
963 "scheme=https,host=example.com,",
964 "https://example.com/",
965 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_OK},
966 {"http://user:foo@example.com/path?query#frag",
967 "fragment=changed,",
968 "http://user:foo@example.com/path?query#changed",
969 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_OK},
970 {"http://example.com/",
971 "scheme=foo,", /* not accepted */
972 "http://example.com/",
973 0, 0, CURLUE_OK, CURLUE_UNSUPPORTED_SCHEME},
974 {"http://example.com/",
975 "scheme=https,path=/hello,fragment=snippet,",
976 "https://example.com/hello#snippet",
977 0, 0, CURLUE_OK, CURLUE_OK},
978 {"http://example.com:80",
979 "user=foo,port=1922,",
980 "http://foo@example.com:1922/",
981 0, 0, CURLUE_OK, CURLUE_OK},
982 {"http://example.com:80",
983 "user=foo,password=bar,",
984 "http://foo:bar@example.com:80/",
985 0, 0, CURLUE_OK, CURLUE_OK},
986 {"http://example.com:80",
987 "user=foo,",
988 "http://foo@example.com:80/",
989 0, 0, CURLUE_OK, CURLUE_OK},
990 {"http://example.com",
991 "host=www.example.com,",
992 "http://www.example.com/",
993 0, 0, CURLUE_OK, CURLUE_OK},
994 {"http://example.com:80",
995 "scheme=ftp,",
996 "ftp://example.com:80/",
997 0, 0, CURLUE_OK, CURLUE_OK},
998 {"custom-scheme://host",
999 "host=\"\",",
1000 "custom-scheme://host/",
1001 CURLU_NON_SUPPORT_SCHEME, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK,
1002 CURLUE_BAD_HOSTNAME},
1003 {"custom-scheme://host",
1004 "host=\"\",",
1005 "custom-scheme:///",
1006 CURLU_NON_SUPPORT_SCHEME, CURLU_NON_SUPPORT_SCHEME | CURLU_NO_AUTHORITY,
1007 CURLUE_OK, CURLUE_OK},
1008
1009 {NULL, NULL, NULL, 0, 0, CURLUE_OK, CURLUE_OK}
1010 };
1011
part2id(char *part)1012 static CURLUPart part2id(char *part)
1013 {
1014 if(!strcmp("url", part))
1015 return CURLUPART_URL;
1016 if(!strcmp("scheme", part))
1017 return CURLUPART_SCHEME;
1018 if(!strcmp("user", part))
1019 return CURLUPART_USER;
1020 if(!strcmp("password", part))
1021 return CURLUPART_PASSWORD;
1022 if(!strcmp("options", part))
1023 return CURLUPART_OPTIONS;
1024 if(!strcmp("host", part))
1025 return CURLUPART_HOST;
1026 if(!strcmp("port", part))
1027 return CURLUPART_PORT;
1028 if(!strcmp("path", part))
1029 return CURLUPART_PATH;
1030 if(!strcmp("query", part))
1031 return CURLUPART_QUERY;
1032 if(!strcmp("fragment", part))
1033 return CURLUPART_FRAGMENT;
1034 if(!strcmp("zoneid", part))
1035 return CURLUPART_ZONEID;
1036 return (CURLUPart)9999; /* bad input => bad output */
1037 }
1038
updateurl(CURLU *u, const char *cmd, unsigned int setflags)1039 static CURLUcode updateurl(CURLU *u, const char *cmd, unsigned int setflags)
1040 {
1041 const char *p = cmd;
1042 CURLUcode uc;
1043
1044 /* make sure the last command ends with a comma too! */
1045 while(p) {
1046 char *e = strchr(p, ',');
1047 if(e) {
1048 size_t n = (size_t)(e - p);
1049 char buf[80];
1050 char part[80];
1051 char value[80];
1052
1053 memset(part, 0, sizeof(part)); /* Avoid valgrind false positive. */
1054 memset(value, 0, sizeof(value)); /* Avoid valgrind false positive. */
1055 memcpy(buf, p, n);
1056 buf[n] = 0;
1057 if(2 == sscanf(buf, "%79[^=]=%79[^,]", part, value)) {
1058 CURLUPart what = part2id(part);
1059 #if 0
1060 /* for debugging this */
1061 fprintf(stderr, "%s = \"%s\" [%d]\n", part, value, (int)what);
1062 #endif
1063 if(what > CURLUPART_ZONEID)
1064 fprintf(stderr, "UNKNOWN part '%s'\n", part);
1065
1066 if(!strcmp("NULL", value))
1067 uc = curl_url_set(u, what, NULL, setflags);
1068 else if(!strcmp("\"\"", value))
1069 uc = curl_url_set(u, what, "", setflags);
1070 else
1071 uc = curl_url_set(u, what, value, setflags);
1072 if(uc)
1073 return uc;
1074 }
1075 p = e + 1;
1076 continue;
1077 }
1078 break;
1079 }
1080 return CURLUE_OK;
1081 }
1082
1083 static const struct redircase set_url_list[] = {
1084 {"http://example.com/please/../gimme/%TESTNUMBER?foobar#hello",
1085 "http://example.net/there/it/is/../../tes t case=/%TESTNUMBER0002? yes no",
1086 "http://example.net/there/tes%20t%20case=/%TESTNUMBER0002?+yes+no",
1087 0, CURLU_URLENCODE|CURLU_ALLOW_SPACE, CURLUE_OK},
1088 {"http://local.test?redirect=http://local.test:80?-321",
1089 "http://local.test:80?-123",
1090 "http://local.test:80/?-123",
1091 0, CURLU_URLENCODE|CURLU_ALLOW_SPACE, CURLUE_OK},
1092 {"http://local.test?redirect=http://local.test:80?-321",
1093 "http://local.test:80?-123",
1094 "http://local.test:80/?-123",
1095 0, 0, CURLUE_OK},
1096 {"http://example.org/static/favicon/wikipedia.ico",
1097 "//fake.example.com/licenses/by-sa/3.0/",
1098 "http://fake.example.com/licenses/by-sa/3.0/",
1099 0, 0, CURLUE_OK},
1100 {"https://example.org/static/favicon/wikipedia.ico",
1101 "//fake.example.com/licenses/by-sa/3.0/",
1102 "https://fake.example.com/licenses/by-sa/3.0/",
1103 0, 0, CURLUE_OK},
1104 {"file://localhost/path?query#frag",
1105 "foo#another",
1106 "file:///foo#another",
1107 0, 0, CURLUE_OK},
1108 {"http://example.com/path?query#frag",
1109 "https://two.example.com/bradnew",
1110 "https://two.example.com/bradnew",
1111 0, 0, CURLUE_OK},
1112 {"http://example.com/path?query#frag",
1113 "../../newpage#foo",
1114 "http://example.com/newpage#foo",
1115 0, 0, CURLUE_OK},
1116 {"http://user:foo@example.com/path?query#frag",
1117 "../../newpage",
1118 "http://user:foo@example.com/newpage",
1119 0, 0, CURLUE_OK},
1120 {"http://user:foo@example.com/path?query#frag",
1121 "../newpage",
1122 "http://user:foo@example.com/newpage",
1123 0, 0, CURLUE_OK},
1124 {"http://user:foo@example.com/path?query#frag",
1125 "http://?hi",
1126 "http:///?hi",
1127 0, CURLU_NO_AUTHORITY, CURLUE_OK},
1128 {NULL, NULL, NULL, 0, 0, CURLUE_OK}
1129 };
1130
set_url(void)1131 static int set_url(void)
1132 {
1133 int i;
1134 int error = 0;
1135
1136 for(i = 0; set_url_list[i].in && !error; i++) {
1137 CURLUcode rc;
1138 CURLU *urlp = curl_url();
1139 if(!urlp)
1140 break;
1141 rc = curl_url_set(urlp, CURLUPART_URL, set_url_list[i].in,
1142 set_url_list[i].urlflags);
1143 if(!rc) {
1144 rc = curl_url_set(urlp, CURLUPART_URL, set_url_list[i].set,
1145 set_url_list[i].setflags);
1146 if(rc) {
1147 fprintf(stderr, "%s:%d Set URL %s returned %d (%s)\n",
1148 __FILE__, __LINE__, set_url_list[i].set,
1149 (int)rc, curl_url_strerror(rc));
1150 error++;
1151 }
1152 else {
1153 char *url = NULL;
1154 rc = curl_url_get(urlp, CURLUPART_URL, &url, 0);
1155 if(rc) {
1156 fprintf(stderr, "%s:%d Get URL returned %d (%s)\n",
1157 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1158 error++;
1159 }
1160 else {
1161 if(checkurl(set_url_list[i].in, url, set_url_list[i].out)) {
1162 error++;
1163 }
1164 }
1165 curl_free(url);
1166 }
1167 }
1168 else if(rc != set_url_list[i].ucode) {
1169 fprintf(stderr, "Set URL\nin: %s\nreturned %d (expected %d)\n",
1170 set_url_list[i].in, (int)rc, set_url_list[i].ucode);
1171 error++;
1172 }
1173 curl_url_cleanup(urlp);
1174 }
1175 return error;
1176 }
1177
1178 /* 1. Set a URL
1179 2. Set one or more parts
1180 3. Extract and compare all parts - not the URL
1181 */
setget_parts(void)1182 static int setget_parts(void)
1183 {
1184 int i;
1185 int error = 0;
1186
1187 for(i = 0; setget_parts_list[i].set && !error; i++) {
1188 CURLUcode rc;
1189 CURLU *urlp = curl_url();
1190 if(!urlp) {
1191 error++;
1192 break;
1193 }
1194 if(setget_parts_list[i].in)
1195 rc = curl_url_set(urlp, CURLUPART_URL, setget_parts_list[i].in,
1196 setget_parts_list[i].urlflags);
1197 else
1198 rc = CURLUE_OK;
1199 if(!rc) {
1200 char *url = NULL;
1201 CURLUcode uc = updateurl(urlp, setget_parts_list[i].set,
1202 setget_parts_list[i].setflags);
1203
1204 if(uc != setget_parts_list[i].pcode) {
1205 fprintf(stderr, "updateurl\nin: %s\nreturned %d (expected %d)\n",
1206 setget_parts_list[i].set, (int)uc, setget_parts_list[i].pcode);
1207 error++;
1208 }
1209 if(!uc) {
1210 if(checkparts(urlp, setget_parts_list[i].set, setget_parts_list[i].out,
1211 setget_parts_list[i].getflags))
1212 error++; /* add */
1213 }
1214 curl_free(url);
1215 }
1216 else if(rc != CURLUE_OK) {
1217 fprintf(stderr, "Set parts\nin: %s\nreturned %d (expected %d)\n",
1218 setget_parts_list[i].in, (int)rc, 0);
1219 error++;
1220 }
1221 curl_url_cleanup(urlp);
1222 }
1223 return error;
1224 }
1225
set_parts(void)1226 static int set_parts(void)
1227 {
1228 int i;
1229 int error = 0;
1230
1231 for(i = 0; set_parts_list[i].set && !error; i++) {
1232 CURLUcode rc;
1233 CURLU *urlp = curl_url();
1234 if(!urlp) {
1235 error++;
1236 break;
1237 }
1238 if(set_parts_list[i].in)
1239 rc = curl_url_set(urlp, CURLUPART_URL, set_parts_list[i].in,
1240 set_parts_list[i].urlflags);
1241 else
1242 rc = CURLUE_OK;
1243 if(!rc) {
1244 char *url = NULL;
1245 CURLUcode uc = updateurl(urlp, set_parts_list[i].set,
1246 set_parts_list[i].setflags);
1247
1248 if(uc != set_parts_list[i].pcode) {
1249 fprintf(stderr, "updateurl\nin: %s\nreturned %d (expected %d)\n",
1250 set_parts_list[i].set, (int)uc, set_parts_list[i].pcode);
1251 error++;
1252 }
1253 if(!uc) {
1254 /* only do this if it worked */
1255 rc = curl_url_get(urlp, CURLUPART_URL, &url, 0);
1256
1257 if(rc) {
1258 fprintf(stderr, "%s:%d Get URL returned %d (%s)\n",
1259 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1260 error++;
1261 }
1262 else if(checkurl(set_parts_list[i].in, url, set_parts_list[i].out)) {
1263 error++;
1264 }
1265 }
1266 curl_free(url);
1267 }
1268 else if(rc != set_parts_list[i].ucode) {
1269 fprintf(stderr, "Set parts\nin: %s\nreturned %d (expected %d)\n",
1270 set_parts_list[i].in, (int)rc, set_parts_list[i].ucode);
1271 error++;
1272 }
1273 curl_url_cleanup(urlp);
1274 }
1275 return error;
1276 }
1277
get_url(void)1278 static int get_url(void)
1279 {
1280 int i;
1281 int error = 0;
1282 for(i = 0; get_url_list[i].in && !error; i++) {
1283 CURLUcode rc;
1284 CURLU *urlp = curl_url();
1285 if(!urlp) {
1286 error++;
1287 break;
1288 }
1289 rc = curl_url_set(urlp, CURLUPART_URL, get_url_list[i].in,
1290 get_url_list[i].urlflags);
1291 if(!rc) {
1292 char *url = NULL;
1293 rc = curl_url_get(urlp, CURLUPART_URL, &url, get_url_list[i].getflags);
1294
1295 if(rc) {
1296 fprintf(stderr, "%s:%d returned %d (%s). URL: '%s'\n",
1297 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc),
1298 get_url_list[i].in);
1299 error++;
1300 }
1301 else {
1302 if(checkurl(get_url_list[i].in, url, get_url_list[i].out)) {
1303 error++;
1304 }
1305 }
1306 curl_free(url);
1307 }
1308 if(rc != get_url_list[i].ucode) {
1309 fprintf(stderr, "Get URL\nin: %s\nreturned %d (expected %d)\n",
1310 get_url_list[i].in, (int)rc, get_url_list[i].ucode);
1311 error++;
1312 }
1313 curl_url_cleanup(urlp);
1314 }
1315 return error;
1316 }
1317
get_parts(void)1318 static int get_parts(void)
1319 {
1320 int i;
1321 int error = 0;
1322 for(i = 0; get_parts_list[i].in && !error; i++) {
1323 CURLUcode rc;
1324 CURLU *urlp = curl_url();
1325 if(!urlp) {
1326 error++;
1327 break;
1328 }
1329 rc = curl_url_set(urlp, CURLUPART_URL,
1330 get_parts_list[i].in,
1331 get_parts_list[i].urlflags);
1332 if(rc != get_parts_list[i].ucode) {
1333 fprintf(stderr, "Get parts\nin: %s\nreturned %d (expected %d)\n",
1334 get_parts_list[i].in, (int)rc, get_parts_list[i].ucode);
1335 error++;
1336 }
1337 else if(get_parts_list[i].ucode) {
1338 /* the expected error happened */
1339 }
1340 else if(checkparts(urlp, get_parts_list[i].in, get_parts_list[i].out,
1341 get_parts_list[i].getflags))
1342 error++;
1343 curl_url_cleanup(urlp);
1344 }
1345 return error;
1346 }
1347
1348 static const struct querycase append_list[] = {
1349 {"HTTP://test/?s", "name=joe\x02", "http://test/?s&name=joe%02",
1350 0, CURLU_URLENCODE, CURLUE_OK},
1351 {"HTTP://test/?size=2#f", "name=joe=", "http://test/?size=2&name=joe%3d#f",
1352 0, CURLU_URLENCODE, CURLUE_OK},
1353 {"HTTP://test/?size=2#f", "name=joe doe",
1354 "http://test/?size=2&name=joe+doe#f",
1355 0, CURLU_URLENCODE, CURLUE_OK},
1356 {"HTTP://test/", "name=joe", "http://test/?name=joe", 0, 0, CURLUE_OK},
1357 {"HTTP://test/?size=2", "name=joe", "http://test/?size=2&name=joe",
1358 0, 0, CURLUE_OK},
1359 {"HTTP://test/?size=2&", "name=joe", "http://test/?size=2&name=joe",
1360 0, 0, CURLUE_OK},
1361 {"HTTP://test/?size=2#f", "name=joe", "http://test/?size=2&name=joe#f",
1362 0, 0, CURLUE_OK},
1363 {NULL, NULL, NULL, 0, 0, CURLUE_OK}
1364 };
1365
append(void)1366 static int append(void)
1367 {
1368 int i;
1369 int error = 0;
1370 for(i = 0; append_list[i].in && !error; i++) {
1371 CURLUcode rc;
1372 CURLU *urlp = curl_url();
1373 if(!urlp) {
1374 error++;
1375 break;
1376 }
1377 rc = curl_url_set(urlp, CURLUPART_URL,
1378 append_list[i].in,
1379 append_list[i].urlflags);
1380 if(rc)
1381 error++;
1382 else
1383 rc = curl_url_set(urlp, CURLUPART_QUERY,
1384 append_list[i].q,
1385 append_list[i].qflags | CURLU_APPENDQUERY);
1386 if(error)
1387 ;
1388 else if(rc != append_list[i].ucode) {
1389 fprintf(stderr, "Append\nin: %s\nreturned %d (expected %d)\n",
1390 append_list[i].in, (int)rc, append_list[i].ucode);
1391 error++;
1392 }
1393 else if(append_list[i].ucode) {
1394 /* the expected error happened */
1395 }
1396 else {
1397 char *url;
1398 rc = curl_url_get(urlp, CURLUPART_URL, &url, 0);
1399 if(rc) {
1400 fprintf(stderr, "%s:%d Get URL returned %d (%s)\n",
1401 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1402 error++;
1403 }
1404 else {
1405 if(checkurl(append_list[i].in, url, append_list[i].out)) {
1406 error++;
1407 }
1408 curl_free(url);
1409 }
1410 }
1411 curl_url_cleanup(urlp);
1412 }
1413 return error;
1414 }
1415
scopeid(void)1416 static int scopeid(void)
1417 {
1418 CURLU *u = curl_url();
1419 int error = 0;
1420 CURLUcode rc;
1421 char *url;
1422
1423 rc = curl_url_set(u, CURLUPART_URL,
1424 "https://[fe80::20c:29ff:fe9c:409b%25eth0]/hello.html", 0);
1425 if(rc != CURLUE_OK) {
1426 fprintf(stderr, "%s:%d curl_url_set returned %d (%s)\n",
1427 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1428 error++;
1429 }
1430
1431 rc = curl_url_get(u, CURLUPART_HOST, &url, 0);
1432 if(rc != CURLUE_OK) {
1433 fprintf(stderr, "%s:%d curl_url_get CURLUPART_HOST returned %d (%s)\n",
1434 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1435 error++;
1436 }
1437 else {
1438 curl_free(url);
1439 }
1440
1441 rc = curl_url_set(u, CURLUPART_HOST, "[::1]", 0);
1442 if(rc != CURLUE_OK) {
1443 fprintf(stderr, "%s:%d curl_url_set CURLUPART_HOST returned %d (%s)\n",
1444 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1445 error++;
1446 }
1447
1448 rc = curl_url_get(u, CURLUPART_URL, &url, 0);
1449 if(rc != CURLUE_OK) {
1450 fprintf(stderr, "%s:%d curl_url_get CURLUPART_URL returned %d (%s)\n",
1451 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1452 error++;
1453 }
1454 else {
1455 curl_free(url);
1456 }
1457
1458 rc = curl_url_set(u, CURLUPART_HOST, "example.com", 0);
1459 if(rc != CURLUE_OK) {
1460 fprintf(stderr, "%s:%d curl_url_set CURLUPART_HOST returned %d (%s)\n",
1461 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1462 error++;
1463 }
1464
1465 rc = curl_url_get(u, CURLUPART_URL, &url, 0);
1466 if(rc != CURLUE_OK) {
1467 fprintf(stderr, "%s:%d curl_url_get CURLUPART_URL returned %d (%s)\n",
1468 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1469 error++;
1470 }
1471 else {
1472 curl_free(url);
1473 }
1474
1475 rc = curl_url_set(u, CURLUPART_HOST,
1476 "[fe80::20c:29ff:fe9c:409b%25eth0]", 0);
1477 if(rc != CURLUE_OK) {
1478 fprintf(stderr, "%s:%d curl_url_set CURLUPART_HOST returned %d (%s)\n",
1479 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1480 error++;
1481 }
1482
1483 rc = curl_url_get(u, CURLUPART_URL, &url, 0);
1484 if(rc != CURLUE_OK) {
1485 fprintf(stderr, "%s:%d curl_url_get CURLUPART_URL returned %d (%s)\n",
1486 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1487 error++;
1488 }
1489 else {
1490 curl_free(url);
1491 }
1492
1493 rc = curl_url_get(u, CURLUPART_HOST, &url, 0);
1494 if(rc != CURLUE_OK) {
1495 fprintf(stderr, "%s:%d curl_url_get CURLUPART_HOST returned %d (%s)\n",
1496 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1497 error++;
1498 }
1499 else {
1500 curl_free(url);
1501 }
1502
1503 rc = curl_url_get(u, CURLUPART_ZONEID, &url, 0);
1504 if(rc != CURLUE_OK) {
1505 fprintf(stderr, "%s:%d curl_url_get CURLUPART_ZONEID returned %d (%s)\n",
1506 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1507 error++;
1508 }
1509 else {
1510 curl_free(url);
1511 }
1512
1513 rc = curl_url_set(u, CURLUPART_ZONEID, "clown", 0);
1514 if(rc != CURLUE_OK) {
1515 fprintf(stderr, "%s:%d curl_url_set CURLUPART_ZONEID returned %d (%s)\n",
1516 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1517 error++;
1518 }
1519
1520 rc = curl_url_get(u, CURLUPART_URL, &url, 0);
1521 if(rc != CURLUE_OK) {
1522 fprintf(stderr, "%s:%d curl_url_get CURLUPART_URL returned %d (%s)\n",
1523 __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
1524 error++;
1525 }
1526 else {
1527 curl_free(url);
1528 }
1529
1530 curl_url_cleanup(u);
1531
1532 return error;
1533 }
1534
get_nothing(void)1535 static int get_nothing(void)
1536 {
1537 CURLU *u = curl_url();
1538 if(u) {
1539 char *p;
1540 CURLUcode rc;
1541
1542 rc = curl_url_get(u, CURLUPART_SCHEME, &p, 0);
1543 if(rc != CURLUE_NO_SCHEME)
1544 fprintf(stderr, "unexpected return code line %u\n", __LINE__);
1545
1546 rc = curl_url_get(u, CURLUPART_HOST, &p, 0);
1547 if(rc != CURLUE_NO_HOST)
1548 fprintf(stderr, "unexpected return code line %u\n", __LINE__);
1549
1550 rc = curl_url_get(u, CURLUPART_USER, &p, 0);
1551 if(rc != CURLUE_NO_USER)
1552 fprintf(stderr, "unexpected return code line %u\n", __LINE__);
1553
1554 rc = curl_url_get(u, CURLUPART_PASSWORD, &p, 0);
1555 if(rc != CURLUE_NO_PASSWORD)
1556 fprintf(stderr, "unexpected return code line %u\n", __LINE__);
1557
1558 rc = curl_url_get(u, CURLUPART_OPTIONS, &p, 0);
1559 if(rc != CURLUE_NO_OPTIONS)
1560 fprintf(stderr, "unexpected return code line %u\n", __LINE__);
1561
1562 rc = curl_url_get(u, CURLUPART_PATH, &p, 0);
1563 if(rc != CURLUE_OK)
1564 fprintf(stderr, "unexpected return code line %u\n", __LINE__);
1565 else
1566 curl_free(p);
1567
1568 rc = curl_url_get(u, CURLUPART_QUERY, &p, 0);
1569 if(rc != CURLUE_NO_QUERY)
1570 fprintf(stderr, "unexpected return code line %u\n", __LINE__);
1571
1572 rc = curl_url_get(u, CURLUPART_FRAGMENT, &p, 0);
1573 if(rc != CURLUE_NO_FRAGMENT)
1574 fprintf(stderr, "unexpected return code line %u\n", __LINE__);
1575
1576 rc = curl_url_get(u, CURLUPART_ZONEID, &p, 0);
1577 if(rc != CURLUE_NO_ZONEID)
1578 fprintf(stderr, "unexpected return code %u on line %u\n", (int)rc,
1579 __LINE__);
1580
1581 curl_url_cleanup(u);
1582 }
1583 return 0;
1584 }
1585
1586 static const struct clearurlcase clear_url_list[] ={
1587 {CURLUPART_SCHEME, "http", NULL, CURLUE_NO_SCHEME},
1588 {CURLUPART_USER, "user", NULL, CURLUE_NO_USER},
1589 {CURLUPART_PASSWORD, "password", NULL, CURLUE_NO_PASSWORD},
1590 {CURLUPART_OPTIONS, "options", NULL, CURLUE_NO_OPTIONS},
1591 {CURLUPART_HOST, "host", NULL, CURLUE_NO_HOST},
1592 {CURLUPART_ZONEID, "eth0", NULL, CURLUE_NO_ZONEID},
1593 {CURLUPART_PORT, "1234", NULL, CURLUE_NO_PORT},
1594 {CURLUPART_PATH, "/hello", "/", CURLUE_OK},
1595 {CURLUPART_QUERY, "a=b", NULL, CURLUE_NO_QUERY},
1596 {CURLUPART_FRAGMENT, "anchor", NULL, CURLUE_NO_FRAGMENT},
1597 {CURLUPART_URL, NULL, NULL, CURLUE_OK},
1598 };
1599
clear_url(void)1600 static int clear_url(void)
1601 {
1602 CURLU *u = curl_url();
1603 int i, error = 0;
1604 if(u) {
1605 char *p = NULL;
1606 CURLUcode rc;
1607
1608 for(i = 0; clear_url_list[i].in && !error; i++) {
1609 rc = curl_url_set(u, clear_url_list[i].part, clear_url_list[i].in, 0);
1610 if(rc != CURLUE_OK)
1611 fprintf(stderr, "unexpected return code line %u\n", __LINE__);
1612
1613 rc = curl_url_set(u, CURLUPART_URL, NULL, 0);
1614 if(rc != CURLUE_OK)
1615 fprintf(stderr, "unexpected return code line %u\n", __LINE__);
1616
1617 rc = curl_url_get(u, clear_url_list[i].part, &p, 0);
1618 if(rc != clear_url_list[i].ucode || (clear_url_list[i].out &&
1619 0 != strcmp(p, clear_url_list[i].out))) {
1620
1621 fprintf(stderr, "unexpected return code line %u\n", __LINE__);
1622 error++;
1623 }
1624 if(rc == CURLUE_OK)
1625 curl_free(p);
1626 }
1627 }
1628
1629 curl_url_cleanup(u);
1630
1631 return error;
1632 }
1633
1634 static char total[128000];
1635 static char bigpart[120000];
1636
1637 /*
1638 * verify ridiculous URL part sizes
1639 */
huge(void)1640 static int huge(void)
1641 {
1642 const char *smallpart = "c";
1643 int i;
1644 CURLU *urlp = curl_url();
1645 CURLUcode rc;
1646 CURLUPart part[]= {
1647 CURLUPART_SCHEME,
1648 CURLUPART_USER,
1649 CURLUPART_PASSWORD,
1650 CURLUPART_HOST,
1651 CURLUPART_PATH,
1652 CURLUPART_QUERY,
1653 CURLUPART_FRAGMENT
1654 };
1655 int error = 0;
1656 if(!urlp)
1657 return 1;
1658 bigpart[0] = '/'; /* for the path */
1659 memset(&bigpart[1], 'a', sizeof(bigpart) - 2);
1660 bigpart[sizeof(bigpart) - 1] = 0;
1661
1662 for(i = 0; i < 7; i++) {
1663 char *partp;
1664 msnprintf(total, sizeof(total),
1665 "%s://%s:%s@%s/%s?%s#%s",
1666 (i == 0)? &bigpart[1] : smallpart,
1667 (i == 1)? &bigpart[1] : smallpart,
1668 (i == 2)? &bigpart[1] : smallpart,
1669 (i == 3)? &bigpart[1] : smallpart,
1670 (i == 4)? &bigpart[1] : smallpart,
1671 (i == 5)? &bigpart[1] : smallpart,
1672 (i == 6)? &bigpart[1] : smallpart);
1673 rc = curl_url_set(urlp, CURLUPART_URL, total, CURLU_NON_SUPPORT_SCHEME);
1674 if((!i && (rc != CURLUE_BAD_SCHEME)) ||
1675 (i && rc)) {
1676 printf("URL %u: failed to parse [%s]\n", i, total);
1677 error++;
1678 }
1679
1680 /* only extract if the parse worked */
1681 if(!rc) {
1682 curl_url_get(urlp, part[i], &partp, 0);
1683 if(!partp || strcmp(partp, &bigpart[1 - (i == 4)])) {
1684 printf("URL %u part %u: failure\n", i, part[i]);
1685 error++;
1686 }
1687 curl_free(partp);
1688 }
1689 }
1690 curl_url_cleanup(urlp);
1691 return error;
1692 }
1693
urldup(void)1694 static int urldup(void)
1695 {
1696 const char *url[] = {
1697 "http://"
1698 "user:pwd@"
1699 "[2a04:4e42:e00::347%25eth0]"
1700 ":80"
1701 "/path"
1702 "?query"
1703 "#fraggie",
1704 "https://example.com",
1705 "https://user@example.com",
1706 "https://user.pwd@example.com",
1707 "https://user.pwd@example.com:1234",
1708 "https://example.com:1234",
1709 "example.com:1234",
1710 "https://user.pwd@example.com:1234/path?query#frag",
1711 NULL
1712 };
1713 CURLU *copy = NULL;
1714 char *h_str = NULL, *copy_str = NULL;
1715 CURLU *h = curl_url();
1716 int i;
1717
1718 if(!h)
1719 goto err;
1720
1721 for(i = 0; url[i]; i++) {
1722 CURLUcode rc = curl_url_set(h, CURLUPART_URL, url[i],
1723 CURLU_GUESS_SCHEME);
1724 if(rc)
1725 goto err;
1726 copy = curl_url_dup(h);
1727
1728 rc = curl_url_get(h, CURLUPART_URL, &h_str, 0);
1729 if(rc)
1730 goto err;
1731
1732 rc = curl_url_get(copy, CURLUPART_URL, ©_str, 0);
1733 if(rc)
1734 goto err;
1735
1736 if(strcmp(h_str, copy_str)) {
1737 printf("Original: %s\nParsed: %s\nCopy: %s\n",
1738 url[i], h_str, copy_str);
1739 goto err;
1740 }
1741 curl_free(copy_str);
1742 curl_free(h_str);
1743 curl_url_cleanup(copy);
1744 copy_str = NULL;
1745 h_str = NULL;
1746 copy = NULL;
1747 }
1748 curl_url_cleanup(h);
1749 return 0;
1750 err:
1751 curl_free(copy_str);
1752 curl_free(h_str);
1753 curl_url_cleanup(copy);
1754 curl_url_cleanup(h);
1755 return 1;
1756 }
1757
test(char *URL)1758 int test(char *URL)
1759 {
1760 (void)URL; /* not used */
1761
1762 if(urldup())
1763 return 11;
1764
1765 if(setget_parts())
1766 return 10;
1767
1768 if(get_url())
1769 return 3;
1770
1771 if(huge())
1772 return 9;
1773
1774 if(get_nothing())
1775 return 7;
1776
1777 if(scopeid())
1778 return 6;
1779
1780 if(append())
1781 return 5;
1782
1783 if(set_url())
1784 return 1;
1785
1786 if(set_parts())
1787 return 2;
1788
1789 if(get_parts())
1790 return 4;
1791
1792 if(clear_url())
1793 return 8;
1794
1795 printf("success\n");
1796 return 0;
1797 }
1798