• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2018, 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.haxx.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  ***************************************************************************/
22 
23 /*
24  * Note:
25  *
26  * Since the URL parser by default only accepts schemes that *this instance*
27  * of libcurl supports, make sure that the test1560 file lists all the schemes
28  * that this test will assume to be present!
29  */
30 
31 #include "test.h"
32 
33 #include "testutil.h"
34 #include "warnless.h"
35 #include "memdebug.h" /* LAST include file */
36 
37 struct part {
38   CURLUPart part;
39   const char *name;
40 };
41 
42 
checkparts(CURLU * u,const char * in,const char * wanted,unsigned int getflags)43 static int checkparts(CURLU *u, const char *in, const char *wanted,
44                       unsigned int getflags)
45 {
46   int i;
47   CURLUcode rc;
48   char buf[256];
49   char *bufp = &buf[0];
50   size_t len = sizeof(buf);
51   struct part parts[] = {
52     {CURLUPART_SCHEME, "scheme"},
53     {CURLUPART_USER, "user"},
54     {CURLUPART_PASSWORD, "password"},
55     {CURLUPART_OPTIONS, "options"},
56     {CURLUPART_HOST, "host"},
57     {CURLUPART_PORT, "port"},
58     {CURLUPART_PATH, "path"},
59     {CURLUPART_QUERY, "query"},
60     {CURLUPART_FRAGMENT, "fragment"},
61     {0, NULL}
62   };
63   buf[0] = 0;
64 
65   for(i = 0; parts[i].name; i++) {
66     char *p = NULL;
67     size_t n;
68     rc = curl_url_get(u, parts[i].part, &p, getflags);
69     if(!rc && p) {
70       msnprintf(bufp, len, "%s%s", buf[0]?" | ":"", p);
71     }
72     else
73       msnprintf(bufp, len, "%s[%d]", buf[0]?" | ":"", (int)rc);
74 
75     n = strlen(bufp);
76     bufp += n;
77     len -= n;
78     curl_free(p);
79   }
80   if(strcmp(buf, wanted)) {
81     fprintf(stderr, "in: %s\nwanted: %s\ngot:    %s\n", in, wanted, buf);
82     return 1;
83   }
84   return 0;
85 }
86 
87 struct redircase {
88   const char *in;
89   const char *set;
90   const char *out;
91   unsigned int urlflags;
92   unsigned int setflags;
93   CURLUcode ucode;
94 };
95 
96 struct setcase {
97   const char *in;
98   const char *set;
99   const char *out;
100   unsigned int urlflags;
101   unsigned int setflags;
102   CURLUcode ucode;
103 };
104 
105 struct testcase {
106   const char *in;
107   const char *out;
108   unsigned int urlflags;
109   unsigned int getflags;
110   CURLUcode ucode;
111 };
112 
113 struct urltestcase {
114   const char *in;
115   const char *out;
116   unsigned int urlflags; /* pass to curl_url() */
117   unsigned int getflags; /* pass to curl_url_get() */
118   CURLUcode ucode;
119 };
120 
121 struct querycase {
122   const char *in;
123   const char *q;
124   const char *out;
125   unsigned int urlflags; /* pass to curl_url() */
126   unsigned int qflags; /* pass to curl_url_get() */
127   CURLUcode ucode;
128 };
129 
130 static struct testcase get_parts_list[] ={
131 #ifdef WIN32
132   {"file:/C:\\programs\\foo",
133    "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
134    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
135   {"file://C:\\programs\\foo",
136    "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
137    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
138   {"file:///C:\\programs\\foo",
139    "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
140    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
141 #endif
142   {"boing:80",
143    "https | [11] | [12] | [13] | boing | 80 | / | [16] | [17]",
144    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
145   {"http://[fd00:a41::50]:8080",
146    "http | [11] | [12] | [13] | [fd00:a41::50] | 8080 | / | [16] | [17]",
147    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
148   {"http://[fd00:a41::50]/",
149    "http | [11] | [12] | [13] | [fd00:a41::50] | [15] | / | [16] | [17]",
150    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
151   {"http://[fd00:a41::50]",
152    "http | [11] | [12] | [13] | [fd00:a41::50] | [15] | / | [16] | [17]",
153    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
154   {"https://[::1%252]:1234",
155    "https | [11] | [12] | [13] | [::1%252] | 1234 | / | [16] | [17]",
156    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
157   {"https://127.0.0.1:443",
158    "https | [11] | [12] | [13] | 127.0.0.1 | [15] | / | [16] | [17]",
159    0, CURLU_NO_DEFAULT_PORT, CURLUE_OK},
160   {"http://%3a:%3a@ex%0ample/%3f+?+%3f+%23#+%23%3f%g7",
161    "http | : | : | [13] | [6] | [15] | /?+ |  ? # | +#?%g7",
162    0, CURLU_URLDECODE, CURLUE_OK},
163   {"http://%3a:%3a@ex%0ample/%3f?%3f%35#%35%3f%g7",
164    "http | %3a | %3a | [13] | ex%0ample | [15] | /%3f | %3f%35 | %35%3f%g7",
165    0, 0, CURLUE_OK},
166   {"http://HO0_-st%41/",
167    "http | [11] | [12] | [13] | HO0_-st%41 | [15] | / | [16] | [17]",
168    0, 0, CURLUE_OK},
169   {"file://hello.html",
170    "",
171    0, 0, CURLUE_MALFORMED_INPUT},
172   {"http://HO0_-st/",
173    "http | [11] | [12] | [13] | HO0_-st | [15] | / | [16] | [17]",
174    0, 0, CURLUE_OK},
175   {"imap://user:pass;option@server/path",
176    "imap | user | pass | option | server | [15] | /path | [16] | [17]",
177    0, 0, CURLUE_OK},
178   {"http://user:pass;option@server/path",
179    "http | user | pass;option | [13] | server | [15] | /path | [16] | [17]",
180    0, 0, CURLUE_OK},
181   {"file:/hello.html",
182    "file | [11] | [12] | [13] | [14] | [15] | /hello.html | [16] | [17]",
183    0, 0, CURLUE_OK},
184   {"file://127.0.0.1/hello.html",
185    "file | [11] | [12] | [13] | [14] | [15] | /hello.html | [16] | [17]",
186    0, 0, CURLUE_OK},
187   {"file:////hello.html",
188    "file | [11] | [12] | [13] | [14] | [15] | //hello.html | [16] | [17]",
189    0, 0, CURLUE_OK},
190   {"file:///hello.html",
191    "file | [11] | [12] | [13] | [14] | [15] | /hello.html | [16] | [17]",
192    0, 0, CURLUE_OK},
193   {"https://127.0.0.1",
194    "https | [11] | [12] | [13] | 127.0.0.1 | 443 | / | [16] | [17]",
195    0, CURLU_DEFAULT_PORT, CURLUE_OK},
196   {"https://127.0.0.1",
197    "https | [11] | [12] | [13] | 127.0.0.1 | [15] | / | [16] | [17]",
198    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
199   {"https://[::1]:1234",
200    "https | [11] | [12] | [13] | [::1] | 1234 | / | [16] | [17]",
201    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
202   {"https://127abc.com",
203    "https | [11] | [12] | [13] | 127abc.com | [15] | / | [16] | [17]",
204    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
205   {"https:// example.com?check",
206    "",
207    CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
208   {"https://e x a m p l e.com?check",
209    "",
210    CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
211   {"https://example.com?check",
212    "https | [11] | [12] | [13] | example.com | [15] | / | check | [17]",
213    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
214   {"https://example.com:65536",
215    "",
216    CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PORT_NUMBER},
217   {"https://example.com:0#moo",
218    "",
219    CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PORT_NUMBER},
220   {"https://example.com:01#moo",
221    "https | [11] | [12] | [13] | example.com | 1 | / | "
222    "[16] | moo",
223    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
224   {"https://example.com:1#moo",
225    "https | [11] | [12] | [13] | example.com | 1 | / | "
226    "[16] | moo",
227    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
228   {"http://example.com#moo",
229    "http | [11] | [12] | [13] | example.com | [15] | / | "
230    "[16] | moo",
231    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
232   {"http://example.com",
233    "http | [11] | [12] | [13] | example.com | [15] | / | "
234    "[16] | [17]",
235    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
236   {"http://example.com/path/html",
237    "http | [11] | [12] | [13] | example.com | [15] | /path/html | "
238    "[16] | [17]",
239    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
240   {"http://example.com/path/html?query=name",
241    "http | [11] | [12] | [13] | example.com | [15] | /path/html | "
242    "query=name | [17]",
243    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
244   {"http://example.com/path/html?query=name#anchor",
245    "http | [11] | [12] | [13] | example.com | [15] | /path/html | "
246    "query=name | anchor",
247    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
248   {"http://example.com:1234/path/html?query=name#anchor",
249    "http | [11] | [12] | [13] | example.com | 1234 | /path/html | "
250    "query=name | anchor",
251    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
252   {"http:///user:password@example.com:1234/path/html?query=name#anchor",
253    "http | user | password | [13] | example.com | 1234 | /path/html | "
254    "query=name | anchor",
255    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
256   {"https://user:password@example.com:1234/path/html?query=name#anchor",
257    "https | user | password | [13] | example.com | 1234 | /path/html | "
258    "query=name | anchor",
259    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
260   {"http://user:password@example.com:1234/path/html?query=name#anchor",
261    "http | user | password | [13] | example.com | 1234 | /path/html | "
262    "query=name | anchor",
263    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
264   {"http:/user:password@example.com:1234/path/html?query=name#anchor",
265    "http | user | password | [13] | example.com | 1234 | /path/html | "
266    "query=name | anchor",
267    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
268   {"http:////user:password@example.com:1234/path/html?query=name#anchor",
269    "",
270    CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
271   {NULL, NULL, 0, 0, CURLUE_OK},
272 };
273 
274 static struct urltestcase get_url_list[] = {
275   {"smtp.example.com/path/html",
276    "smtp://smtp.example.com/path/html",
277    CURLU_GUESS_SCHEME, 0, CURLUE_OK},
278   {"https.example.com/path/html",
279    "http://https.example.com/path/html",
280    CURLU_GUESS_SCHEME, 0, CURLUE_OK},
281   {"dict.example.com/path/html",
282    "dict://dict.example.com/path/html",
283    CURLU_GUESS_SCHEME, 0, CURLUE_OK},
284   {"pop3.example.com/path/html",
285    "pop3://pop3.example.com/path/html",
286    CURLU_GUESS_SCHEME, 0, CURLUE_OK},
287   {"ldap.example.com/path/html",
288    "ldap://ldap.example.com/path/html",
289    CURLU_GUESS_SCHEME, 0, CURLUE_OK},
290   {"imap.example.com/path/html",
291    "imap://imap.example.com/path/html",
292    CURLU_GUESS_SCHEME, 0, CURLUE_OK},
293   {"ftp.example.com/path/html",
294    "ftp://ftp.example.com/path/html",
295    CURLU_GUESS_SCHEME, 0, CURLUE_OK},
296   {"example.com/path/html",
297    "http://example.com/path/html",
298    CURLU_GUESS_SCHEME, 0, CURLUE_OK},
299   {"HTTP://test/", "http://test/", 0, 0, CURLUE_OK},
300   {"http://HO0_-st..~./", "http://HO0_-st..~./", 0, 0, CURLUE_OK},
301   {"http:/@example.com: 123/", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
302   {"http:/@example.com:123 /", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
303   {"http:/@example.com:123a/", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
304   {"http://host/file\r", "", 0, 0, CURLUE_MALFORMED_INPUT},
305   {"http://host/file\n\x03", "", 0, 0, CURLUE_MALFORMED_INPUT},
306   {"htt\x02://host/file", "",
307    CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
308   {" http://host/file", "", 0, 0, CURLUE_MALFORMED_INPUT},
309   /* here the password ends at the semicolon and options is 'word' */
310   {"imap://user:pass;word@host/file",
311    "imap://user:pass;word@host/file",
312    0, 0, CURLUE_OK},
313   /* here the password has the semicolon */
314   {"http://user:pass;word@host/file",
315    "http://user:pass;word@host/file",
316    0, 0, CURLUE_OK},
317   {"file:///file.txt#moo",
318    "file:///file.txt#moo",
319    0, 0, CURLUE_OK},
320   {"file:////file.txt",
321    "file:////file.txt",
322    0, 0, CURLUE_OK},
323   {"file:///file.txt",
324    "file:///file.txt",
325    0, 0, CURLUE_OK},
326   {"file:./",
327    "file://",
328    0, 0, CURLUE_MALFORMED_INPUT},
329   {"http://example.com/hello/../here",
330    "http://example.com/hello/../here",
331    CURLU_PATH_AS_IS, 0, CURLUE_OK},
332   {"http://example.com/hello/../here",
333    "http://example.com/here",
334    0, 0, CURLUE_OK},
335   {"http://example.com:80",
336    "http://example.com/",
337    0, CURLU_NO_DEFAULT_PORT, CURLUE_OK},
338   {"tp://example.com/path/html",
339    "",
340    0, 0, CURLUE_UNSUPPORTED_SCHEME},
341   {"http://hello:fool@example.com",
342    "",
343    CURLU_DISALLOW_USER, 0, CURLUE_USER_NOT_ALLOWED},
344   {"http:/@example.com:123",
345    "http://example.com:123/",
346    0, 0, CURLUE_OK},
347   {"http:/:password@example.com",
348    "http://:password@example.com/",
349    0, 0, CURLUE_OK},
350   {"http://user@example.com?#",
351    "http://user@example.com/",
352    0, 0, CURLUE_OK},
353   {"http://user@example.com?",
354    "http://user@example.com/",
355    0, 0, CURLUE_OK},
356   {"http://user@example.com#anchor",
357    "http://user@example.com/#anchor",
358    0, 0, CURLUE_OK},
359   {"example.com/path/html",
360    "https://example.com/path/html",
361    CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
362   {"example.com/path/html",
363    "",
364    0, 0, CURLUE_MALFORMED_INPUT},
365   {"http://user:password@example.com:1234/path/html?query=name#anchor",
366    "http://user:password@example.com:1234/path/html?query=name#anchor",
367    0, 0, CURLUE_OK},
368   {"http://example.com:1234/path/html?query=name#anchor",
369    "http://example.com:1234/path/html?query=name#anchor",
370    0, 0, CURLUE_OK},
371   {"http://example.com/path/html?query=name#anchor",
372    "http://example.com/path/html?query=name#anchor",
373    0, 0, CURLUE_OK},
374   {"http://example.com/path/html?query=name",
375    "http://example.com/path/html?query=name",
376    0, 0, CURLUE_OK},
377   {"http://example.com/path/html",
378    "http://example.com/path/html",
379    0, 0, CURLUE_OK},
380   {"tp://example.com/path/html",
381    "tp://example.com/path/html",
382    CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
383   {NULL, NULL, 0, 0, 0}
384 };
385 
checkurl(const char * url,const char * out)386 static int checkurl(const char *url, const char *out)
387 {
388   if(strcmp(out, url)) {
389     fprintf(stderr, "Wanted: %s\nGot   : %s\n",
390             out, url);
391     return 1;
392   }
393   return 0;
394 }
395 
396 /* !checksrc! disable SPACEBEFORECOMMA 1 */
397 static struct setcase set_parts_list[] = {
398   {"https://host/",
399    "path=%4A%4B%4C,",
400    "https://host/%4a%4b%4c",
401    0, 0, CURLUE_NO_HOST},
402   {"https://host/mooo?q#f",
403    "path=NULL,query=NULL,fragment=NULL,",
404    "https://host/",
405    0, 0, CURLUE_NO_HOST},
406   {"https://user:secret@host/",
407    "user=NULL,password=NULL,",
408    "https://host/",
409    0, 0, CURLUE_NO_HOST},
410   {NULL,
411    "scheme=https,user=   @:,host=foobar,",
412    "https://%20%20%20%40%3a@foobar/",
413    0, CURLU_URLENCODE, CURLUE_OK},
414   {NULL,
415    "scheme=https,host=  ,path= ,user= ,password= ,query= ,fragment= ,",
416    "https://%20:%20@%20%20/%20?+#%20",
417    0, CURLU_URLENCODE, CURLUE_OK},
418   {NULL,
419    "scheme=https,host=foobar,path=/this /path /is /here,",
420    "https://foobar/this%20/path%20/is%20/here",
421    0, CURLU_URLENCODE, CURLUE_OK},
422   {"imap://user:secret;opt@host/",
423    "options=updated,scheme=imaps,password=p4ssw0rd,",
424    "imaps://user:p4ssw0rd;updated@host/",
425    0, 0, CURLUE_NO_HOST},
426   {"imap://user:secret;optit@host/",
427    "scheme=https,",
428    "https://user:secret@host/",
429    0, 0, CURLUE_NO_HOST},
430   {"file:///file#anchor",
431    "scheme=https,host=example,",
432    "https://example/file#anchor",
433    0, 0, CURLUE_NO_HOST},
434   {NULL, /* start fresh! */
435    "scheme=file,host=127.0.0.1,path=/no,user=anonymous,",
436    "file:///no",
437    0, 0, CURLUE_OK},
438   {NULL, /* start fresh! */
439    "scheme=ftp,host=127.0.0.1,path=/no,user=anonymous,",
440    "ftp://anonymous@127.0.0.1/no",
441    0, 0, CURLUE_OK},
442   {NULL, /* start fresh! */
443    "scheme=https,host=example.com,",
444    "https://example.com/",
445    0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK},
446   {"http://user:foo@example.com/path?query#frag",
447    "fragment=changed,",
448    "http://user:foo@example.com/path?query#changed",
449    0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK},
450   {"http://example.com/",
451    "scheme=foo,", /* not accepted */
452    "http://example.com/",
453    0, 0, CURLUE_OK},
454   {"http://example.com/",
455    "scheme=https,path=/hello,fragment=snippet,",
456    "https://example.com/hello#snippet",
457    0, 0, CURLUE_OK},
458   {"http://example.com:80",
459    "user=foo,port=1922,",
460    "http://foo@example.com:1922/",
461    0, 0, CURLUE_OK},
462   {"http://example.com:80",
463    "user=foo,password=bar,",
464    "http://foo:bar@example.com:80/",
465    0, 0, CURLUE_OK},
466   {"http://example.com:80",
467    "user=foo,",
468    "http://foo@example.com:80/",
469    0, 0, CURLUE_OK},
470   {"http://example.com",
471    "host=www.example.com,",
472    "http://www.example.com/",
473    0, 0, CURLUE_OK},
474   {"http://example.com:80",
475    "scheme=ftp,",
476    "ftp://example.com:80/",
477    0, 0, CURLUE_OK},
478   {NULL, NULL, NULL, 0, 0, 0}
479 };
480 
part2id(char * part)481 static CURLUPart part2id(char *part)
482 {
483   if(!strcmp("url", part))
484     return CURLUPART_URL;
485   if(!strcmp("scheme", part))
486     return CURLUPART_SCHEME;
487   if(!strcmp("user", part))
488     return CURLUPART_USER;
489   if(!strcmp("password", part))
490     return CURLUPART_PASSWORD;
491   if(!strcmp("options", part))
492     return CURLUPART_OPTIONS;
493   if(!strcmp("host", part))
494     return CURLUPART_HOST;
495   if(!strcmp("port", part))
496     return CURLUPART_PORT;
497   if(!strcmp("path", part))
498     return CURLUPART_PATH;
499   if(!strcmp("query", part))
500     return CURLUPART_QUERY;
501   if(!strcmp("fragment", part))
502     return CURLUPART_FRAGMENT;
503   return 9999; /* bad input => bad output */
504 }
505 
updateurl(CURLU * u,const char * cmd,unsigned int setflags)506 static void updateurl(CURLU *u, const char *cmd, unsigned int setflags)
507 {
508   const char *p = cmd;
509 
510   /* make sure the last command ends with a comma too! */
511   while(p) {
512     char *e = strchr(p, ',');
513     if(e) {
514       size_t n = e-p;
515       char buf[80];
516       char part[80];
517       char value[80];
518       memcpy(buf, p, n);
519       buf[n] = 0;
520       if(2 == sscanf(buf, "%79[^=]=%79[^,]", part, value)) {
521         CURLUPart what = part2id(part);
522 #if 0
523         /* for debugging this */
524         fprintf(stderr, "%s = %s [%d]\n", part, value, (int)what);
525 #endif
526         if(!strcmp("NULL", value))
527           curl_url_set(u, what, NULL, setflags);
528         else
529           curl_url_set(u, what, value, setflags);
530       }
531       p = e + 1;
532       continue;
533     }
534     break;
535   }
536 
537 }
538 
539 static struct redircase set_url_list[] = {
540   {"file://localhost/path?query#frag",
541    "foo#another",
542    "file:///foo#another",
543    0, 0, 0},
544   {"http://example.com/path?query#frag",
545    "https://two.example.com/bradnew",
546    "https://two.example.com/bradnew",
547    0, 0, 0},
548   {"http://example.com/path?query#frag",
549    "../../newpage#foo",
550    "http://example.com/newpage#foo",
551    0, 0, 0},
552   {"http://user:foo@example.com/path?query#frag",
553    "../../newpage",
554    "http://user:foo@example.com/newpage",
555    0, 0, 0},
556   {"http://user:foo@example.com/path?query#frag",
557    "../newpage",
558    "http://user:foo@example.com/newpage",
559    0, 0, 0},
560   {NULL, NULL, NULL, 0, 0, 0}
561 };
562 
set_url(void)563 static int set_url(void)
564 {
565   int i;
566   CURLUcode rc;
567   CURLU *urlp;
568   int error = 0;
569 
570   for(i = 0; set_url_list[i].in && !error; i++) {
571     char *url = NULL;
572     urlp = curl_url();
573     if(!urlp)
574       break;
575     rc = curl_url_set(urlp, CURLUPART_URL, set_url_list[i].in,
576                       set_url_list[i].urlflags);
577     if(!rc) {
578       rc = curl_url_set(urlp, CURLUPART_URL, set_url_list[i].set,
579                         set_url_list[i].setflags);
580       if(rc) {
581         fprintf(stderr, "%s:%d Set URL %s returned %d\n",
582                 __FILE__, __LINE__, set_url_list[i].set,
583                 (int)rc);
584         error++;
585       }
586       else {
587         rc = curl_url_get(urlp, CURLUPART_URL, &url, 0);
588         if(rc) {
589           fprintf(stderr, "%s:%d Get URL returned %d\n",
590                   __FILE__, __LINE__, (int)rc);
591           error++;
592         }
593         else {
594           if(checkurl(url, set_url_list[i].out)) {
595             error++;
596           }
597         }
598       }
599       curl_free(url);
600     }
601     else if(rc != set_url_list[i].ucode) {
602       fprintf(stderr, "Set URL\nin: %s\nreturned %d (expected %d)\n",
603               set_url_list[i].in, (int)rc, set_url_list[i].ucode);
604       error++;
605     }
606     curl_url_cleanup(urlp);
607   }
608   return error;
609 }
610 
set_parts(void)611 static int set_parts(void)
612 {
613   int i;
614   CURLUcode rc;
615   int error = 0;
616 
617   for(i = 0; set_parts_list[i].set && !error; i++) {
618     char *url = NULL;
619     CURLU *urlp = curl_url();
620     if(!urlp) {
621       error++;
622       break;
623     }
624     if(set_parts_list[i].in)
625       rc = curl_url_set(urlp, CURLUPART_URL, set_parts_list[i].in,
626                         set_parts_list[i].urlflags);
627     else
628       rc = CURLUE_OK;
629     if(!rc) {
630       updateurl(urlp, set_parts_list[i].set, set_parts_list[i].setflags);
631       rc = curl_url_get(urlp, CURLUPART_URL, &url, 0);
632 
633       if(rc) {
634         fprintf(stderr, "%s:%d Get URL returned %d\n",
635                 __FILE__, __LINE__, (int)rc);
636         error++;
637       }
638       else if(checkurl(url, set_parts_list[i].out)) {
639         error++;
640       }
641     }
642     else if(rc != set_parts_list[i].ucode) {
643       fprintf(stderr, "Set parts\nin: %s\nreturned %d (expected %d)\n",
644               set_parts_list[i].in, (int)rc, set_parts_list[i].ucode);
645       error++;
646     }
647     curl_free(url);
648     curl_url_cleanup(urlp);
649   }
650   return error;
651 }
652 
get_url(void)653 static int get_url(void)
654 {
655   int i;
656   CURLUcode rc;
657   int error = 0;
658   for(i = 0; get_url_list[i].in && !error; i++) {
659     char *url = NULL;
660     CURLU *urlp = curl_url();
661     if(!urlp) {
662       error++;
663       break;
664     }
665     rc = curl_url_set(urlp, CURLUPART_URL, get_url_list[i].in,
666                       get_url_list[i].urlflags);
667     if(!rc) {
668       rc = curl_url_get(urlp, CURLUPART_URL, &url, get_url_list[i].getflags);
669 
670       if(rc) {
671         fprintf(stderr, "%s:%d returned %d\n",
672                 __FILE__, __LINE__, (int)rc);
673         error++;
674       }
675       else {
676         if(checkurl(url, get_url_list[i].out)) {
677           error++;
678         }
679       }
680     }
681     else if(rc != get_url_list[i].ucode) {
682       fprintf(stderr, "Get URL\nin: %s\nreturned %d (expected %d)\n",
683               get_url_list[i].in, (int)rc, get_url_list[i].ucode);
684       error++;
685     }
686     curl_free(url);
687     curl_url_cleanup(urlp);
688   }
689   return error;
690 }
691 
get_parts(void)692 static int get_parts(void)
693 {
694   int i;
695   CURLUcode rc;
696   CURLU *urlp;
697   int error = 0;
698   for(i = 0; get_parts_list[i].in && !error; i++) {
699     urlp = curl_url();
700     if(!urlp) {
701       error++;
702       break;
703     }
704     rc = curl_url_set(urlp, CURLUPART_URL,
705                       get_parts_list[i].in,
706                       get_parts_list[i].urlflags);
707     if(rc != get_parts_list[i].ucode) {
708       fprintf(stderr, "Get parts\nin: %s\nreturned %d (expected %d)\n",
709               get_parts_list[i].in, (int)rc, get_parts_list[i].ucode);
710       error++;
711     }
712     else if(get_parts_list[i].ucode) {
713       /* the expected error happened */
714     }
715     else if(checkparts(urlp, get_parts_list[i].in, get_parts_list[i].out,
716                        get_parts_list[i].getflags))
717       error++;
718     curl_url_cleanup(urlp);
719   }
720   return error;
721 }
722 
723 static struct querycase append_list[] = {
724   {"HTTP://test/?s", "name=joe\x02", "http://test/?s&name=joe%02",
725    0, CURLU_URLENCODE, CURLUE_OK},
726   {"HTTP://test/?size=2#f", "name=joe=", "http://test/?size=2&name=joe%3d#f",
727    0, CURLU_URLENCODE, CURLUE_OK},
728   {"HTTP://test/?size=2#f", "name=joe doe",
729    "http://test/?size=2&name=joe+doe#f",
730    0, CURLU_URLENCODE, CURLUE_OK},
731   {"HTTP://test/", "name=joe", "http://test/?name=joe", 0, 0, CURLUE_OK},
732   {"HTTP://test/?size=2", "name=joe", "http://test/?size=2&name=joe",
733    0, 0, CURLUE_OK},
734   {"HTTP://test/?size=2&", "name=joe", "http://test/?size=2&name=joe",
735    0, 0, CURLUE_OK},
736   {"HTTP://test/?size=2#f", "name=joe", "http://test/?size=2&name=joe#f",
737    0, 0, CURLUE_OK},
738   {NULL, NULL, NULL, 0, 0, 0}
739 };
740 
append(void)741 static int append(void)
742 {
743   int i;
744   CURLUcode rc;
745   CURLU *urlp;
746   int error = 0;
747   for(i = 0; append_list[i].in && !error; i++) {
748     urlp = curl_url();
749     if(!urlp) {
750       error++;
751       break;
752     }
753     rc = curl_url_set(urlp, CURLUPART_URL,
754                       append_list[i].in,
755                       append_list[i].urlflags);
756     if(rc)
757       error++;
758     else
759       rc = curl_url_set(urlp, CURLUPART_QUERY,
760                         append_list[i].q,
761                         append_list[i].qflags | CURLU_APPENDQUERY);
762     if(error)
763       ;
764     else if(rc != append_list[i].ucode) {
765       fprintf(stderr, "Append\nin: %s\nreturned %d (expected %d)\n",
766               append_list[i].in, (int)rc, append_list[i].ucode);
767       error++;
768     }
769     else if(append_list[i].ucode) {
770       /* the expected error happened */
771     }
772     else {
773       char *url;
774       rc = curl_url_get(urlp, CURLUPART_URL, &url, 0);
775       if(rc) {
776         fprintf(stderr, "%s:%d Get URL returned %d\n",
777                 __FILE__, __LINE__, (int)rc);
778         error++;
779       }
780       else {
781         if(checkurl(url, append_list[i].out)) {
782           error++;
783         }
784         curl_free(url);
785       }
786     }
787     curl_url_cleanup(urlp);
788   }
789   return error;
790 }
791 
test(char * URL)792 int test(char *URL)
793 {
794   (void)URL; /* not used */
795 
796   if(append())
797     return 5;
798 
799   if(set_url())
800     return 1;
801 
802   if(set_parts())
803     return 2;
804 
805   if(get_url())
806     return 3;
807 
808   if(get_parts())
809     return 4;
810 
811   printf("success\n");
812   return 0;
813 }
814