lib1560.c 46 KB

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