lib1560.c 58 KB

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