lib1560.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.haxx.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. ***************************************************************************/
  22. /*
  23. * Note:
  24. *
  25. * Since the URL parser by default only accepts schemes that *this instance*
  26. * of libcurl supports, make sure that the test1560 file lists all the schemes
  27. * that this test will assume to be present!
  28. */
  29. #include "test.h"
  30. #include "testutil.h"
  31. #include "warnless.h"
  32. #include "memdebug.h" /* LAST include file */
  33. struct part {
  34. CURLUPart part;
  35. const char *name;
  36. };
  37. static int checkparts(CURLU *u, const char *in, const char *wanted,
  38. unsigned int getflags)
  39. {
  40. int i;
  41. CURLUcode rc;
  42. char buf[256];
  43. char *bufp = &buf[0];
  44. size_t len = sizeof(buf);
  45. struct part parts[] = {
  46. {CURLUPART_SCHEME, "scheme"},
  47. {CURLUPART_USER, "user"},
  48. {CURLUPART_PASSWORD, "password"},
  49. {CURLUPART_OPTIONS, "options"},
  50. {CURLUPART_HOST, "host"},
  51. {CURLUPART_PORT, "port"},
  52. {CURLUPART_PATH, "path"},
  53. {CURLUPART_QUERY, "query"},
  54. {CURLUPART_FRAGMENT, "fragment"},
  55. {0, NULL}
  56. };
  57. buf[0] = 0;
  58. for(i = 0; parts[i].name; i++) {
  59. char *p = NULL;
  60. size_t n;
  61. rc = curl_url_get(u, parts[i].part, &p, getflags);
  62. if(!rc && p) {
  63. msnprintf(bufp, len, "%s%s", buf[0]?" | ":"", p);
  64. }
  65. else
  66. msnprintf(bufp, len, "%s[%d]", buf[0]?" | ":"", (int)rc);
  67. n = strlen(bufp);
  68. bufp += n;
  69. len -= n;
  70. curl_free(p);
  71. }
  72. if(strcmp(buf, wanted)) {
  73. fprintf(stderr, "in: %s\nwanted: %s\ngot: %s\n", in, wanted, buf);
  74. return 1;
  75. }
  76. return 0;
  77. }
  78. struct redircase {
  79. const char *in;
  80. const char *set;
  81. const char *out;
  82. unsigned int urlflags;
  83. unsigned int setflags;
  84. CURLUcode ucode;
  85. };
  86. struct setcase {
  87. const char *in;
  88. const char *set;
  89. const char *out;
  90. unsigned int urlflags;
  91. unsigned int setflags;
  92. CURLUcode ucode; /* for the main URL set */
  93. CURLUcode pcode; /* for updating parts */
  94. };
  95. struct testcase {
  96. const char *in;
  97. const char *out;
  98. unsigned int urlflags;
  99. unsigned int getflags;
  100. CURLUcode ucode;
  101. };
  102. struct urltestcase {
  103. const char *in;
  104. const char *out;
  105. unsigned int urlflags; /* pass to curl_url() */
  106. unsigned int getflags; /* pass to curl_url_get() */
  107. CURLUcode ucode;
  108. };
  109. struct querycase {
  110. const char *in;
  111. const char *q;
  112. const char *out;
  113. unsigned int urlflags; /* pass to curl_url() */
  114. unsigned int qflags; /* pass to curl_url_get() */
  115. CURLUcode ucode;
  116. };
  117. static struct testcase get_parts_list[] ={
  118. #ifdef WIN32
  119. {"file:/C:\\programs\\foo",
  120. "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
  121. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  122. {"file://C:\\programs\\foo",
  123. "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
  124. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  125. {"file:///C:\\programs\\foo",
  126. "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
  127. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  128. #endif
  129. {"http://[ab.be:1]/x", "",
  130. CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
  131. {"http://[ab.be]/x", "",
  132. CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
  133. /* URL without host name */
  134. {"http://a:b@/x", "",
  135. CURLU_DEFAULT_SCHEME, 0, CURLUE_NO_HOST},
  136. {"boing:80",
  137. "https | [11] | [12] | [13] | boing | 80 | / | [16] | [17]",
  138. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  139. {"http://[fd00:a41::50]:8080",
  140. "http | [11] | [12] | [13] | [fd00:a41::50] | 8080 | / | [16] | [17]",
  141. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  142. {"http://[fd00:a41::50]/",
  143. "http | [11] | [12] | [13] | [fd00:a41::50] | [15] | / | [16] | [17]",
  144. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  145. {"http://[fd00:a41::50]",
  146. "http | [11] | [12] | [13] | [fd00:a41::50] | [15] | / | [16] | [17]",
  147. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  148. {"https://[::1%252]:1234",
  149. "https | [11] | [12] | [13] | [::1] | 1234 | / | [16] | [17]",
  150. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  151. /* here's "bad" zone id */
  152. {"https://[fe80::20c:29ff:fe9c:409b%eth0]:1234",
  153. "https | [11] | [12] | [13] | [fe80::20c:29ff:fe9c:409b] | 1234 "
  154. "| / | [16] | [17]",
  155. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  156. {"https://127.0.0.1:443",
  157. "https | [11] | [12] | [13] | 127.0.0.1 | [15] | / | [16] | [17]",
  158. 0, CURLU_NO_DEFAULT_PORT, CURLUE_OK},
  159. {"http://%3a:%3a@ex%0ample/%3f+?+%3f+%23#+%23%3f%g7",
  160. "http | : | : | [13] | [6] | [15] | /?+ | ? # | +#?%g7",
  161. 0, CURLU_URLDECODE, CURLUE_OK},
  162. {"http://%3a:%3a@ex%0ample/%3f?%3f%35#%35%3f%g7",
  163. "http | %3a | %3a | [13] | ex%0ample | [15] | /%3f | %3f%35 | %35%3f%g7",
  164. 0, 0, CURLUE_OK},
  165. {"http://HO0_-st%41/",
  166. "http | [11] | [12] | [13] | HO0_-st%41 | [15] | / | [16] | [17]",
  167. 0, 0, CURLUE_OK},
  168. {"file://hello.html",
  169. "",
  170. 0, 0, CURLUE_MALFORMED_INPUT},
  171. {"http://HO0_-st/",
  172. "http | [11] | [12] | [13] | HO0_-st | [15] | / | [16] | [17]",
  173. 0, 0, CURLUE_OK},
  174. {"imap://user:pass;option@server/path",
  175. "imap | user | pass | option | server | [15] | /path | [16] | [17]",
  176. 0, 0, CURLUE_OK},
  177. {"http://user:pass;option@server/path",
  178. "http | user | pass;option | [13] | server | [15] | /path | [16] | [17]",
  179. 0, 0, CURLUE_OK},
  180. {"file:/hello.html",
  181. "file | [11] | [12] | [13] | [14] | [15] | /hello.html | [16] | [17]",
  182. 0, 0, CURLUE_OK},
  183. {"file://127.0.0.1/hello.html",
  184. "file | [11] | [12] | [13] | [14] | [15] | /hello.html | [16] | [17]",
  185. 0, 0, CURLUE_OK},
  186. {"file:////hello.html",
  187. "file | [11] | [12] | [13] | [14] | [15] | //hello.html | [16] | [17]",
  188. 0, 0, CURLUE_OK},
  189. {"file:///hello.html",
  190. "file | [11] | [12] | [13] | [14] | [15] | /hello.html | [16] | [17]",
  191. 0, 0, CURLUE_OK},
  192. {"https://127.0.0.1",
  193. "https | [11] | [12] | [13] | 127.0.0.1 | 443 | / | [16] | [17]",
  194. 0, CURLU_DEFAULT_PORT, CURLUE_OK},
  195. {"https://127.0.0.1",
  196. "https | [11] | [12] | [13] | 127.0.0.1 | [15] | / | [16] | [17]",
  197. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  198. {"https://[::1]:1234",
  199. "https | [11] | [12] | [13] | [::1] | 1234 | / | [16] | [17]",
  200. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  201. {"https://127abc.com",
  202. "https | [11] | [12] | [13] | 127abc.com | [15] | / | [16] | [17]",
  203. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  204. {"https:// example.com?check",
  205. "",
  206. CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
  207. {"https://e x a m p l e.com?check",
  208. "",
  209. CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
  210. {"https://example.com?check",
  211. "https | [11] | [12] | [13] | example.com | [15] | / | check | [17]",
  212. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  213. {"https://example.com:65536",
  214. "",
  215. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PORT_NUMBER},
  216. {"https://example.com:0#moo",
  217. "",
  218. CURLU_DEFAULT_SCHEME, 0, CURLUE_BAD_PORT_NUMBER},
  219. {"https://example.com:01#moo",
  220. "https | [11] | [12] | [13] | example.com | 1 | / | "
  221. "[16] | moo",
  222. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  223. {"https://example.com:1#moo",
  224. "https | [11] | [12] | [13] | example.com | 1 | / | "
  225. "[16] | moo",
  226. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  227. {"http://example.com#moo",
  228. "http | [11] | [12] | [13] | example.com | [15] | / | "
  229. "[16] | moo",
  230. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  231. {"http://example.com",
  232. "http | [11] | [12] | [13] | example.com | [15] | / | "
  233. "[16] | [17]",
  234. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  235. {"http://example.com/path/html",
  236. "http | [11] | [12] | [13] | example.com | [15] | /path/html | "
  237. "[16] | [17]",
  238. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  239. {"http://example.com/path/html?query=name",
  240. "http | [11] | [12] | [13] | example.com | [15] | /path/html | "
  241. "query=name | [17]",
  242. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  243. {"http://example.com/path/html?query=name#anchor",
  244. "http | [11] | [12] | [13] | example.com | [15] | /path/html | "
  245. "query=name | anchor",
  246. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  247. {"http://example.com:1234/path/html?query=name#anchor",
  248. "http | [11] | [12] | [13] | example.com | 1234 | /path/html | "
  249. "query=name | anchor",
  250. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  251. {"http:///user:password@example.com:1234/path/html?query=name#anchor",
  252. "http | user | password | [13] | example.com | 1234 | /path/html | "
  253. "query=name | anchor",
  254. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  255. {"https://user:password@example.com:1234/path/html?query=name#anchor",
  256. "https | user | password | [13] | example.com | 1234 | /path/html | "
  257. "query=name | anchor",
  258. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  259. {"http://user:password@example.com:1234/path/html?query=name#anchor",
  260. "http | user | password | [13] | example.com | 1234 | /path/html | "
  261. "query=name | anchor",
  262. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  263. {"http:/user:password@example.com:1234/path/html?query=name#anchor",
  264. "http | user | password | [13] | example.com | 1234 | /path/html | "
  265. "query=name | anchor",
  266. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  267. {"http:////user:password@example.com:1234/path/html?query=name#anchor",
  268. "",
  269. CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
  270. {NULL, NULL, 0, 0, CURLUE_OK},
  271. };
  272. static struct urltestcase get_url_list[] = {
  273. /* 40 bytes scheme is the max allowed */
  274. {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA://hostname/path",
  275. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa://hostname/path",
  276. CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
  277. /* 41 bytes scheme is not allowed */
  278. {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA://hostname/path",
  279. "",
  280. CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
  281. {"https://[fe80::20c:29ff:fe9c:409b%]:1234",
  282. "",
  283. 0, 0, CURLUE_MALFORMED_INPUT},
  284. {"https://[fe80::20c:29ff:fe9c:409b%25]:1234",
  285. "https://[fe80::20c:29ff:fe9c:409b%2525]:1234/",
  286. 0, 0, CURLUE_OK},
  287. {"https://[fe80::20c:29ff:fe9c:409b%eth0]:1234",
  288. "https://[fe80::20c:29ff:fe9c:409b%25eth0]:1234/",
  289. 0, 0, CURLUE_OK},
  290. {"https://[::%25fakeit]/moo",
  291. "https://[::%25fakeit]/moo",
  292. 0, 0, CURLUE_OK},
  293. {"smtp.example.com/path/html",
  294. "smtp://smtp.example.com/path/html",
  295. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  296. {"https.example.com/path/html",
  297. "http://https.example.com/path/html",
  298. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  299. {"dict.example.com/path/html",
  300. "dict://dict.example.com/path/html",
  301. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  302. {"pop3.example.com/path/html",
  303. "pop3://pop3.example.com/path/html",
  304. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  305. {"ldap.example.com/path/html",
  306. "ldap://ldap.example.com/path/html",
  307. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  308. {"imap.example.com/path/html",
  309. "imap://imap.example.com/path/html",
  310. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  311. {"ftp.example.com/path/html",
  312. "ftp://ftp.example.com/path/html",
  313. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  314. {"example.com/path/html",
  315. "http://example.com/path/html",
  316. CURLU_GUESS_SCHEME, 0, CURLUE_OK},
  317. {"HTTP://test/", "http://test/", 0, 0, CURLUE_OK},
  318. {"http://HO0_-st..~./", "http://HO0_-st..~./", 0, 0, CURLUE_OK},
  319. {"http:/@example.com: 123/", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
  320. {"http:/@example.com:123 /", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
  321. {"http:/@example.com:123a/", "", 0, 0, CURLUE_BAD_PORT_NUMBER},
  322. {"http://host/file\r", "", 0, 0, CURLUE_MALFORMED_INPUT},
  323. {"http://host/file\n\x03", "", 0, 0, CURLUE_MALFORMED_INPUT},
  324. {"htt\x02://host/file", "",
  325. CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
  326. {" http://host/file", "", 0, 0, CURLUE_MALFORMED_INPUT},
  327. /* here the password ends at the semicolon and options is 'word' */
  328. {"imap://user:pass;word@host/file",
  329. "imap://user:pass;word@host/file",
  330. 0, 0, CURLUE_OK},
  331. /* here the password has the semicolon */
  332. {"http://user:pass;word@host/file",
  333. "http://user:pass;word@host/file",
  334. 0, 0, CURLUE_OK},
  335. {"file:///file.txt#moo",
  336. "file:///file.txt#moo",
  337. 0, 0, CURLUE_OK},
  338. {"file:////file.txt",
  339. "file:////file.txt",
  340. 0, 0, CURLUE_OK},
  341. {"file:///file.txt",
  342. "file:///file.txt",
  343. 0, 0, CURLUE_OK},
  344. {"file:./",
  345. "file://",
  346. 0, 0, CURLUE_MALFORMED_INPUT},
  347. {"http://example.com/hello/../here",
  348. "http://example.com/hello/../here",
  349. CURLU_PATH_AS_IS, 0, CURLUE_OK},
  350. {"http://example.com/hello/../here",
  351. "http://example.com/here",
  352. 0, 0, CURLUE_OK},
  353. {"http://example.com:80",
  354. "http://example.com/",
  355. 0, CURLU_NO_DEFAULT_PORT, CURLUE_OK},
  356. {"tp://example.com/path/html",
  357. "",
  358. 0, 0, CURLUE_UNSUPPORTED_SCHEME},
  359. {"http://hello:fool@example.com",
  360. "",
  361. CURLU_DISALLOW_USER, 0, CURLUE_USER_NOT_ALLOWED},
  362. {"http:/@example.com:123",
  363. "http://example.com:123/",
  364. 0, 0, CURLUE_OK},
  365. {"http:/:password@example.com",
  366. "http://:password@example.com/",
  367. 0, 0, CURLUE_OK},
  368. {"http://user@example.com?#",
  369. "http://user@example.com/",
  370. 0, 0, CURLUE_OK},
  371. {"http://user@example.com?",
  372. "http://user@example.com/",
  373. 0, 0, CURLUE_OK},
  374. {"http://user@example.com#anchor",
  375. "http://user@example.com/#anchor",
  376. 0, 0, CURLUE_OK},
  377. {"example.com/path/html",
  378. "https://example.com/path/html",
  379. CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
  380. {"example.com/path/html",
  381. "",
  382. 0, 0, CURLUE_MALFORMED_INPUT},
  383. {"http://user:password@example.com:1234/path/html?query=name#anchor",
  384. "http://user:password@example.com:1234/path/html?query=name#anchor",
  385. 0, 0, CURLUE_OK},
  386. {"http://example.com:1234/path/html?query=name#anchor",
  387. "http://example.com:1234/path/html?query=name#anchor",
  388. 0, 0, CURLUE_OK},
  389. {"http://example.com/path/html?query=name#anchor",
  390. "http://example.com/path/html?query=name#anchor",
  391. 0, 0, CURLUE_OK},
  392. {"http://example.com/path/html?query=name",
  393. "http://example.com/path/html?query=name",
  394. 0, 0, CURLUE_OK},
  395. {"http://example.com/path/html",
  396. "http://example.com/path/html",
  397. 0, 0, CURLUE_OK},
  398. {"tp://example.com/path/html",
  399. "tp://example.com/path/html",
  400. CURLU_NON_SUPPORT_SCHEME, 0, CURLUE_OK},
  401. {NULL, NULL, 0, 0, 0}
  402. };
  403. static int checkurl(const char *url, const char *out)
  404. {
  405. if(strcmp(out, url)) {
  406. fprintf(stderr, "Wanted: %s\nGot : %s\n",
  407. out, url);
  408. return 1;
  409. }
  410. return 0;
  411. }
  412. /* !checksrc! disable SPACEBEFORECOMMA 1 */
  413. static struct setcase set_parts_list[] = {
  414. {"https://example.com/",
  415. /* Set a 41 bytes scheme. That's too long so the old scheme remains set. */
  416. "scheme=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc,",
  417. "https://example.com/",
  418. 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_MALFORMED_INPUT},
  419. {"https://example.com/",
  420. /* set a 40 bytes scheme */
  421. "scheme=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,",
  422. "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb://example.com/",
  423. 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_OK},
  424. {"https://[::1%25fake]:1234/",
  425. "zoneid=NULL,",
  426. "https://[::1]:1234/",
  427. 0, 0, CURLUE_OK, CURLUE_OK},
  428. {"https://host:1234/",
  429. "port=NULL,",
  430. "https://host/",
  431. 0, 0, CURLUE_OK, CURLUE_OK},
  432. {"https://host:1234/",
  433. "port=\"\",",
  434. "https://host:1234/",
  435. 0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
  436. {"https://host:1234/",
  437. "port=56 78,",
  438. "https://host:1234/",
  439. 0, 0, CURLUE_OK, CURLUE_MALFORMED_INPUT},
  440. {"https://host:1234/",
  441. "port=0,",
  442. "https://host:1234/",
  443. 0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
  444. {"https://host:1234/",
  445. "port=65535,",
  446. "https://host:65535/",
  447. 0, 0, CURLUE_OK, CURLUE_OK},
  448. {"https://host:1234/",
  449. "port=65536,",
  450. "https://host:1234/",
  451. 0, 0, CURLUE_OK, CURLUE_BAD_PORT_NUMBER},
  452. {"https://host/",
  453. "path=%4A%4B%4C,",
  454. "https://host/%4a%4b%4c",
  455. 0, 0, CURLUE_OK, CURLUE_OK},
  456. {"https://host/mooo?q#f",
  457. "path=NULL,query=NULL,fragment=NULL,",
  458. "https://host/",
  459. 0, 0, CURLUE_OK, CURLUE_OK},
  460. {"https://user:secret@host/",
  461. "user=NULL,password=NULL,",
  462. "https://host/",
  463. 0, 0, CURLUE_OK, CURLUE_OK},
  464. {NULL,
  465. "scheme=https,user= @:,host=foobar,",
  466. "https://%20%20%20%40%3a@foobar/",
  467. 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
  468. {NULL,
  469. "scheme=https,host= ,path= ,user= ,password= ,query= ,fragment= ,",
  470. "https://%20:%20@%20%20/%20?+#%20",
  471. 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
  472. {NULL,
  473. "scheme=https,host=foobar,path=/this /path /is /here,",
  474. "https://foobar/this%20/path%20/is%20/here",
  475. 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
  476. {NULL,
  477. "scheme=https,host=foobar,path=\xc3\xa4\xc3\xb6\xc3\xbc,",
  478. "https://foobar/%c3%a4%c3%b6%c3%bc",
  479. 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
  480. {"imap://user:secret;opt@host/",
  481. "options=updated,scheme=imaps,password=p4ssw0rd,",
  482. "imaps://user:p4ssw0rd;updated@host/",
  483. 0, 0, CURLUE_NO_HOST, CURLUE_OK},
  484. {"imap://user:secret;optit@host/",
  485. "scheme=https,",
  486. "https://user:secret@host/",
  487. 0, 0, CURLUE_NO_HOST, CURLUE_OK},
  488. {"file:///file#anchor",
  489. "scheme=https,host=example,",
  490. "https://example/file#anchor",
  491. 0, 0, CURLUE_NO_HOST, CURLUE_OK},
  492. {NULL, /* start fresh! */
  493. "scheme=file,host=127.0.0.1,path=/no,user=anonymous,",
  494. "file:///no",
  495. 0, 0, CURLUE_OK, CURLUE_OK},
  496. {NULL, /* start fresh! */
  497. "scheme=ftp,host=127.0.0.1,path=/no,user=anonymous,",
  498. "ftp://anonymous@127.0.0.1/no",
  499. 0, 0, CURLUE_OK, CURLUE_OK},
  500. {NULL, /* start fresh! */
  501. "scheme=https,host=example.com,",
  502. "https://example.com/",
  503. 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_OK},
  504. {"http://user:foo@example.com/path?query#frag",
  505. "fragment=changed,",
  506. "http://user:foo@example.com/path?query#changed",
  507. 0, CURLU_NON_SUPPORT_SCHEME, CURLUE_OK, CURLUE_OK},
  508. {"http://example.com/",
  509. "scheme=foo,", /* not accepted */
  510. "http://example.com/",
  511. 0, 0, CURLUE_OK, CURLUE_UNSUPPORTED_SCHEME},
  512. {"http://example.com/",
  513. "scheme=https,path=/hello,fragment=snippet,",
  514. "https://example.com/hello#snippet",
  515. 0, 0, CURLUE_OK, CURLUE_OK},
  516. {"http://example.com:80",
  517. "user=foo,port=1922,",
  518. "http://foo@example.com:1922/",
  519. 0, 0, CURLUE_OK, CURLUE_OK},
  520. {"http://example.com:80",
  521. "user=foo,password=bar,",
  522. "http://foo:bar@example.com:80/",
  523. 0, 0, CURLUE_OK, CURLUE_OK},
  524. {"http://example.com:80",
  525. "user=foo,",
  526. "http://foo@example.com:80/",
  527. 0, 0, CURLUE_OK, CURLUE_OK},
  528. {"http://example.com",
  529. "host=www.example.com,",
  530. "http://www.example.com/",
  531. 0, 0, CURLUE_OK, CURLUE_OK},
  532. {"http://example.com:80",
  533. "scheme=ftp,",
  534. "ftp://example.com:80/",
  535. 0, 0, CURLUE_OK, CURLUE_OK},
  536. {NULL, NULL, NULL, 0, 0, 0, 0}
  537. };
  538. static CURLUPart part2id(char *part)
  539. {
  540. if(!strcmp("url", part))
  541. return CURLUPART_URL;
  542. if(!strcmp("scheme", part))
  543. return CURLUPART_SCHEME;
  544. if(!strcmp("user", part))
  545. return CURLUPART_USER;
  546. if(!strcmp("password", part))
  547. return CURLUPART_PASSWORD;
  548. if(!strcmp("options", part))
  549. return CURLUPART_OPTIONS;
  550. if(!strcmp("host", part))
  551. return CURLUPART_HOST;
  552. if(!strcmp("port", part))
  553. return CURLUPART_PORT;
  554. if(!strcmp("path", part))
  555. return CURLUPART_PATH;
  556. if(!strcmp("query", part))
  557. return CURLUPART_QUERY;
  558. if(!strcmp("fragment", part))
  559. return CURLUPART_FRAGMENT;
  560. if(!strcmp("zoneid", part))
  561. return CURLUPART_ZONEID;
  562. return 9999; /* bad input => bad output */
  563. }
  564. static CURLUcode updateurl(CURLU *u, const char *cmd, unsigned int setflags)
  565. {
  566. const char *p = cmd;
  567. CURLUcode uc;
  568. /* make sure the last command ends with a comma too! */
  569. while(p) {
  570. char *e = strchr(p, ',');
  571. if(e) {
  572. size_t n = e-p;
  573. char buf[80];
  574. char part[80];
  575. char value[80];
  576. memcpy(buf, p, n);
  577. buf[n] = 0;
  578. if(2 == sscanf(buf, "%79[^=]=%79[^,]", part, value)) {
  579. CURLUPart what = part2id(part);
  580. #if 0
  581. /* for debugging this */
  582. fprintf(stderr, "%s = %s [%d]\n", part, value, (int)what);
  583. #endif
  584. if(what > CURLUPART_ZONEID)
  585. fprintf(stderr, "UNKNOWN part '%s'\n", part);
  586. if(!strcmp("NULL", value))
  587. uc = curl_url_set(u, what, NULL, setflags);
  588. else if(!strcmp("\"\"", value))
  589. uc = curl_url_set(u, what, "", setflags);
  590. else
  591. uc = curl_url_set(u, what, value, setflags);
  592. if(uc)
  593. return uc;
  594. }
  595. p = e + 1;
  596. continue;
  597. }
  598. break;
  599. }
  600. return CURLUE_OK;
  601. }
  602. static struct redircase set_url_list[] = {
  603. {"file://localhost/path?query#frag",
  604. "foo#another",
  605. "file:///foo#another",
  606. 0, 0, 0},
  607. {"http://example.com/path?query#frag",
  608. "https://two.example.com/bradnew",
  609. "https://two.example.com/bradnew",
  610. 0, 0, 0},
  611. {"http://example.com/path?query#frag",
  612. "../../newpage#foo",
  613. "http://example.com/newpage#foo",
  614. 0, 0, 0},
  615. {"http://user:foo@example.com/path?query#frag",
  616. "../../newpage",
  617. "http://user:foo@example.com/newpage",
  618. 0, 0, 0},
  619. {"http://user:foo@example.com/path?query#frag",
  620. "../newpage",
  621. "http://user:foo@example.com/newpage",
  622. 0, 0, 0},
  623. {NULL, NULL, NULL, 0, 0, 0}
  624. };
  625. static int set_url(void)
  626. {
  627. int i;
  628. int error = 0;
  629. for(i = 0; set_url_list[i].in && !error; i++) {
  630. CURLUcode rc;
  631. CURLU *urlp = curl_url();
  632. if(!urlp)
  633. break;
  634. rc = curl_url_set(urlp, CURLUPART_URL, set_url_list[i].in,
  635. set_url_list[i].urlflags);
  636. if(!rc) {
  637. rc = curl_url_set(urlp, CURLUPART_URL, set_url_list[i].set,
  638. set_url_list[i].setflags);
  639. if(rc) {
  640. fprintf(stderr, "%s:%d Set URL %s returned %d\n",
  641. __FILE__, __LINE__, set_url_list[i].set,
  642. (int)rc);
  643. error++;
  644. }
  645. else {
  646. char *url = NULL;
  647. rc = curl_url_get(urlp, CURLUPART_URL, &url, 0);
  648. if(rc) {
  649. fprintf(stderr, "%s:%d Get URL returned %d\n",
  650. __FILE__, __LINE__, (int)rc);
  651. error++;
  652. }
  653. else {
  654. if(checkurl(url, set_url_list[i].out)) {
  655. error++;
  656. }
  657. }
  658. curl_free(url);
  659. }
  660. }
  661. else if(rc != set_url_list[i].ucode) {
  662. fprintf(stderr, "Set URL\nin: %s\nreturned %d (expected %d)\n",
  663. set_url_list[i].in, (int)rc, set_url_list[i].ucode);
  664. error++;
  665. }
  666. curl_url_cleanup(urlp);
  667. }
  668. return error;
  669. }
  670. static int set_parts(void)
  671. {
  672. int i;
  673. int error = 0;
  674. for(i = 0; set_parts_list[i].set && !error; i++) {
  675. CURLUcode rc;
  676. CURLU *urlp = curl_url();
  677. if(!urlp) {
  678. error++;
  679. break;
  680. }
  681. if(set_parts_list[i].in)
  682. rc = curl_url_set(urlp, CURLUPART_URL, set_parts_list[i].in,
  683. set_parts_list[i].urlflags);
  684. else
  685. rc = CURLUE_OK;
  686. if(!rc) {
  687. char *url = NULL;
  688. CURLUcode uc = updateurl(urlp, set_parts_list[i].set,
  689. set_parts_list[i].setflags);
  690. if(uc != set_parts_list[i].pcode) {
  691. fprintf(stderr, "updateurl\nin: %s\nreturned %d (expected %d)\n",
  692. set_parts_list[i].set, (int)uc, set_parts_list[i].pcode);
  693. error++;
  694. }
  695. rc = curl_url_get(urlp, CURLUPART_URL, &url, 0);
  696. if(rc) {
  697. fprintf(stderr, "%s:%d Get URL returned %d\n",
  698. __FILE__, __LINE__, (int)rc);
  699. error++;
  700. }
  701. else if(checkurl(url, set_parts_list[i].out)) {
  702. error++;
  703. }
  704. curl_free(url);
  705. }
  706. else if(rc != set_parts_list[i].ucode) {
  707. fprintf(stderr, "Set parts\nin: %s\nreturned %d (expected %d)\n",
  708. set_parts_list[i].in, (int)rc, set_parts_list[i].ucode);
  709. error++;
  710. }
  711. curl_url_cleanup(urlp);
  712. }
  713. return error;
  714. }
  715. static int get_url(void)
  716. {
  717. int i;
  718. int error = 0;
  719. for(i = 0; get_url_list[i].in && !error; i++) {
  720. CURLUcode rc;
  721. CURLU *urlp = curl_url();
  722. if(!urlp) {
  723. error++;
  724. break;
  725. }
  726. rc = curl_url_set(urlp, CURLUPART_URL, get_url_list[i].in,
  727. get_url_list[i].urlflags);
  728. if(!rc) {
  729. char *url = NULL;
  730. rc = curl_url_get(urlp, CURLUPART_URL, &url, get_url_list[i].getflags);
  731. if(rc) {
  732. fprintf(stderr, "%s:%d returned %d\n",
  733. __FILE__, __LINE__, (int)rc);
  734. error++;
  735. }
  736. else {
  737. if(checkurl(url, get_url_list[i].out)) {
  738. error++;
  739. }
  740. }
  741. curl_free(url);
  742. }
  743. else if(rc != get_url_list[i].ucode) {
  744. fprintf(stderr, "Get URL\nin: %s\nreturned %d (expected %d)\n",
  745. get_url_list[i].in, (int)rc, get_url_list[i].ucode);
  746. error++;
  747. }
  748. curl_url_cleanup(urlp);
  749. }
  750. return error;
  751. }
  752. static int get_parts(void)
  753. {
  754. int i;
  755. int error = 0;
  756. for(i = 0; get_parts_list[i].in && !error; i++) {
  757. CURLUcode rc;
  758. CURLU *urlp = curl_url();
  759. if(!urlp) {
  760. error++;
  761. break;
  762. }
  763. rc = curl_url_set(urlp, CURLUPART_URL,
  764. get_parts_list[i].in,
  765. get_parts_list[i].urlflags);
  766. if(rc != get_parts_list[i].ucode) {
  767. fprintf(stderr, "Get parts\nin: %s\nreturned %d (expected %d)\n",
  768. get_parts_list[i].in, (int)rc, get_parts_list[i].ucode);
  769. error++;
  770. }
  771. else if(get_parts_list[i].ucode) {
  772. /* the expected error happened */
  773. }
  774. else if(checkparts(urlp, get_parts_list[i].in, get_parts_list[i].out,
  775. get_parts_list[i].getflags))
  776. error++;
  777. curl_url_cleanup(urlp);
  778. }
  779. return error;
  780. }
  781. static struct querycase append_list[] = {
  782. {"HTTP://test/?s", "name=joe\x02", "http://test/?s&name=joe%02",
  783. 0, CURLU_URLENCODE, CURLUE_OK},
  784. {"HTTP://test/?size=2#f", "name=joe=", "http://test/?size=2&name=joe%3d#f",
  785. 0, CURLU_URLENCODE, CURLUE_OK},
  786. {"HTTP://test/?size=2#f", "name=joe doe",
  787. "http://test/?size=2&name=joe+doe#f",
  788. 0, CURLU_URLENCODE, CURLUE_OK},
  789. {"HTTP://test/", "name=joe", "http://test/?name=joe", 0, 0, CURLUE_OK},
  790. {"HTTP://test/?size=2", "name=joe", "http://test/?size=2&name=joe",
  791. 0, 0, CURLUE_OK},
  792. {"HTTP://test/?size=2&", "name=joe", "http://test/?size=2&name=joe",
  793. 0, 0, CURLUE_OK},
  794. {"HTTP://test/?size=2#f", "name=joe", "http://test/?size=2&name=joe#f",
  795. 0, 0, CURLUE_OK},
  796. {NULL, NULL, NULL, 0, 0, 0}
  797. };
  798. static int append(void)
  799. {
  800. int i;
  801. int error = 0;
  802. for(i = 0; append_list[i].in && !error; i++) {
  803. CURLUcode rc;
  804. CURLU *urlp = curl_url();
  805. if(!urlp) {
  806. error++;
  807. break;
  808. }
  809. rc = curl_url_set(urlp, CURLUPART_URL,
  810. append_list[i].in,
  811. append_list[i].urlflags);
  812. if(rc)
  813. error++;
  814. else
  815. rc = curl_url_set(urlp, CURLUPART_QUERY,
  816. append_list[i].q,
  817. append_list[i].qflags | CURLU_APPENDQUERY);
  818. if(error)
  819. ;
  820. else if(rc != append_list[i].ucode) {
  821. fprintf(stderr, "Append\nin: %s\nreturned %d (expected %d)\n",
  822. append_list[i].in, (int)rc, append_list[i].ucode);
  823. error++;
  824. }
  825. else if(append_list[i].ucode) {
  826. /* the expected error happened */
  827. }
  828. else {
  829. char *url;
  830. rc = curl_url_get(urlp, CURLUPART_URL, &url, 0);
  831. if(rc) {
  832. fprintf(stderr, "%s:%d Get URL returned %d\n",
  833. __FILE__, __LINE__, (int)rc);
  834. error++;
  835. }
  836. else {
  837. if(checkurl(url, append_list[i].out)) {
  838. error++;
  839. }
  840. curl_free(url);
  841. }
  842. }
  843. curl_url_cleanup(urlp);
  844. }
  845. return error;
  846. }
  847. static int scopeid(void)
  848. {
  849. CURLU *u = curl_url();
  850. int error = 0;
  851. CURLUcode rc;
  852. char *url;
  853. rc = curl_url_set(u, CURLUPART_URL,
  854. "https://[fe80::20c:29ff:fe9c:409b%25eth0]/hello.html", 0);
  855. if(rc != CURLUE_OK) {
  856. fprintf(stderr, "%s:%d curl_url_set returned %d\n",
  857. __FILE__, __LINE__, (int)rc);
  858. error++;
  859. }
  860. rc = curl_url_get(u, CURLUPART_HOST, &url, 0);
  861. if(rc != CURLUE_OK) {
  862. fprintf(stderr, "%s:%d curl_url_get CURLUPART_HOST returned %d\n",
  863. __FILE__, __LINE__, (int)rc);
  864. error++;
  865. }
  866. else {
  867. printf("we got %s\n", url);
  868. curl_free(url);
  869. }
  870. rc = curl_url_set(u, CURLUPART_HOST, "[::1]", 0);
  871. if(rc != CURLUE_OK) {
  872. fprintf(stderr, "%s:%d curl_url_set CURLUPART_HOST returned %d\n",
  873. __FILE__, __LINE__, (int)rc);
  874. error++;
  875. }
  876. rc = curl_url_get(u, CURLUPART_URL, &url, 0);
  877. if(rc != CURLUE_OK) {
  878. fprintf(stderr, "%s:%d curl_url_get CURLUPART_URL returned %d\n",
  879. __FILE__, __LINE__, (int)rc);
  880. error++;
  881. }
  882. else {
  883. printf("we got %s\n", url);
  884. curl_free(url);
  885. }
  886. rc = curl_url_set(u, CURLUPART_HOST, "example.com", 0);
  887. if(rc != CURLUE_OK) {
  888. fprintf(stderr, "%s:%d curl_url_set CURLUPART_HOST returned %d\n",
  889. __FILE__, __LINE__, (int)rc);
  890. error++;
  891. }
  892. rc = curl_url_get(u, CURLUPART_URL, &url, 0);
  893. if(rc != CURLUE_OK) {
  894. fprintf(stderr, "%s:%d curl_url_get CURLUPART_URL returned %d\n",
  895. __FILE__, __LINE__, (int)rc);
  896. error++;
  897. }
  898. else {
  899. printf("we got %s\n", url);
  900. curl_free(url);
  901. }
  902. rc = curl_url_set(u, CURLUPART_HOST,
  903. "[fe80::20c:29ff:fe9c:409b%25eth0]", 0);
  904. if(rc != CURLUE_OK) {
  905. fprintf(stderr, "%s:%d curl_url_set CURLUPART_HOST returned %d\n",
  906. __FILE__, __LINE__, (int)rc);
  907. error++;
  908. }
  909. rc = curl_url_get(u, CURLUPART_URL, &url, 0);
  910. if(rc != CURLUE_OK) {
  911. fprintf(stderr, "%s:%d curl_url_get CURLUPART_URL returned %d\n",
  912. __FILE__, __LINE__, (int)rc);
  913. error++;
  914. }
  915. else {
  916. printf("we got %s\n", url);
  917. curl_free(url);
  918. }
  919. rc = curl_url_get(u, CURLUPART_HOST, &url, 0);
  920. if(rc != CURLUE_OK) {
  921. fprintf(stderr, "%s:%d curl_url_get CURLUPART_HOST returned %d\n",
  922. __FILE__, __LINE__, (int)rc);
  923. error++;
  924. }
  925. else {
  926. printf("we got %s\n", url);
  927. curl_free(url);
  928. }
  929. rc = curl_url_get(u, CURLUPART_ZONEID, &url, 0);
  930. if(rc != CURLUE_OK) {
  931. fprintf(stderr, "%s:%d curl_url_get CURLUPART_ZONEID returned %d\n",
  932. __FILE__, __LINE__, (int)rc);
  933. error++;
  934. }
  935. else {
  936. printf("we got %s\n", url);
  937. curl_free(url);
  938. }
  939. rc = curl_url_set(u, CURLUPART_ZONEID, "clown", 0);
  940. if(rc != CURLUE_OK) {
  941. fprintf(stderr, "%s:%d curl_url_set CURLUPART_ZONEID returned %d\n",
  942. __FILE__, __LINE__, (int)rc);
  943. error++;
  944. }
  945. rc = curl_url_get(u, CURLUPART_URL, &url, 0);
  946. if(rc != CURLUE_OK) {
  947. fprintf(stderr, "%s:%d curl_url_get CURLUPART_URL returned %d\n",
  948. __FILE__, __LINE__, (int)rc);
  949. error++;
  950. }
  951. else {
  952. printf("we got %s\n", url);
  953. curl_free(url);
  954. }
  955. curl_url_cleanup(u);
  956. return error;
  957. }
  958. int test(char *URL)
  959. {
  960. (void)URL; /* not used */
  961. if(scopeid())
  962. return 6;
  963. if(append())
  964. return 5;
  965. if(set_url())
  966. return 1;
  967. if(set_parts())
  968. return 2;
  969. if(get_url())
  970. return 3;
  971. if(get_parts())
  972. return 4;
  973. printf("success\n");
  974. return 0;
  975. }