lib1560.c 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2022, Daniel Stenberg, <[email protected]>, 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. * Note:
  26. *
  27. * Since the URL parser by default only accepts schemes that *this instance*
  28. * of libcurl supports, make sure that the test1560 file lists all the schemes
  29. * that this test will assume to be present!
  30. */
  31. #include "test.h"
  32. #include "testutil.h"
  33. #include "warnless.h"
  34. #include "memdebug.h" /* LAST include file */
  35. struct part {
  36. CURLUPart part;
  37. const char *name;
  38. };
  39. static int checkparts(CURLU *u, const char *in, const char *wanted,
  40. unsigned int getflags)
  41. {
  42. int i;
  43. CURLUcode rc;
  44. char buf[256];
  45. char *bufp = &buf[0];
  46. size_t len = sizeof(buf);
  47. struct part parts[] = {
  48. {CURLUPART_SCHEME, "scheme"},
  49. {CURLUPART_USER, "user"},
  50. {CURLUPART_PASSWORD, "password"},
  51. {CURLUPART_OPTIONS, "options"},
  52. {CURLUPART_HOST, "host"},
  53. {CURLUPART_PORT, "port"},
  54. {CURLUPART_PATH, "path"},
  55. {CURLUPART_QUERY, "query"},
  56. {CURLUPART_FRAGMENT, "fragment"},
  57. {CURLUPART_URL, NULL}
  58. };
  59. memset(buf, 0, sizeof(buf));
  60. for(i = 0; parts[i].name; i++) {
  61. char *p = NULL;
  62. size_t n;
  63. rc = curl_url_get(u, parts[i].part, &p, getflags);
  64. if(!rc && p) {
  65. msnprintf(bufp, len, "%s%s", buf[0]?" | ":"", p);
  66. }
  67. else
  68. msnprintf(bufp, len, "%s[%d]", buf[0]?" | ":"", (int)rc);
  69. n = strlen(bufp);
  70. bufp += n;
  71. len -= n;
  72. curl_free(p);
  73. }
  74. if(strcmp(buf, wanted)) {
  75. fprintf(stderr, "in: %s\nwanted: %s\ngot: %s\n", in, wanted, buf);
  76. return 1;
  77. }
  78. return 0;
  79. }
  80. struct redircase {
  81. const char *in;
  82. const char *set;
  83. const char *out;
  84. unsigned int urlflags;
  85. unsigned int setflags;
  86. CURLUcode ucode;
  87. };
  88. struct setcase {
  89. const char *in;
  90. const char *set;
  91. const char *out;
  92. unsigned int urlflags;
  93. unsigned int setflags;
  94. CURLUcode ucode; /* for the main URL set */
  95. CURLUcode pcode; /* for updating parts */
  96. };
  97. struct testcase {
  98. const char *in;
  99. const char *out;
  100. unsigned int urlflags;
  101. unsigned int getflags;
  102. CURLUcode ucode;
  103. };
  104. struct urltestcase {
  105. const char *in;
  106. const char *out;
  107. unsigned int urlflags; /* pass to curl_url() */
  108. unsigned int getflags; /* pass to curl_url_get() */
  109. CURLUcode ucode;
  110. };
  111. struct querycase {
  112. const char *in;
  113. const char *q;
  114. const char *out;
  115. unsigned int urlflags; /* pass to curl_url() */
  116. unsigned int qflags; /* pass to curl_url_get() */
  117. CURLUcode ucode;
  118. };
  119. struct clearurlcase {
  120. CURLUPart part;
  121. const char *in;
  122. const char *out;
  123. CURLUcode ucode;
  124. };
  125. static const struct testcase get_parts_list[] ={
  126. {"https://user:[email protected]/get?this=and#but frag then", "",
  127. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_FRAGMENT},
  128. {"https://user:[email protected]/get?this=and what", "",
  129. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_QUERY},
  130. {"https://user:[email protected]/ge t?this=and-what", "",
  131. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PATH},
  132. {"https://user:pass [email protected]/get?this=and-what", "",
  133. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PASSWORD},
  134. {"https://u ser:[email protected]/get?this=and-what", "",
  135. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_USER},
  136. {"imap://user:pass;opt ion@server/path", "",
  137. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_LOGIN},
  138. /* no space allowed in scheme */
  139. {"htt ps://user:[email protected]/get?this=and-what", "",
  140. CURLU_NON_SUPPORT_SCHEME|CURLU_ALLOW_SPACE, 0, CURLUE_BAD_SCHEME},
  141. {"https://user:[email protected]/get?this=and what",
  142. "https | user | password | [13] | example.net | [15] | /get | "
  143. "this=and what | [17]",
  144. CURLU_ALLOW_SPACE, 0, CURLUE_OK},
  145. {"https://user:[email protected]/ge t?this=and-what",
  146. "https | user | password | [13] | example.net | [15] | /ge t | "
  147. "this=and-what | [17]",
  148. CURLU_ALLOW_SPACE, 0, CURLUE_OK},
  149. {"https://user:pass [email protected]/get?this=and-what",
  150. "https | user | pass word | [13] | example.net | [15] | /get | "
  151. "this=and-what | [17]",
  152. CURLU_ALLOW_SPACE, 0, CURLUE_OK},
  153. {"https://u ser:[email protected]/get?this=and-what",
  154. "https | u ser | password | [13] | example.net | [15] | /get | "
  155. "this=and-what | [17]",
  156. CURLU_ALLOW_SPACE, 0, CURLUE_OK},
  157. {"https://user:[email protected]/ge t?this=and-what",
  158. "https | user | password | [13] | example.net | [15] | /ge%20t | "
  159. "this=and-what | [17]",
  160. CURLU_ALLOW_SPACE | CURLU_URLENCODE, 0, CURLUE_OK},
  161. {"[0:0:0:0:0:0:0:1]",
  162. "http | [11] | [12] | [13] | [::1] | [15] | / | [16] | [17]",
  163. CURLU_GUESS_SCHEME, 0, CURLUE_OK },
  164. {"[::1]",
  165. "http | [11] | [12] | [13] | [::1] | [15] | / | [16] | [17]",
  166. CURLU_GUESS_SCHEME, 0, CURLUE_OK },
  167. {"[::]",
  168. "http | [11] | [12] | [13] | [::] | [15] | / | [16] | [17]",
  169. CURLU_GUESS_SCHEME, 0, CURLUE_OK },
  170. {"https://[::1]",
  171. "https | [11] | [12] | [13] | [::1] | [15] | / | [16] | [17]",
  172. 0, 0, CURLUE_OK },
  173. {"user:[email protected]/color/#green?no-red",
  174. "ftp | user | moo | [13] | ftp.example.com | [15] | /color/ | [16] | "
  175. "green?no-red",
  176. CURLU_GUESS_SCHEME, 0, CURLUE_OK },
  177. {"ftp.user:[email protected]/color/#green?no-red",
  178. "http | ftp.user | moo | [13] | example.com | [15] | /color/ | [16] | "
  179. "green?no-red",
  180. CURLU_GUESS_SCHEME, 0, CURLUE_OK },
  181. #ifdef WIN32
  182. {"file:/C:\\programs\\foo",
  183. "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
  184. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  185. {"file://C:\\programs\\foo",
  186. "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
  187. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  188. {"file:///C:\\programs\\foo",
  189. "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
  190. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  191. {"file://host.example.com/Share/path/to/file.txt",
  192. "file | [11] | [12] | [13] | host.example.com | [15] | "
  193. "//host.example.com/Share/path/to/file.txt | [16] | [17]",
  194. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  195. #endif
  196. {"https://example.com/color/#green?no-red",
  197. "https | [11] | [12] | [13] | example.com | [15] | /color/ | [16] | "
  198. "green?no-red",
  199. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
  200. {"https://example.com/color/#green#no-red",
  201. "https | [11] | [12] | [13] | example.com | [15] | /color/ | [16] | "
  202. "green#no-red",
  203. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
  204. {"https://example.com/color/?green#no-red",
  205. "https | [11] | [12] | [13] | example.com | [15] | /color/ | green | "
  206. "no-red",
  207. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
  208. {"https://example.com/#color/?green#no-red",
  209. "https | [11] | [12] | [13] | example.com | [15] | / | [16] | "
  210. "color/?green#no-red",
  211. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
  212. {"https://example.#com/color/?green#no-red",
  213. "https | [11] | [12] | [13] | example. | [15] | / | [16] | "
  214. "com/color/?green#no-red",
  215. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
  216. {"http://[ab.be:1]/x", "",
  217. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_IPV6},
  218. {"http://[ab.be]/x", "",
  219. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_IPV6},
  220. /* URL without host name */
  221. {"http://a:b@/x", "",
  222. CURLU_DEFAULT_SCHEME, 0, CURLUE_NO_HOST},
  223. {"boing:80",
  224. "https | [11] | [12] | [13] | boing | 80 | / | [16] | [17]",
  225. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  226. {"http://[fd00:a41::50]:8080",
  227. "http | [11] | [12] | [13] | [fd00:a41::50] | 8080 | / | [16] | [17]",
  228. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  229. {"http://[fd00:a41::50]/",
  230. "http | [11] | [12] | [13] | [fd00:a41::50] | [15] | / | [16] | [17]",
  231. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  232. {"http://[fd00:a41::50]",
  233. "http | [11] | [12] | [13] | [fd00:a41::50] | [15] | / | [16] | [17]",
  234. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  235. {"https://[::1%252]:1234",
  236. "https | [11] | [12] | [13] | [::1] | 1234 | / | [16] | [17]",
  237. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  238. /* here's "bad" zone id */
  239. {"https://[fe80::20c:29ff:fe9c:409b%eth0]:1234",
  240. "https | [11] | [12] | [13] | [fe80::20c:29ff:fe9c:409b] | 1234 "
  241. "| / | [16] | [17]",
  242. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  243. {"https://127.0.0.1:443",
  244. "https | [11] | [12] | [13] | 127.0.0.1 | [15] | / | [16] | [17]",
  245. 0, CURLU_NO_DEFAULT_PORT, CURLUE_OK},
  246. {"http://%3a:%3a@ex4mple/%3f+?+%3f+%23#+%23%3f%g7",
  247. "http | : | : | [13] | ex4mple | [15] | /?+ | ? # | +#?%g7",
  248. 0, CURLU_URLDECODE, CURLUE_OK},
  249. {"http://%3a:%3a@ex4mple/%3f?%3f%35#%35%3f%g7",
  250. "http | %3a | %3a | [13] | ex4mple | [15] | /%3f | %3f%35 | %35%3f%g7",
  251. 0, 0, CURLUE_OK},
  252. {"http://HO0_-st%41/",
  253. "http | [11] | [12] | [13] | HO0_-stA | [15] | / | [16] | [17]",
  254. 0, 0, CURLUE_OK},
  255. {"file://hello.html",
  256. "",
  257. 0, 0, CURLUE_BAD_FILE_URL},
  258. {"http://HO0_-st/",
  259. "http | [11] | [12] | [13] | HO0_-st | [15] | / | [16] | [17]",
  260. 0, 0, CURLUE_OK},
  261. {"imap://user:pass;option@server/path",
  262. "imap | user | pass | option | server | [15] | /path | [16] | [17]",
  263. 0, 0, CURLUE_OK},
  264. {"http://user:pass;option@server/path",
  265. "http | user | pass;option | [13] | server | [15] | /path | [16] | [17]",
  266. 0, 0, CURLUE_OK},
  267. {"file:/hello.html",
  268. "file | [11] | [12] | [13] | [14] | [15] | /hello.html | [16] | [17]",
  269. 0, 0, CURLUE_OK},
  270. {"file:/h",
  271. "file | [11] | [12] | [13] | [14] | [15] | /h | [16] | [17]",
  272. 0, 0, CURLUE_OK},
  273. {"file:/",
  274. "file | [11] | [12] | [13] | [14] | [15] | | [16] | [17]",
  275. 0, 0, CURLUE_BAD_FILE_URL},
  276. {"file://127.0.0.1/hello.html",
  277. "file | [11] | [12] | [13] | [14] | [15] | /hello.html | [16] | [17]",
  278. 0, 0, CURLUE_OK},
  279. {"file:////hello.html",
  280. "file | [11] | [12] | [13] | [14] | [15] | //hello.html | [16] | [17]",
  281. 0, 0, CURLUE_OK},
  282. {"file:///hello.html",
  283. "file | [11] | [12] | [13] | [14] | [15] | /hello.html | [16] | [17]",
  284. 0, 0, CURLUE_OK},
  285. {"https://127.0.0.1",
  286. "https | [11] | [12] | [13] | 127.0.0.1 | 443 | / | [16] | [17]",
  287. 0, CURLU_DEFAULT_PORT, CURLUE_OK},
  288. {"https://127.0.0.1",
  289. "https | [11] | [12] | [13] | 127.0.0.1 | [15] | / | [16] | [17]",
  290. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  291. {"https://[::1]:1234",
  292. "https | [11] | [12] | [13] | [::1] | 1234 | / | [16] | [17]",
  293. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  294. {"https://127abc.com",
  295. "https | [11] | [12] | [13] | 127abc.com | [15] | / | [16] | [17]",
  296. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  297. {"https:// example.com?check", "",
  298. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_HOSTNAME},
  299. {"https://e x a m p l e.com?check", "",
  300. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_HOSTNAME},
  301. {"https://example.com?check",
  302. "https | [11] | [12] | [13] | example.com | [15] | / | check | [17]",
  303. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  304. {"https://example.com:65536",
  305. "",
  306. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PORT_NUMBER},
  307. {"https://example.com:-1#moo",
  308. "",
  309. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PORT_NUMBER},
  310. {"https://example.com:0#moo",
  311. "https | [11] | [12] | [13] | example.com | 0 | / | "
  312. "[16] | moo",
  313. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  314. {"https://example.com:01#moo",
  315. "https | [11] | [12] | [13] | example.com | 1 | / | "
  316. "[16] | moo",
  317. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  318. {"https://example.com:1#moo",
  319. "https | [11] | [12] | [13] | example.com | 1 | / | "
  320. "[16] | moo",
  321. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  322. {"http://example.com#moo",
  323. "http | [11] | [12] | [13] | example.com | [15] | / | "
  324. "[16] | moo",
  325. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  326. {"http://example.com",
  327. "http | [11] | [12] | [13] | example.com | [15] | / | "
  328. "[16] | [17]",
  329. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  330. {"http://example.com/path/html",
  331. "http | [11] | [12] | [13] | example.com | [15] | /path/html | "
  332. "[16] | [17]",
  333. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  334. {"http://example.com/path/html?query=name",
  335. "http | [11] | [12] | [13] | example.com | [15] | /path/html | "
  336. "query=name | [17]",
  337. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  338. {"http://example.com/path/html?query=name#anchor",
  339. "http | [11] | [12] | [13] | example.com | [15] | /path/html | "
  340. "query=name | anchor",
  341. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  342. {"http://example.com:1234/path/html?query=name#anchor",
  343. "http | [11] | [12] | [13] | example.com | 1234 | /path/html | "
  344. "query=name | anchor",
  345. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  346. {"http:///user:[email protected]:1234/path/html?query=name#anchor",
  347. "http | user | password | [13] | example.com | 1234 | /path/html | "
  348. "query=name | anchor",
  349. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  350. {"https://user:[email protected]:1234/path/html?query=name#anchor",
  351. "https | user | password | [13] | example.com | 1234 | /path/html | "
  352. "query=name | anchor",
  353. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  354. {"http://user:[email protected]:1234/path/html?query=name#anchor",
  355. "http | user | password | [13] | example.com | 1234 | /path/html | "
  356. "query=name | anchor",
  357. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  358. {"http:/user:[email protected]:1234/path/html?query=name#anchor",
  359. "http | user | password | [13] | example.com | 1234 | /path/html | "
  360. "query=name | anchor",
  361. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  362. {"http:////user:[email protected]:1234/path/html?query=name#anchor",
  363. "",
  364. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_SLASHES},
  365. {NULL, NULL, 0, 0, CURLUE_OK},
  366. };
  367. static const struct urltestcase get_url_list[] = {
  368. /* percent encoded host names */
  369. {"http://example.com%40127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
  370. {"http://example.com%21127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
  371. {"http://example.com%3f127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
  372. {"http://example.com%23127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
  373. {"http://example.com%3a127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
  374. {"http://example.com%09127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
  375. {"http://example.com%2F127.0.0.1/", "", 0, 0, CURLUE_BAD_HOSTNAME},
  376. {"https://%this", "https://%25this/", 0, 0, CURLUE_OK},
  377. {"https://h%c", "https://h%25c/", 0, 0, CURLUE_OK},
  378. {"https://%%%%%%", "https://%25%25%25%25%25%25/", 0, 0, CURLUE_OK},
  379. {"https://%41", "https://A/", 0, 0, CURLUE_OK},
  380. {"https://%20", "", 0, 0, CURLUE_BAD_HOSTNAME},
  381. {"https://%41%0d", "", 0, 0, CURLUE_BAD_HOSTNAME},
  382. {"https://%25", "https://%25/", 0, 0, CURLUE_OK},
  383. {"https://_%c0_", "https://_\xC0_/", 0, 0, CURLUE_OK},
  384. {"https://_%c0_", "https://_%C0_/", 0, CURLU_URLENCODE, CURLUE_OK},
  385. /* IPv4 trickeries */
  386. {"https://16843009", "https://1.1.1.1/", 0, 0, CURLUE_OK},
  387. {"https://0x7f.1", "https://127.0.0.1/", 0, 0, CURLUE_OK},
  388. {"https://0177.1", "https://127.0.0.1/", 0, 0, CURLUE_OK},
  389. {"https://0111.02.0x3", "https://73.2.0.3/", 0, 0, CURLUE_OK},
  390. {"https://0xff.0xff.0377.255", "https://255.255.255.255/", 0, 0, CURLUE_OK},
  391. {"https://1.0xffffff", "https://1.255.255.255/", 0, 0, CURLUE_OK},
  392. /* IPv4 numerical overflows or syntax errors will not normalize */
  393. {"https://+127.0.0.1", "https://+127.0.0.1/", 0, 0, CURLUE_OK},
  394. {"https://+127.0.0.1", "https://%2B127.0.0.1/", 0, CURLU_URLENCODE,
  395. CURLUE_OK},
  396. {"https://127.-0.0.1", "https://127.-0.0.1/", 0, 0, CURLUE_OK},
  397. {"https://127.0. 1", "https://127.0.0.1/", 0, 0, CURLUE_BAD_HOSTNAME},
  398. {"https://1.0x1000000", "https://1.0x1000000/", 0, 0, CURLUE_OK},
  399. {"https://1.2.3.256", "https://1.2.3.256/", 0, 0, CURLUE_OK},
  400. {"https://1.2.3.4.5", "https://1.2.3.4.5/", 0, 0, CURLUE_OK},
  401. {"https://1.2.0x100.3", "https://1.2.0x100.3/", 0, 0, CURLUE_OK},
  402. {"https://4294967296", "https://4294967296/", 0, 0, CURLUE_OK},
  403. /* 40 bytes scheme is the max allowed */
  404. {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA://hostname/path",
  405. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa://hostname/path",
  406. CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
  407. /* 41 bytes scheme is not allowed */
  408. {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA://hostname/path",
  409. "",
  410. CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_BAD_SCHEME},
  411. {"https://[fe80::20c:29ff:fe9c:409b%]:1234",
  412. "",
  413. 0, 0, CURLUE_BAD_IPV6},
  414. {"https://[fe80::20c:29ff:fe9c:409b%25]:1234",
  415. "https://[fe80::20c:29ff:fe9c:409b%2525]:1234/",
  416. 0, 0, CURLUE_OK},
  417. {"https://[fe80::20c:29ff:fe9c:409b%eth0]:1234",
  418. "https://[fe80::20c:29ff:fe9c:409b%25eth0]:1234/",
  419. 0, 0, CURLUE_OK},
  420. {"https://[::%25fakeit]/moo",
  421. "https://[::%25fakeit]/moo",
  422. 0, 0, CURLUE_OK},
  423. {"smtp.example.com/path/html",
  424. "smtp://smtp.example.com/path/html",
  425. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  426. {"https.example.com/path/html",
  427. "http://https.example.com/path/html",
  428. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  429. {"dict.example.com/path/html",
  430. "dict://dict.example.com/path/html",
  431. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  432. {"pop3.example.com/path/html",
  433. "pop3://pop3.example.com/path/html",
  434. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  435. {"ldap.example.com/path/html",
  436. "ldap://ldap.example.com/path/html",
  437. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  438. {"imap.example.com/path/html",
  439. "imap://imap.example.com/path/html",
  440. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  441. {"ftp.example.com/path/html",
  442. "ftp://ftp.example.com/path/html",
  443. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  444. {"example.com/path/html",
  445. "http://example.com/path/html",
  446. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  447. {"HTTP://test/", "http://test/", 0, 0, CURLUE_OK},
  448. {"http://HO0_-st..~./", "http://HO0_-st..~./", 0, 0, CURLUE_OK},
  449. {"http:/@example.com: 123/", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
  450. {"http:/@example.com:123 /", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
  451. {"http:/@example.com:123a/", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
  452. {"http://host/file\r", "", 0, 0, CURLUE_BAD_PATH},
  453. {"http://host/file\n\x03", "", 0, 0, CURLUE_BAD_PATH},
  454. {"htt\x02://host/file", "",
  455. CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_BAD_SCHEME},
  456. {" http://host/file", "", 0, 0, CURLUE_BAD_SCHEME},
  457. /* here the password ends at the semicolon and options is 'word' */
  458. {"imap://user:pass;word@host/file",
  459. "imap://user:pass;word@host/file",
  460. 0, 0, CURLUE_OK},
  461. /* here the password has the semicolon */
  462. {"http://user:pass;word@host/file",
  463. "http://user:pass;word@host/file",
  464. 0, 0, CURLUE_OK},
  465. {"file:///file.txt#moo",
  466. "file:///file.txt#moo",
  467. 0, 0, CURLUE_OK},
  468. {"file:////file.txt",
  469. "file:////file.txt",
  470. 0, 0, CURLUE_OK},
  471. {"file:///file.txt",
  472. "file:///file.txt",
  473. 0, 0, CURLUE_OK},
  474. {"file:./",
  475. "file://",
  476. 0, 0, CURLUE_BAD_SCHEME},
  477. {"http://example.com/hello/../here",
  478. "http://example.com/hello/../here",
  479. CURLU_PATH_AS_IS, 0, CURLUE_OK},
  480. {"http://example.com/hello/../here",
  481. "http://example.com/here",
  482. 0, 0, CURLUE_OK},
  483. {"http://example.com:80",
  484. "http://example.com/",
  485. 0, CURLU_NO_DEFAULT_PORT, CURLUE_OK},
  486. {"tp://example.com/path/html",
  487. "",
  488. 0, 0, CURLUE_UNSUPPORTED_SCHEME},
  489. {"http://hello:[email protected]",
  490. "",
  491. CURLU_DISALLOW_USER, 0, CURLUE_USER_NOT_ALLOWED},
  492. {"http:/@example.com:123",
  493. "http://example.com:123/",
  494. 0, 0, CURLUE_OK},
  495. {"http:/:[email protected]",
  496. "http://:[email protected]/",
  497. 0, 0, CURLUE_OK},
  498. {"http://[email protected]?#",
  499. "http://[email protected]/",
  500. 0, 0, CURLUE_OK},
  501. {"http://[email protected]?",
  502. "http://[email protected]/",
  503. 0, 0, CURLUE_OK},
  504. {"http://[email protected]#anchor",
  505. "http://[email protected]/#anchor",
  506. 0, 0, CURLUE_OK},
  507. {"example.com/path/html",
  508. "https://example.com/path/html",
  509. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  510. {"example.com/path/html",
  511. "",
  512. 0, 0, CURLUE_BAD_SCHEME},
  513. {"http://user:[email protected]:1234/path/html?query=name#anchor",
  514. "http://user:[email protected]:1234/path/html?query=name#anchor",
  515. 0, 0, CURLUE_OK},
  516. {"http://example.com:1234/path/html?query=name#anchor",
  517. "http://example.com:1234/path/html?query=name#anchor",
  518. 0, 0, CURLUE_OK},
  519. {"http://example.com/path/html?query=name#anchor",
  520. "http://example.com/path/html?query=name#anchor",
  521. 0, 0, CURLUE_OK},
  522. {"http://example.com/path/html?query=name",
  523. "http://example.com/path/html?query=name",
  524. 0, 0, CURLUE_OK},
  525. {"http://example.com/path/html",
  526. "http://example.com/path/html",
  527. 0, 0, CURLUE_OK},
  528. {"tp://example.com/path/html",
  529. "tp://example.com/path/html",
  530. CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
  531. {"custom-scheme://host?expected=test-good",
  532. "custom-scheme://host/?expected=test-good",
  533. CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
  534. {"custom-scheme://?expected=test-bad",
  535. "",
  536. CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_NO_HOST},
  537. {"custom-scheme://?expected=test-new-good",
  538. "custom-scheme:///?expected=test-new-good",
  539. CURLU_NON_SUPPORT_SCHEME | CURLU_NO_AUTHORITY, 0, CURLUE_OK},
  540. {"custom-scheme://host?expected=test-still-good",
  541. "custom-scheme://host/?expected=test-still-good",
  542. CURLU_NON_SUPPORT_SCHEME | CURLU_NO_AUTHORITY, 0, CURLUE_OK},
  543. {NULL, NULL, 0, 0, CURLUE_OK}
  544. };
  545. static int checkurl(const char *url, const char *out)
  546. {
  547. if(strcmp(out, url)) {
  548. fprintf(stderr, "Wanted: %s\nGot : %s\n",
  549. out, url);
  550. return 1;
  551. }
  552. return 0;
  553. }
  554. /* !checksrc! disable SPACEBEFORECOMMA 1 */
  555. static const struct setcase set_parts_list[] = {
  556. {"https://example.com/",
  557. "host=++,", /* '++' there's no automatic URL decode when settin this
  558. part */
  559. "https://++/",
  560. 0, /* get */
  561. 0, /* set */
  562. CURLUE_OK, CURLUE_OK},
  563. {"https://example.com/",
  564. "query=Al2cO3tDkcDZ3EWE5Lh+LX8TPHs,", /* contains '+' */
  565. "https://example.com/?Al2cO3tDkcDZ3EWE5Lh%2bLX8TPHs",
  566. CURLU_URLDECODE, /* decode on get */
  567. CURLU_URLENCODE, /* encode on set */
  568. CURLUE_OK, CURLUE_OK},
  569. {"https://example.com/",
  570. /* Set a 41 bytes scheme. That's too long so the old scheme remains set. */
  571. "scheme=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc,",
  572. "https://example.com/",
  573. 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_BAD_SCHEME},
  574. {"https://example.com/",
  575. /* set a 40 bytes scheme */
  576. "scheme=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,",
  577. "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb://example.com/",
  578. 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_OK},
  579. {"https://[::1%25fake]:1234/",
  580. "zoneid=NULL,",
  581. "https://[::1]:1234/",
  582. 0, 0, CURLUE_OK, CURLUE_OK},
  583. {"https://host:1234/",
  584. "port=NULL,",
  585. "https://host/",
  586. 0, 0, CURLUE_OK, CURLUE_OK},
  587. {"https://host:1234/",
  588. "port=\"\",",
  589. "https://host:1234/",
  590. 0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
  591. {"https://host:1234/",
  592. "port=56 78,",
  593. "https://host:1234/",
  594. 0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
  595. {"https://host:1234/",
  596. "port=0,",
  597. "https://host:1234/",
  598. 0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
  599. {"https://host:1234/",
  600. "port=65535,",
  601. "https://host:65535/",
  602. 0, 0, CURLUE_OK, CURLUE_OK},
  603. {"https://host:1234/",
  604. "port=65536,",
  605. "https://host:1234/",
  606. 0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
  607. {"https://host/",
  608. "path=%4A%4B%4C,",
  609. "https://host/%4a%4b%4c",
  610. 0, 0, CURLUE_OK, CURLUE_OK},
  611. {"https://host/mooo?q#f",
  612. "path=NULL,query=NULL,fragment=NULL,",
  613. "https://host/",
  614. 0, 0, CURLUE_OK, CURLUE_OK},
  615. {"https://user:secret@host/",
  616. "user=NULL,password=NULL,",
  617. "https://host/",
  618. 0, 0, CURLUE_OK, CURLUE_OK},
  619. {NULL,
  620. "scheme=https,user= @:,host=foobar,",
  621. "https://%20%20%20%40%3a@foobar/",
  622. 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
  623. /* Setting a host name with spaces is not OK: */
  624. {NULL,
  625. "scheme=https,host= ,path= ,user= ,password= ,query= ,fragment= ,",
  626. "[nothing]",
  627. 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_BAD_HOSTNAME},
  628. {NULL,
  629. "scheme=https,host=foobar,path=/this /path /is /here,",
  630. "https://foobar/this%20/path%20/is%20/here",
  631. 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
  632. {NULL,
  633. "scheme=https,host=foobar,path=\xc3\xa4\xc3\xb6\xc3\xbc,",
  634. "https://foobar/%c3%a4%c3%b6%c3%bc",
  635. 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
  636. {"imap://user:secret;opt@host/",
  637. "options=updated,scheme=imaps,password=p4ssw0rd,",
  638. "imaps://user:p4ssw0rd;updated@host/",
  639. 0, 0, CURLUE_NO_HOST, CURLUE_OK},
  640. {"imap://user:secret;optit@host/",
  641. "scheme=https,",
  642. "https://user:secret@host/",
  643. 0, 0, CURLUE_NO_HOST, CURLUE_OK},
  644. {"file:///file#anchor",
  645. "scheme=https,host=example,",
  646. "https://example/file#anchor",
  647. 0, 0, CURLUE_NO_HOST, CURLUE_OK},
  648. {NULL, /* start fresh! */
  649. "scheme=file,host=127.0.0.1,path=/no,user=anonymous,",
  650. "file:///no",
  651. 0, 0, CURLUE_OK, CURLUE_OK},
  652. {NULL, /* start fresh! */
  653. "scheme=ftp,host=127.0.0.1,path=/no,user=anonymous,",
  654. "ftp://[email protected]/no",
  655. 0, 0, CURLUE_OK, CURLUE_OK},
  656. {NULL, /* start fresh! */
  657. "scheme=https,host=example.com,",
  658. "https://example.com/",
  659. 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_OK},
  660. {"http://user:[email protected]/path?query#frag",
  661. "fragment=changed,",
  662. "http://user:[email protected]/path?query#changed",
  663. 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_OK},
  664. {"http://example.com/",
  665. "scheme=foo,", /* not accepted */
  666. "http://example.com/",
  667. 0, 0, CURLUE_OK, CURLUE_UNSUPPORTED_SCHEME},
  668. {"http://example.com/",
  669. "scheme=https,path=/hello,fragment=snippet,",
  670. "https://example.com/hello#snippet",
  671. 0, 0, CURLUE_OK, CURLUE_OK},
  672. {"http://example.com:80",
  673. "user=foo,port=1922,",
  674. "http://[email protected]:1922/",
  675. 0, 0, CURLUE_OK, CURLUE_OK},
  676. {"http://example.com:80",
  677. "user=foo,password=bar,",
  678. "http://foo:[email protected]:80/",
  679. 0, 0, CURLUE_OK, CURLUE_OK},
  680. {"http://example.com:80",
  681. "user=foo,",
  682. "http://[email protected]:80/",
  683. 0, 0, CURLUE_OK, CURLUE_OK},
  684. {"http://example.com",
  685. "host=www.example.com,",
  686. "http://www.example.com/",
  687. 0, 0, CURLUE_OK, CURLUE_OK},
  688. {"http://example.com:80",
  689. "scheme=ftp,",
  690. "ftp://example.com:80/",
  691. 0, 0, CURLUE_OK, CURLUE_OK},
  692. {"custom-scheme://host",
  693. "host=\"\",",
  694. "custom-scheme://host/",
  695. CURLU_NON_SUPPORT_SCHEME, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK,
  696. CURLUE_BAD_HOSTNAME},
  697. {"custom-scheme://host",
  698. "host=\"\",",
  699. "custom-scheme:///",
  700. CURLU_NON_SUPPORT_SCHEME, CURLU_NON_SUPPORT_SCHEME | CURLU_NO_AUTHORITY,
  701. CURLUE_OK, CURLUE_OK},
  702. {NULL, NULL, NULL, 0, 0, CURLUE_OK, CURLUE_OK}
  703. };
  704. static CURLUPart part2id(char *part)
  705. {
  706. if(!strcmp("url", part))
  707. return CURLUPART_URL;
  708. if(!strcmp("scheme", part))
  709. return CURLUPART_SCHEME;
  710. if(!strcmp("user", part))
  711. return CURLUPART_USER;
  712. if(!strcmp("password", part))
  713. return CURLUPART_PASSWORD;
  714. if(!strcmp("options", part))
  715. return CURLUPART_OPTIONS;
  716. if(!strcmp("host", part))
  717. return CURLUPART_HOST;
  718. if(!strcmp("port", part))
  719. return CURLUPART_PORT;
  720. if(!strcmp("path", part))
  721. return CURLUPART_PATH;
  722. if(!strcmp("query", part))
  723. return CURLUPART_QUERY;
  724. if(!strcmp("fragment", part))
  725. return CURLUPART_FRAGMENT;
  726. if(!strcmp("zoneid", part))
  727. return CURLUPART_ZONEID;
  728. return (CURLUPart)9999; /* bad input => bad output */
  729. }
  730. static CURLUcode updateurl(CURLU *u, const char *cmd, unsigned int setflags)
  731. {
  732. const char *p = cmd;
  733. CURLUcode uc;
  734. /* make sure the last command ends with a comma too! */
  735. while(p) {
  736. char *e = strchr(p, ',');
  737. if(e) {
  738. size_t n = e-p;
  739. char buf[80];
  740. char part[80];
  741. char value[80];
  742. memset(part, 0, sizeof(part)); /* Avoid valgrind false positive. */
  743. memset(value, 0, sizeof(value)); /* Avoid valgrind false positive. */
  744. memcpy(buf, p, n);
  745. buf[n] = 0;
  746. if(2 == sscanf(buf, "%79[^=]=%79[^,]", part, value)) {
  747. CURLUPart what = part2id(part);
  748. #if 0
  749. /* for debugging this */
  750. fprintf(stderr, "%s = \"%s\" [%d]\n", part, value, (int)what);
  751. #endif
  752. if(what > CURLUPART_ZONEID)
  753. fprintf(stderr, "UNKNOWN part '%s'\n", part);
  754. if(!strcmp("NULL", value))
  755. uc = curl_url_set(u, what, NULL, setflags);
  756. else if(!strcmp("\"\"", value))
  757. uc = curl_url_set(u, what, "", setflags);
  758. else
  759. uc = curl_url_set(u, what, value, setflags);
  760. if(uc)
  761. return uc;
  762. }
  763. p = e + 1;
  764. continue;
  765. }
  766. break;
  767. }
  768. return CURLUE_OK;
  769. }
  770. static const struct redircase set_url_list[] = {
  771. {"http://example.org/static/favicon/wikipedia.ico",
  772. "//fake.example.com/licenses/by-sa/3.0/",
  773. "http://fake.example.com/licenses/by-sa/3.0/",
  774. 0, 0, CURLUE_OK},
  775. {"https://example.org/static/favicon/wikipedia.ico",
  776. "//fake.example.com/licenses/by-sa/3.0/",
  777. "https://fake.example.com/licenses/by-sa/3.0/",
  778. 0, 0, CURLUE_OK},
  779. {"file://localhost/path?query#frag",
  780. "foo#another",
  781. "file:///foo#another",
  782. 0, 0, CURLUE_OK},
  783. {"http://example.com/path?query#frag",
  784. "https://two.example.com/bradnew",
  785. "https://two.example.com/bradnew",
  786. 0, 0, CURLUE_OK},
  787. {"http://example.com/path?query#frag",
  788. "../../newpage#foo",
  789. "http://example.com/newpage#foo",
  790. 0, 0, CURLUE_OK},
  791. {"http://user:[email protected]/path?query#frag",
  792. "../../newpage",
  793. "http://user:[email protected]/newpage",
  794. 0, 0, CURLUE_OK},
  795. {"http://user:[email protected]/path?query#frag",
  796. "../newpage",
  797. "http://user:[email protected]/newpage",
  798. 0, 0, CURLUE_OK},
  799. {NULL, NULL, NULL, 0, 0, CURLUE_OK}
  800. };
  801. static int set_url(void)
  802. {
  803. int i;
  804. int error = 0;
  805. for(i = 0; set_url_list[i].in && !error; i++) {
  806. CURLUcode rc;
  807. CURLU *urlp = curl_url();
  808. if(!urlp)
  809. break;
  810. rc = curl_url_set(urlp, CURLUPART_URL, set_url_list[i].in,
  811. set_url_list[i].urlflags);
  812. if(!rc) {
  813. rc = curl_url_set(urlp, CURLUPART_URL, set_url_list[i].set,
  814. set_url_list[i].setflags);
  815. if(rc) {
  816. fprintf(stderr, "%s:%d Set URL %s returned %d (%s)\n",
  817. __FILE__, __LINE__, set_url_list[i].set,
  818. (int)rc, curl_url_strerror(rc));
  819. error++;
  820. }
  821. else {
  822. char *url = NULL;
  823. rc = curl_url_get(urlp, CURLUPART_URL, &url, 0);
  824. if(rc) {
  825. fprintf(stderr, "%s:%d Get URL returned %d (%s)\n",
  826. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  827. error++;
  828. }
  829. else {
  830. if(checkurl(url, set_url_list[i].out)) {
  831. error++;
  832. }
  833. }
  834. curl_free(url);
  835. }
  836. }
  837. else if(rc != set_url_list[i].ucode) {
  838. fprintf(stderr, "Set URL\nin: %s\nreturned %d (expected %d)\n",
  839. set_url_list[i].in, (int)rc, set_url_list[i].ucode);
  840. error++;
  841. }
  842. curl_url_cleanup(urlp);
  843. }
  844. return error;
  845. }
  846. static int set_parts(void)
  847. {
  848. int i;
  849. int error = 0;
  850. for(i = 0; set_parts_list[i].set && !error; i++) {
  851. CURLUcode rc;
  852. CURLU *urlp = curl_url();
  853. if(!urlp) {
  854. error++;
  855. break;
  856. }
  857. if(set_parts_list[i].in)
  858. rc = curl_url_set(urlp, CURLUPART_URL, set_parts_list[i].in,
  859. set_parts_list[i].urlflags);
  860. else
  861. rc = CURLUE_OK;
  862. if(!rc) {
  863. char *url = NULL;
  864. CURLUcode uc = updateurl(urlp, set_parts_list[i].set,
  865. set_parts_list[i].setflags);
  866. if(uc != set_parts_list[i].pcode) {
  867. fprintf(stderr, "updateurl\nin: %s\nreturned %d (expected %d)\n",
  868. set_parts_list[i].set, (int)uc, set_parts_list[i].pcode);
  869. error++;
  870. }
  871. if(!uc) {
  872. /* only do this if it worked */
  873. rc = curl_url_get(urlp, CURLUPART_URL, &url, 0);
  874. if(rc) {
  875. fprintf(stderr, "%s:%d Get URL returned %d (%s)\n",
  876. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  877. error++;
  878. }
  879. else if(checkurl(url, set_parts_list[i].out)) {
  880. error++;
  881. }
  882. }
  883. curl_free(url);
  884. }
  885. else if(rc != set_parts_list[i].ucode) {
  886. fprintf(stderr, "Set parts\nin: %s\nreturned %d (expected %d)\n",
  887. set_parts_list[i].in, (int)rc, set_parts_list[i].ucode);
  888. error++;
  889. }
  890. curl_url_cleanup(urlp);
  891. }
  892. return error;
  893. }
  894. static int get_url(void)
  895. {
  896. int i;
  897. int error = 0;
  898. for(i = 0; get_url_list[i].in && !error; i++) {
  899. CURLUcode rc;
  900. CURLU *urlp = curl_url();
  901. if(!urlp) {
  902. error++;
  903. break;
  904. }
  905. rc = curl_url_set(urlp, CURLUPART_URL, get_url_list[i].in,
  906. get_url_list[i].urlflags);
  907. if(!rc) {
  908. char *url = NULL;
  909. rc = curl_url_get(urlp, CURLUPART_URL, &url, get_url_list[i].getflags);
  910. if(rc) {
  911. fprintf(stderr, "%s:%d returned %d (%s). URL: '%s'\n",
  912. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc),
  913. get_url_list[i].in);
  914. error++;
  915. }
  916. else {
  917. if(checkurl(url, get_url_list[i].out)) {
  918. error++;
  919. }
  920. }
  921. curl_free(url);
  922. }
  923. else if(rc != get_url_list[i].ucode) {
  924. fprintf(stderr, "Get URL\nin: %s\nreturned %d (expected %d)\n",
  925. get_url_list[i].in, (int)rc, get_url_list[i].ucode);
  926. error++;
  927. }
  928. curl_url_cleanup(urlp);
  929. }
  930. return error;
  931. }
  932. static int get_parts(void)
  933. {
  934. int i;
  935. int error = 0;
  936. for(i = 0; get_parts_list[i].in && !error; i++) {
  937. CURLUcode rc;
  938. CURLU *urlp = curl_url();
  939. if(!urlp) {
  940. error++;
  941. break;
  942. }
  943. rc = curl_url_set(urlp, CURLUPART_URL,
  944. get_parts_list[i].in,
  945. get_parts_list[i].urlflags);
  946. if(rc != get_parts_list[i].ucode) {
  947. fprintf(stderr, "Get parts\nin: %s\nreturned %d (expected %d)\n",
  948. get_parts_list[i].in, (int)rc, get_parts_list[i].ucode);
  949. error++;
  950. }
  951. else if(get_parts_list[i].ucode) {
  952. /* the expected error happened */
  953. }
  954. else if(checkparts(urlp, get_parts_list[i].in, get_parts_list[i].out,
  955. get_parts_list[i].getflags))
  956. error++;
  957. curl_url_cleanup(urlp);
  958. }
  959. return error;
  960. }
  961. static const struct querycase append_list[] = {
  962. {"HTTP://test/?s", "name=joe\x02", "http://test/?s&name=joe%02",
  963. 0, CURLU_URLENCODE, CURLUE_OK},
  964. {"HTTP://test/?size=2#f", "name=joe=", "http://test/?size=2&name=joe%3d#f",
  965. 0, CURLU_URLENCODE, CURLUE_OK},
  966. {"HTTP://test/?size=2#f", "name=joe doe",
  967. "http://test/?size=2&name=joe+doe#f",
  968. 0, CURLU_URLENCODE, CURLUE_OK},
  969. {"HTTP://test/", "name=joe", "http://test/?name=joe", 0, 0, CURLUE_OK},
  970. {"HTTP://test/?size=2", "name=joe", "http://test/?size=2&name=joe",
  971. 0, 0, CURLUE_OK},
  972. {"HTTP://test/?size=2&", "name=joe", "http://test/?size=2&name=joe",
  973. 0, 0, CURLUE_OK},
  974. {"HTTP://test/?size=2#f", "name=joe", "http://test/?size=2&name=joe#f",
  975. 0, 0, CURLUE_OK},
  976. {NULL, NULL, NULL, 0, 0, CURLUE_OK}
  977. };
  978. static int append(void)
  979. {
  980. int i;
  981. int error = 0;
  982. for(i = 0; append_list[i].in && !error; i++) {
  983. CURLUcode rc;
  984. CURLU *urlp = curl_url();
  985. if(!urlp) {
  986. error++;
  987. break;
  988. }
  989. rc = curl_url_set(urlp, CURLUPART_URL,
  990. append_list[i].in,
  991. append_list[i].urlflags);
  992. if(rc)
  993. error++;
  994. else
  995. rc = curl_url_set(urlp, CURLUPART_QUERY,
  996. append_list[i].q,
  997. append_list[i].qflags | CURLU_APPENDQUERY);
  998. if(error)
  999. ;
  1000. else if(rc != append_list[i].ucode) {
  1001. fprintf(stderr, "Append\nin: %s\nreturned %d (expected %d)\n",
  1002. append_list[i].in, (int)rc, append_list[i].ucode);
  1003. error++;
  1004. }
  1005. else if(append_list[i].ucode) {
  1006. /* the expected error happened */
  1007. }
  1008. else {
  1009. char *url;
  1010. rc = curl_url_get(urlp, CURLUPART_URL, &url, 0);
  1011. if(rc) {
  1012. fprintf(stderr, "%s:%d Get URL returned %d (%s)\n",
  1013. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  1014. error++;
  1015. }
  1016. else {
  1017. if(checkurl(url, append_list[i].out)) {
  1018. error++;
  1019. }
  1020. curl_free(url);
  1021. }
  1022. }
  1023. curl_url_cleanup(urlp);
  1024. }
  1025. return error;
  1026. }
  1027. static int scopeid(void)
  1028. {
  1029. CURLU *u = curl_url();
  1030. int error = 0;
  1031. CURLUcode rc;
  1032. char *url;
  1033. rc = curl_url_set(u, CURLUPART_URL,
  1034. "https://[fe80::20c:29ff:fe9c:409b%25eth0]/hello.html", 0);
  1035. if(rc != CURLUE_OK) {
  1036. fprintf(stderr, "%s:%d curl_url_set returned %d (%s)\n",
  1037. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  1038. error++;
  1039. }
  1040. rc = curl_url_get(u, CURLUPART_HOST, &url, 0);
  1041. if(rc != CURLUE_OK) {
  1042. fprintf(stderr, "%s:%d curl_url_get CURLUPART_HOST returned %d (%s)\n",
  1043. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  1044. error++;
  1045. }
  1046. else {
  1047. printf("we got %s\n", url);
  1048. curl_free(url);
  1049. }
  1050. rc = curl_url_set(u, CURLUPART_HOST, "[::1]", 0);
  1051. if(rc != CURLUE_OK) {
  1052. fprintf(stderr, "%s:%d curl_url_set CURLUPART_HOST returned %d (%s)\n",
  1053. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  1054. error++;
  1055. }
  1056. rc = curl_url_get(u, CURLUPART_URL, &url, 0);
  1057. if(rc != CURLUE_OK) {
  1058. fprintf(stderr, "%s:%d curl_url_get CURLUPART_URL returned %d (%s)\n",
  1059. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  1060. error++;
  1061. }
  1062. else {
  1063. printf("we got %s\n", url);
  1064. curl_free(url);
  1065. }
  1066. rc = curl_url_set(u, CURLUPART_HOST, "example.com", 0);
  1067. if(rc != CURLUE_OK) {
  1068. fprintf(stderr, "%s:%d curl_url_set CURLUPART_HOST returned %d (%s)\n",
  1069. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  1070. error++;
  1071. }
  1072. rc = curl_url_get(u, CURLUPART_URL, &url, 0);
  1073. if(rc != CURLUE_OK) {
  1074. fprintf(stderr, "%s:%d curl_url_get CURLUPART_URL returned %d (%s)\n",
  1075. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  1076. error++;
  1077. }
  1078. else {
  1079. printf("we got %s\n", url);
  1080. curl_free(url);
  1081. }
  1082. rc = curl_url_set(u, CURLUPART_HOST,
  1083. "[fe80::20c:29ff:fe9c:409b%25eth0]", 0);
  1084. if(rc != CURLUE_OK) {
  1085. fprintf(stderr, "%s:%d curl_url_set CURLUPART_HOST returned %d (%s)\n",
  1086. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  1087. error++;
  1088. }
  1089. rc = curl_url_get(u, CURLUPART_URL, &url, 0);
  1090. if(rc != CURLUE_OK) {
  1091. fprintf(stderr, "%s:%d curl_url_get CURLUPART_URL returned %d (%s)\n",
  1092. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  1093. error++;
  1094. }
  1095. else {
  1096. printf("we got %s\n", url);
  1097. curl_free(url);
  1098. }
  1099. rc = curl_url_get(u, CURLUPART_HOST, &url, 0);
  1100. if(rc != CURLUE_OK) {
  1101. fprintf(stderr, "%s:%d curl_url_get CURLUPART_HOST returned %d (%s)\n",
  1102. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  1103. error++;
  1104. }
  1105. else {
  1106. printf("we got %s\n", url);
  1107. curl_free(url);
  1108. }
  1109. rc = curl_url_get(u, CURLUPART_ZONEID, &url, 0);
  1110. if(rc != CURLUE_OK) {
  1111. fprintf(stderr, "%s:%d curl_url_get CURLUPART_ZONEID returned %d (%s)\n",
  1112. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  1113. error++;
  1114. }
  1115. else {
  1116. printf("we got %s\n", url);
  1117. curl_free(url);
  1118. }
  1119. rc = curl_url_set(u, CURLUPART_ZONEID, "clown", 0);
  1120. if(rc != CURLUE_OK) {
  1121. fprintf(stderr, "%s:%d curl_url_set CURLUPART_ZONEID returned %d (%s)\n",
  1122. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  1123. error++;
  1124. }
  1125. rc = curl_url_get(u, CURLUPART_URL, &url, 0);
  1126. if(rc != CURLUE_OK) {
  1127. fprintf(stderr, "%s:%d curl_url_get CURLUPART_URL returned %d (%s)\n",
  1128. __FILE__, __LINE__, (int)rc, curl_url_strerror(rc));
  1129. error++;
  1130. }
  1131. else {
  1132. printf("we got %s\n", url);
  1133. curl_free(url);
  1134. }
  1135. curl_url_cleanup(u);
  1136. return error;
  1137. }
  1138. static int get_nothing(void)
  1139. {
  1140. CURLU *u = curl_url();
  1141. if(u) {
  1142. char *p;
  1143. CURLUcode rc;
  1144. rc = curl_url_get(u, CURLUPART_SCHEME, &p, 0);
  1145. if(rc != CURLUE_NO_SCHEME)
  1146. fprintf(stderr, "unexpected return code line %u\n", __LINE__);
  1147. rc = curl_url_get(u, CURLUPART_HOST, &p, 0);
  1148. if(rc != CURLUE_NO_HOST)
  1149. fprintf(stderr, "unexpected return code line %u\n", __LINE__);
  1150. rc = curl_url_get(u, CURLUPART_USER, &p, 0);
  1151. if(rc != CURLUE_NO_USER)
  1152. fprintf(stderr, "unexpected return code line %u\n", __LINE__);
  1153. rc = curl_url_get(u, CURLUPART_PASSWORD, &p, 0);
  1154. if(rc != CURLUE_NO_PASSWORD)
  1155. fprintf(stderr, "unexpected return code line %u\n", __LINE__);
  1156. rc = curl_url_get(u, CURLUPART_OPTIONS, &p, 0);
  1157. if(rc != CURLUE_NO_OPTIONS)
  1158. fprintf(stderr, "unexpected return code line %u\n", __LINE__);
  1159. rc = curl_url_get(u, CURLUPART_PATH, &p, 0);
  1160. if(rc != CURLUE_OK)
  1161. fprintf(stderr, "unexpected return code line %u\n", __LINE__);
  1162. else
  1163. curl_free(p);
  1164. rc = curl_url_get(u, CURLUPART_QUERY, &p, 0);
  1165. if(rc != CURLUE_NO_QUERY)
  1166. fprintf(stderr, "unexpected return code line %u\n", __LINE__);
  1167. rc = curl_url_get(u, CURLUPART_FRAGMENT, &p, 0);
  1168. if(rc != CURLUE_NO_FRAGMENT)
  1169. fprintf(stderr, "unexpected return code line %u\n", __LINE__);
  1170. rc = curl_url_get(u, CURLUPART_ZONEID, &p, 0);
  1171. if(rc != CURLUE_OK)
  1172. fprintf(stderr, "unexpected return code %u on line %u\n", (int)rc,
  1173. __LINE__);
  1174. curl_url_cleanup(u);
  1175. }
  1176. return 0;
  1177. }
  1178. static const struct clearurlcase clear_url_list[] ={
  1179. {CURLUPART_SCHEME, "http", NULL, CURLUE_NO_SCHEME},
  1180. {CURLUPART_USER, "user", NULL, CURLUE_NO_USER},
  1181. {CURLUPART_PASSWORD, "password", NULL, CURLUE_NO_PASSWORD},
  1182. {CURLUPART_OPTIONS, "options", NULL, CURLUE_NO_OPTIONS},
  1183. {CURLUPART_HOST, "host", NULL, CURLUE_NO_HOST},
  1184. {CURLUPART_ZONEID, "eth0", NULL, CURLUE_NO_ZONEID},
  1185. {CURLUPART_PORT, "1234", NULL, CURLUE_NO_PORT},
  1186. {CURLUPART_PATH, "/hello", "/", CURLUE_OK},
  1187. {CURLUPART_QUERY, "a=b", NULL, CURLUE_NO_QUERY},
  1188. {CURLUPART_FRAGMENT, "anchor", NULL, CURLUE_NO_FRAGMENT},
  1189. {CURLUPART_URL, NULL, NULL, CURLUE_OK},
  1190. };
  1191. static int clear_url(void)
  1192. {
  1193. CURLU *u = curl_url();
  1194. int i, error = 0;
  1195. if(u) {
  1196. char *p = NULL;
  1197. CURLUcode rc;
  1198. for(i = 0; clear_url_list[i].in && !error; i++) {
  1199. rc = curl_url_set(u, clear_url_list[i].part, clear_url_list[i].in, 0);
  1200. if(rc != CURLUE_OK)
  1201. fprintf(stderr, "unexpected return code line %u\n", __LINE__);
  1202. rc = curl_url_set(u, CURLUPART_URL, NULL, 0);
  1203. if(rc != CURLUE_OK)
  1204. fprintf(stderr, "unexpected return code line %u\n", __LINE__);
  1205. rc = curl_url_get(u, clear_url_list[i].part, &p, 0);
  1206. if(rc != clear_url_list[i].ucode || (clear_url_list[i].out &&
  1207. 0 != strcmp(p, clear_url_list[i].out))) {
  1208. fprintf(stderr, "unexpected return code line %u\n", __LINE__);
  1209. error++;
  1210. }
  1211. if(rc == CURLUE_OK)
  1212. curl_free(p);
  1213. }
  1214. }
  1215. curl_url_cleanup(u);
  1216. return error;
  1217. }
  1218. int test(char *URL)
  1219. {
  1220. (void)URL; /* not used */
  1221. if(get_nothing())
  1222. return 7;
  1223. if(scopeid())
  1224. return 6;
  1225. if(append())
  1226. return 5;
  1227. if(set_url())
  1228. return 1;
  1229. if(set_parts())
  1230. return 2;
  1231. if(get_url())
  1232. return 3;
  1233. if(get_parts())
  1234. return 4;
  1235. if(clear_url())
  1236. return 8;
  1237. printf("success\n");
  1238. return 0;
  1239. }