tool_getparam.c 75 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2020, 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. #include "tool_setup.h"
  23. #include "strcase.h"
  24. #define ENABLE_CURLX_PRINTF
  25. /* use our own printf() functions */
  26. #include "curlx.h"
  27. #include "tool_binmode.h"
  28. #include "tool_cfgable.h"
  29. #include "tool_cb_prg.h"
  30. #include "tool_convert.h"
  31. #include "tool_filetime.h"
  32. #include "tool_formparse.h"
  33. #include "tool_getparam.h"
  34. #include "tool_helpers.h"
  35. #include "tool_libinfo.h"
  36. #include "tool_metalink.h"
  37. #include "tool_msgs.h"
  38. #include "tool_paramhlp.h"
  39. #include "tool_parsecfg.h"
  40. #include "tool_main.h"
  41. #include "memdebug.h" /* keep this as LAST include */
  42. #ifdef MSDOS
  43. # define USE_WATT32
  44. #endif
  45. #define GetStr(str,val) do { \
  46. if(*(str)) { \
  47. free(*(str)); \
  48. *(str) = NULL; \
  49. } \
  50. if((val)) { \
  51. *(str) = strdup((val)); \
  52. if(!(*(str))) \
  53. return PARAM_NO_MEM; \
  54. } \
  55. } while(0)
  56. struct LongShort {
  57. const char *letter; /* short name option */
  58. const char *lname; /* long name option */
  59. enum {
  60. ARG_NONE, /* stand-alone but not a boolean */
  61. ARG_BOOL, /* accepts a --no-[name] prefix */
  62. ARG_STRING, /* requires an argument */
  63. ARG_FILENAME /* requires an argument, usually a file name */
  64. } desc;
  65. };
  66. static const struct LongShort aliases[]= {
  67. /* 'letter' strings with more than one character have *no* short option to
  68. mention. */
  69. {"*@", "url", ARG_STRING},
  70. {"*4", "dns-ipv4-addr", ARG_STRING},
  71. {"*6", "dns-ipv6-addr", ARG_STRING},
  72. {"*a", "random-file", ARG_FILENAME},
  73. {"*b", "egd-file", ARG_STRING},
  74. {"*B", "oauth2-bearer", ARG_STRING},
  75. {"*c", "connect-timeout", ARG_STRING},
  76. {"*C", "doh-url" , ARG_STRING},
  77. {"*d", "ciphers", ARG_STRING},
  78. {"*D", "dns-interface", ARG_STRING},
  79. {"*e", "disable-epsv", ARG_BOOL},
  80. {"*f", "disallow-username-in-url", ARG_BOOL},
  81. {"*E", "epsv", ARG_BOOL},
  82. /* 'epsv' made like this to make --no-epsv and --epsv to work
  83. although --disable-epsv is the documented option */
  84. {"*F", "dns-servers", ARG_STRING},
  85. {"*g", "trace", ARG_FILENAME},
  86. {"*G", "npn", ARG_BOOL},
  87. {"*h", "trace-ascii", ARG_FILENAME},
  88. {"*H", "alpn", ARG_BOOL},
  89. {"*i", "limit-rate", ARG_STRING},
  90. {"*j", "compressed", ARG_BOOL},
  91. {"*J", "tr-encoding", ARG_BOOL},
  92. {"*k", "digest", ARG_BOOL},
  93. {"*l", "negotiate", ARG_BOOL},
  94. {"*m", "ntlm", ARG_BOOL},
  95. {"*M", "ntlm-wb", ARG_BOOL},
  96. {"*n", "basic", ARG_BOOL},
  97. {"*o", "anyauth", ARG_BOOL},
  98. #ifdef USE_WATT32
  99. {"*p", "wdebug", ARG_BOOL},
  100. #endif
  101. {"*q", "ftp-create-dirs", ARG_BOOL},
  102. {"*r", "create-dirs", ARG_BOOL},
  103. {"*s", "max-redirs", ARG_STRING},
  104. {"*t", "proxy-ntlm", ARG_BOOL},
  105. {"*u", "crlf", ARG_BOOL},
  106. {"*v", "stderr", ARG_FILENAME},
  107. {"*w", "interface", ARG_STRING},
  108. {"*x", "krb", ARG_STRING},
  109. {"*x", "krb4", ARG_STRING},
  110. /* 'krb4' is the previous name */
  111. {"*X", "haproxy-protocol", ARG_BOOL},
  112. {"*y", "max-filesize", ARG_STRING},
  113. {"*z", "disable-eprt", ARG_BOOL},
  114. {"*Z", "eprt", ARG_BOOL},
  115. /* 'eprt' made like this to make --no-eprt and --eprt to work
  116. although --disable-eprt is the documented option */
  117. {"*~", "xattr", ARG_BOOL},
  118. {"$a", "ftp-ssl", ARG_BOOL},
  119. /* 'ftp-ssl' deprecated name since 7.20.0 */
  120. {"$a", "ssl", ARG_BOOL},
  121. /* 'ssl' new option name in 7.20.0, previously this was ftp-ssl */
  122. {"$b", "ftp-pasv", ARG_BOOL},
  123. {"$c", "socks5", ARG_STRING},
  124. {"$d", "tcp-nodelay", ARG_BOOL},
  125. {"$e", "proxy-digest", ARG_BOOL},
  126. {"$f", "proxy-basic", ARG_BOOL},
  127. {"$g", "retry", ARG_STRING},
  128. {"$V", "retry-connrefused", ARG_BOOL},
  129. {"$h", "retry-delay", ARG_STRING},
  130. {"$i", "retry-max-time", ARG_STRING},
  131. {"$k", "proxy-negotiate", ARG_BOOL},
  132. {"$m", "ftp-account", ARG_STRING},
  133. {"$n", "proxy-anyauth", ARG_BOOL},
  134. {"$o", "trace-time", ARG_BOOL},
  135. {"$p", "ignore-content-length", ARG_BOOL},
  136. {"$q", "ftp-skip-pasv-ip", ARG_BOOL},
  137. {"$r", "ftp-method", ARG_STRING},
  138. {"$s", "local-port", ARG_STRING},
  139. {"$t", "socks4", ARG_STRING},
  140. {"$T", "socks4a", ARG_STRING},
  141. {"$u", "ftp-alternative-to-user", ARG_STRING},
  142. {"$v", "ftp-ssl-reqd", ARG_BOOL},
  143. /* 'ftp-ssl-reqd' deprecated name since 7.20.0 */
  144. {"$v", "ssl-reqd", ARG_BOOL},
  145. /* 'ssl-reqd' new in 7.20.0, previously this was ftp-ssl-reqd */
  146. {"$w", "sessionid", ARG_BOOL},
  147. /* 'sessionid' listed as --no-sessionid in the help */
  148. {"$x", "ftp-ssl-control", ARG_BOOL},
  149. {"$y", "ftp-ssl-ccc", ARG_BOOL},
  150. {"$j", "ftp-ssl-ccc-mode", ARG_STRING},
  151. {"$z", "libcurl", ARG_STRING},
  152. {"$#", "raw", ARG_BOOL},
  153. {"$0", "post301", ARG_BOOL},
  154. {"$1", "keepalive", ARG_BOOL},
  155. /* 'keepalive' listed as --no-keepalive in the help */
  156. {"$2", "socks5-hostname", ARG_STRING},
  157. {"$3", "keepalive-time", ARG_STRING},
  158. {"$4", "post302", ARG_BOOL},
  159. {"$5", "noproxy", ARG_STRING},
  160. {"$7", "socks5-gssapi-nec", ARG_BOOL},
  161. {"$8", "proxy1.0", ARG_STRING},
  162. {"$9", "tftp-blksize", ARG_STRING},
  163. {"$A", "mail-from", ARG_STRING},
  164. {"$B", "mail-rcpt", ARG_STRING},
  165. {"$C", "ftp-pret", ARG_BOOL},
  166. {"$D", "proto", ARG_STRING},
  167. {"$E", "proto-redir", ARG_STRING},
  168. {"$F", "resolve", ARG_STRING},
  169. {"$G", "delegation", ARG_STRING},
  170. {"$H", "mail-auth", ARG_STRING},
  171. {"$I", "post303", ARG_BOOL},
  172. {"$J", "metalink", ARG_BOOL},
  173. {"$6", "sasl-authzid", ARG_STRING},
  174. {"$K", "sasl-ir", ARG_BOOL },
  175. {"$L", "test-event", ARG_BOOL},
  176. {"$M", "unix-socket", ARG_FILENAME},
  177. {"$N", "path-as-is", ARG_BOOL},
  178. {"$O", "socks5-gssapi-service", ARG_STRING},
  179. /* 'socks5-gssapi-service' merged with'proxy-service-name' and
  180. deprecated since 7.49.0 */
  181. {"$O", "proxy-service-name", ARG_STRING},
  182. {"$P", "service-name", ARG_STRING},
  183. {"$Q", "proto-default", ARG_STRING},
  184. {"$R", "expect100-timeout", ARG_STRING},
  185. {"$S", "tftp-no-options", ARG_BOOL},
  186. {"$U", "connect-to", ARG_STRING},
  187. {"$W", "abstract-unix-socket", ARG_FILENAME},
  188. {"$X", "tls-max", ARG_STRING},
  189. {"$Y", "suppress-connect-headers", ARG_BOOL},
  190. {"$Z", "compressed-ssh", ARG_BOOL},
  191. {"$~", "happy-eyeballs-timeout-ms", ARG_STRING},
  192. {"$!", "retry-all-errors", ARG_BOOL},
  193. {"0", "http1.0", ARG_NONE},
  194. {"01", "http1.1", ARG_NONE},
  195. {"02", "http2", ARG_NONE},
  196. {"03", "http2-prior-knowledge", ARG_NONE},
  197. {"04", "http3", ARG_NONE},
  198. {"09", "http0.9", ARG_BOOL},
  199. {"1", "tlsv1", ARG_NONE},
  200. {"10", "tlsv1.0", ARG_NONE},
  201. {"11", "tlsv1.1", ARG_NONE},
  202. {"12", "tlsv1.2", ARG_NONE},
  203. {"13", "tlsv1.3", ARG_NONE},
  204. {"1A", "tls13-ciphers", ARG_STRING},
  205. {"1B", "proxy-tls13-ciphers", ARG_STRING},
  206. {"2", "sslv2", ARG_NONE},
  207. {"3", "sslv3", ARG_NONE},
  208. {"4", "ipv4", ARG_NONE},
  209. {"6", "ipv6", ARG_NONE},
  210. {"a", "append", ARG_BOOL},
  211. {"A", "user-agent", ARG_STRING},
  212. {"b", "cookie", ARG_STRING},
  213. {"ba", "alt-svc", ARG_STRING},
  214. {"B", "use-ascii", ARG_BOOL},
  215. {"c", "cookie-jar", ARG_STRING},
  216. {"C", "continue-at", ARG_STRING},
  217. {"d", "data", ARG_STRING},
  218. {"dr", "data-raw", ARG_STRING},
  219. {"da", "data-ascii", ARG_STRING},
  220. {"db", "data-binary", ARG_STRING},
  221. {"de", "data-urlencode", ARG_STRING},
  222. {"D", "dump-header", ARG_FILENAME},
  223. {"e", "referer", ARG_STRING},
  224. {"E", "cert", ARG_FILENAME},
  225. {"Ea", "cacert", ARG_FILENAME},
  226. {"Eb", "cert-type", ARG_STRING},
  227. {"Ec", "key", ARG_FILENAME},
  228. {"Ed", "key-type", ARG_STRING},
  229. {"Ee", "pass", ARG_STRING},
  230. {"Ef", "engine", ARG_STRING},
  231. {"Eg", "capath", ARG_FILENAME},
  232. {"Eh", "pubkey", ARG_STRING},
  233. {"Ei", "hostpubmd5", ARG_STRING},
  234. {"Ej", "crlfile", ARG_FILENAME},
  235. {"Ek", "tlsuser", ARG_STRING},
  236. {"El", "tlspassword", ARG_STRING},
  237. {"Em", "tlsauthtype", ARG_STRING},
  238. {"En", "ssl-allow-beast", ARG_BOOL},
  239. /* Eo */
  240. {"Ep", "pinnedpubkey", ARG_STRING},
  241. {"EP", "proxy-pinnedpubkey", ARG_STRING},
  242. {"Eq", "cert-status", ARG_BOOL},
  243. {"Er", "false-start", ARG_BOOL},
  244. {"Es", "ssl-no-revoke", ARG_BOOL},
  245. {"ES", "ssl-revoke-best-effort", ARG_BOOL},
  246. {"Et", "tcp-fastopen", ARG_BOOL},
  247. {"Eu", "proxy-tlsuser", ARG_STRING},
  248. {"Ev", "proxy-tlspassword", ARG_STRING},
  249. {"Ew", "proxy-tlsauthtype", ARG_STRING},
  250. {"Ex", "proxy-cert", ARG_FILENAME},
  251. {"Ey", "proxy-cert-type", ARG_STRING},
  252. {"Ez", "proxy-key", ARG_FILENAME},
  253. {"E0", "proxy-key-type", ARG_STRING},
  254. {"E1", "proxy-pass", ARG_STRING},
  255. {"E2", "proxy-ciphers", ARG_STRING},
  256. {"E3", "proxy-crlfile", ARG_FILENAME},
  257. {"E4", "proxy-ssl-allow-beast", ARG_BOOL},
  258. {"E5", "login-options", ARG_STRING},
  259. {"E6", "proxy-cacert", ARG_FILENAME},
  260. {"E7", "proxy-capath", ARG_FILENAME},
  261. {"E8", "proxy-insecure", ARG_BOOL},
  262. {"E9", "proxy-tlsv1", ARG_NONE},
  263. {"EA", "socks5-basic", ARG_BOOL},
  264. {"EB", "socks5-gssapi", ARG_BOOL},
  265. {"EC", "etag-save", ARG_FILENAME},
  266. {"ED", "etag-compare", ARG_FILENAME},
  267. {"EE", "curves", ARG_STRING},
  268. {"f", "fail", ARG_BOOL},
  269. {"fa", "fail-early", ARG_BOOL},
  270. {"fb", "styled-output", ARG_BOOL},
  271. {"fc", "mail-rcpt-allowfails", ARG_BOOL},
  272. {"F", "form", ARG_STRING},
  273. {"Fs", "form-string", ARG_STRING},
  274. {"g", "globoff", ARG_BOOL},
  275. {"G", "get", ARG_NONE},
  276. {"Ga", "request-target", ARG_STRING},
  277. {"h", "help", ARG_BOOL},
  278. {"H", "header", ARG_STRING},
  279. {"Hp", "proxy-header", ARG_STRING},
  280. {"i", "include", ARG_BOOL},
  281. {"I", "head", ARG_BOOL},
  282. {"j", "junk-session-cookies", ARG_BOOL},
  283. {"J", "remote-header-name", ARG_BOOL},
  284. {"k", "insecure", ARG_BOOL},
  285. {"K", "config", ARG_FILENAME},
  286. {"l", "list-only", ARG_BOOL},
  287. {"L", "location", ARG_BOOL},
  288. {"Lt", "location-trusted", ARG_BOOL},
  289. {"m", "max-time", ARG_STRING},
  290. {"M", "manual", ARG_BOOL},
  291. {"n", "netrc", ARG_BOOL},
  292. {"no", "netrc-optional", ARG_BOOL},
  293. {"ne", "netrc-file", ARG_FILENAME},
  294. {"N", "buffer", ARG_BOOL},
  295. /* 'buffer' listed as --no-buffer in the help */
  296. {"o", "output", ARG_FILENAME},
  297. {"O", "remote-name", ARG_NONE},
  298. {"Oa", "remote-name-all", ARG_BOOL},
  299. {"Ob", "output-dir", ARG_STRING},
  300. {"p", "proxytunnel", ARG_BOOL},
  301. {"P", "ftp-port", ARG_STRING},
  302. {"q", "disable", ARG_BOOL},
  303. {"Q", "quote", ARG_STRING},
  304. {"r", "range", ARG_STRING},
  305. {"R", "remote-time", ARG_BOOL},
  306. {"s", "silent", ARG_BOOL},
  307. {"S", "show-error", ARG_BOOL},
  308. {"t", "telnet-option", ARG_STRING},
  309. {"T", "upload-file", ARG_FILENAME},
  310. {"u", "user", ARG_STRING},
  311. {"U", "proxy-user", ARG_STRING},
  312. {"v", "verbose", ARG_BOOL},
  313. {"V", "version", ARG_BOOL},
  314. {"w", "write-out", ARG_STRING},
  315. {"x", "proxy", ARG_STRING},
  316. {"xa", "preproxy", ARG_STRING},
  317. {"X", "request", ARG_STRING},
  318. {"Y", "speed-limit", ARG_STRING},
  319. {"y", "speed-time", ARG_STRING},
  320. {"z", "time-cond", ARG_STRING},
  321. {"Z", "parallel", ARG_BOOL},
  322. {"Zb", "parallel-max", ARG_STRING},
  323. {"Zc", "parallel-immediate", ARG_BOOL},
  324. {"#", "progress-bar", ARG_BOOL},
  325. {"#m", "progress-meter", ARG_BOOL},
  326. {":", "next", ARG_NONE},
  327. };
  328. /* Split the argument of -E to 'certname' and 'passphrase' separated by colon.
  329. * We allow ':' and '\' to be escaped by '\' so that we can use certificate
  330. * nicknames containing ':'. See <https://sourceforge.net/p/curl/bugs/1196/>
  331. * for details. */
  332. #ifndef UNITTESTS
  333. static
  334. #endif
  335. void parse_cert_parameter(const char *cert_parameter,
  336. char **certname,
  337. char **passphrase)
  338. {
  339. size_t param_length = strlen(cert_parameter);
  340. size_t span;
  341. const char *param_place = NULL;
  342. char *certname_place = NULL;
  343. *certname = NULL;
  344. *passphrase = NULL;
  345. /* most trivial assumption: cert_parameter is empty */
  346. if(param_length == 0)
  347. return;
  348. /* next less trivial: cert_parameter starts 'pkcs11:' and thus
  349. * looks like a RFC7512 PKCS#11 URI which can be used as-is.
  350. * Also if cert_parameter contains no colon nor backslash, this
  351. * means no passphrase was given and no characters escaped */
  352. if(curl_strnequal(cert_parameter, "pkcs11:", 7) ||
  353. !strpbrk(cert_parameter, ":\\")) {
  354. *certname = strdup(cert_parameter);
  355. return;
  356. }
  357. /* deal with escaped chars; find unescaped colon if it exists */
  358. certname_place = malloc(param_length + 1);
  359. if(!certname_place)
  360. return;
  361. *certname = certname_place;
  362. param_place = cert_parameter;
  363. while(*param_place) {
  364. span = strcspn(param_place, ":\\");
  365. strncpy(certname_place, param_place, span);
  366. param_place += span;
  367. certname_place += span;
  368. /* we just ate all the non-special chars. now we're on either a special
  369. * char or the end of the string. */
  370. switch(*param_place) {
  371. case '\0':
  372. break;
  373. case '\\':
  374. param_place++;
  375. switch(*param_place) {
  376. case '\0':
  377. *certname_place++ = '\\';
  378. break;
  379. case '\\':
  380. *certname_place++ = '\\';
  381. param_place++;
  382. break;
  383. case ':':
  384. *certname_place++ = ':';
  385. param_place++;
  386. break;
  387. default:
  388. *certname_place++ = '\\';
  389. *certname_place++ = *param_place;
  390. param_place++;
  391. break;
  392. }
  393. break;
  394. case ':':
  395. /* Since we live in a world of weirdness and confusion, the win32
  396. dudes can use : when using drive letters and thus c:\file:password
  397. needs to work. In order not to break compatibility, we still use : as
  398. separator, but we try to detect when it is used for a file name! On
  399. windows. */
  400. #ifdef WIN32
  401. if(param_place &&
  402. (param_place == &cert_parameter[1]) &&
  403. (cert_parameter[2] == '\\' || cert_parameter[2] == '/') &&
  404. (ISALPHA(cert_parameter[0])) ) {
  405. /* colon in the second column, followed by a backslash, and the
  406. first character is an alphabetic letter:
  407. this is a drive letter colon */
  408. *certname_place++ = ':';
  409. param_place++;
  410. break;
  411. }
  412. #endif
  413. /* escaped colons and Windows drive letter colons were handled
  414. * above; if we're still here, this is a separating colon */
  415. param_place++;
  416. if(*param_place) {
  417. *passphrase = strdup(param_place);
  418. }
  419. goto done;
  420. }
  421. }
  422. done:
  423. *certname_place = '\0';
  424. }
  425. static void
  426. GetFileAndPassword(char *nextarg, char **file, char **password)
  427. {
  428. char *certname, *passphrase;
  429. parse_cert_parameter(nextarg, &certname, &passphrase);
  430. Curl_safefree(*file);
  431. *file = certname;
  432. if(passphrase) {
  433. Curl_safefree(*password);
  434. *password = passphrase;
  435. }
  436. cleanarg(nextarg);
  437. }
  438. /* Get a size parameter for '--limit-rate' or '--max-filesize'.
  439. * We support a 'G', 'M' or 'K' suffix too.
  440. */
  441. static ParameterError GetSizeParameter(struct GlobalConfig *global,
  442. const char *arg,
  443. const char *which,
  444. curl_off_t *value_out)
  445. {
  446. char *unit;
  447. curl_off_t value;
  448. if(curlx_strtoofft(arg, &unit, 0, &value)) {
  449. warnf(global, "invalid number specified for %s\n", which);
  450. return PARAM_BAD_USE;
  451. }
  452. if(!*unit)
  453. unit = (char *)"b";
  454. else if(strlen(unit) > 1)
  455. unit = (char *)"w"; /* unsupported */
  456. switch(*unit) {
  457. case 'G':
  458. case 'g':
  459. if(value > (CURL_OFF_T_MAX / (1024*1024*1024)))
  460. return PARAM_NUMBER_TOO_LARGE;
  461. value *= 1024*1024*1024;
  462. break;
  463. case 'M':
  464. case 'm':
  465. if(value > (CURL_OFF_T_MAX / (1024*1024)))
  466. return PARAM_NUMBER_TOO_LARGE;
  467. value *= 1024*1024;
  468. break;
  469. case 'K':
  470. case 'k':
  471. if(value > (CURL_OFF_T_MAX / 1024))
  472. return PARAM_NUMBER_TOO_LARGE;
  473. value *= 1024;
  474. break;
  475. case 'b':
  476. case 'B':
  477. /* for plain bytes, leave as-is */
  478. break;
  479. default:
  480. warnf(global, "unsupported %s unit. Use G, M, K or B!\n", which);
  481. return PARAM_BAD_USE;
  482. }
  483. *value_out = value;
  484. return PARAM_OK;
  485. }
  486. ParameterError getparameter(const char *flag, /* f or -long-flag */
  487. char *nextarg, /* NULL if unset */
  488. bool *usedarg, /* set to TRUE if the arg
  489. has been used */
  490. struct GlobalConfig *global,
  491. struct OperationConfig *config)
  492. {
  493. char letter;
  494. char subletter = '\0'; /* subletters can only occur on long options */
  495. int rc;
  496. const char *parse = NULL;
  497. unsigned int j;
  498. time_t now;
  499. int hit = -1;
  500. bool longopt = FALSE;
  501. bool singleopt = FALSE; /* when true means '-o foo' used '-ofoo' */
  502. ParameterError err;
  503. bool toggle = TRUE; /* how to switch boolean options, on or off. Controlled
  504. by using --OPTION or --no-OPTION */
  505. *usedarg = FALSE; /* default is that we don't use the arg */
  506. if(('-' != flag[0]) || ('-' == flag[1])) {
  507. /* this should be a long name */
  508. const char *word = ('-' == flag[0]) ? flag + 2 : flag;
  509. size_t fnam = strlen(word);
  510. int numhits = 0;
  511. bool noflagged = FALSE;
  512. if(!strncmp(word, "no-", 3)) {
  513. /* disable this option but ignore the "no-" part when looking for it */
  514. word += 3;
  515. toggle = FALSE;
  516. noflagged = TRUE;
  517. }
  518. for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
  519. if(curl_strnequal(aliases[j].lname, word, fnam)) {
  520. longopt = TRUE;
  521. numhits++;
  522. if(curl_strequal(aliases[j].lname, word)) {
  523. parse = aliases[j].letter;
  524. hit = j;
  525. numhits = 1; /* a single unique hit */
  526. break;
  527. }
  528. parse = aliases[j].letter;
  529. hit = j;
  530. }
  531. }
  532. if(numhits > 1) {
  533. /* this is at least the second match! */
  534. return PARAM_OPTION_AMBIGUOUS;
  535. }
  536. if(hit < 0) {
  537. return PARAM_OPTION_UNKNOWN;
  538. }
  539. if(noflagged && (aliases[hit].desc != ARG_BOOL))
  540. /* --no- prefixed an option that isn't boolean! */
  541. return PARAM_NO_NOT_BOOLEAN;
  542. }
  543. else {
  544. flag++; /* prefixed with one dash, pass it */
  545. hit = -1;
  546. parse = flag;
  547. }
  548. do {
  549. /* we can loop here if we have multiple single-letters */
  550. if(!longopt) {
  551. letter = (char)*parse;
  552. subletter = '\0';
  553. }
  554. else {
  555. letter = parse[0];
  556. subletter = parse[1];
  557. }
  558. if(hit < 0) {
  559. for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
  560. if(letter == aliases[j].letter[0]) {
  561. hit = j;
  562. break;
  563. }
  564. }
  565. if(hit < 0) {
  566. return PARAM_OPTION_UNKNOWN;
  567. }
  568. }
  569. if(aliases[hit].desc >= ARG_STRING) {
  570. /* this option requires an extra parameter */
  571. if(!longopt && parse[1]) {
  572. nextarg = (char *)&parse[1]; /* this is the actual extra parameter */
  573. singleopt = TRUE; /* don't loop anymore after this */
  574. }
  575. else if(!nextarg)
  576. return PARAM_REQUIRES_PARAMETER;
  577. else
  578. *usedarg = TRUE; /* mark it as used */
  579. if((aliases[hit].desc == ARG_FILENAME) &&
  580. (nextarg[0] == '-') && nextarg[1]) {
  581. /* if the file name looks like a command line option */
  582. warnf(global, "The file name argument '%s' looks like a flag.\n",
  583. nextarg);
  584. }
  585. }
  586. else if((aliases[hit].desc == ARG_NONE) && !toggle)
  587. return PARAM_NO_PREFIX;
  588. switch(letter) {
  589. case '*': /* options without a short option */
  590. switch(subletter) {
  591. case '4': /* --dns-ipv4-addr */
  592. /* addr in dot notation */
  593. GetStr(&config->dns_ipv4_addr, nextarg);
  594. break;
  595. case '6': /* --dns-ipv6-addr */
  596. /* addr in dot notation */
  597. GetStr(&config->dns_ipv6_addr, nextarg);
  598. break;
  599. case 'a': /* random-file */
  600. GetStr(&config->random_file, nextarg);
  601. break;
  602. case 'b': /* egd-file */
  603. GetStr(&config->egd_file, nextarg);
  604. break;
  605. case 'B': /* OAuth 2.0 bearer token */
  606. GetStr(&config->oauth_bearer, nextarg);
  607. config->authtype |= CURLAUTH_BEARER;
  608. break;
  609. case 'c': /* connect-timeout */
  610. err = str2udouble(&config->connecttimeout, nextarg,
  611. LONG_MAX/1000);
  612. if(err)
  613. return err;
  614. break;
  615. case 'C': /* doh-url */
  616. GetStr(&config->doh_url, nextarg);
  617. break;
  618. case 'd': /* ciphers */
  619. GetStr(&config->cipher_list, nextarg);
  620. break;
  621. case 'D': /* --dns-interface */
  622. /* interface name */
  623. GetStr(&config->dns_interface, nextarg);
  624. break;
  625. case 'e': /* --disable-epsv */
  626. config->disable_epsv = toggle;
  627. break;
  628. case 'f': /* --disallow-username-in-url */
  629. config->disallow_username_in_url = toggle;
  630. break;
  631. case 'E': /* --epsv */
  632. config->disable_epsv = (!toggle)?TRUE:FALSE;
  633. break;
  634. case 'F': /* --dns-servers */
  635. /* IP addrs of DNS servers */
  636. GetStr(&config->dns_servers, nextarg);
  637. break;
  638. case 'g': /* --trace */
  639. GetStr(&global->trace_dump, nextarg);
  640. if(global->tracetype && (global->tracetype != TRACE_BIN))
  641. warnf(global, "--trace overrides an earlier trace/verbose option\n");
  642. global->tracetype = TRACE_BIN;
  643. break;
  644. case 'G': /* --npn */
  645. config->nonpn = (!toggle)?TRUE:FALSE;
  646. break;
  647. case 'h': /* --trace-ascii */
  648. GetStr(&global->trace_dump, nextarg);
  649. if(global->tracetype && (global->tracetype != TRACE_ASCII))
  650. warnf(global,
  651. "--trace-ascii overrides an earlier trace/verbose option\n");
  652. global->tracetype = TRACE_ASCII;
  653. break;
  654. case 'H': /* --alpn */
  655. config->noalpn = (!toggle)?TRUE:FALSE;
  656. break;
  657. case 'i': /* --limit-rate */
  658. {
  659. curl_off_t value;
  660. ParameterError pe = GetSizeParameter(global, nextarg, "rate", &value);
  661. if(pe != PARAM_OK)
  662. return pe;
  663. config->recvpersecond = value;
  664. config->sendpersecond = value;
  665. }
  666. break;
  667. case 'j': /* --compressed */
  668. if(toggle &&
  669. !(curlinfo->features & (CURL_VERSION_LIBZ |
  670. CURL_VERSION_BROTLI | CURL_VERSION_ZSTD)))
  671. return PARAM_LIBCURL_DOESNT_SUPPORT;
  672. config->encoding = toggle;
  673. break;
  674. case 'J': /* --tr-encoding */
  675. config->tr_encoding = toggle;
  676. break;
  677. case 'k': /* --digest */
  678. if(toggle)
  679. config->authtype |= CURLAUTH_DIGEST;
  680. else
  681. config->authtype &= ~CURLAUTH_DIGEST;
  682. break;
  683. case 'l': /* --negotiate */
  684. if(toggle) {
  685. if(curlinfo->features & CURL_VERSION_SPNEGO)
  686. config->authtype |= CURLAUTH_NEGOTIATE;
  687. else
  688. return PARAM_LIBCURL_DOESNT_SUPPORT;
  689. }
  690. else
  691. config->authtype &= ~CURLAUTH_NEGOTIATE;
  692. break;
  693. case 'm': /* --ntlm */
  694. if(toggle) {
  695. if(curlinfo->features & CURL_VERSION_NTLM)
  696. config->authtype |= CURLAUTH_NTLM;
  697. else
  698. return PARAM_LIBCURL_DOESNT_SUPPORT;
  699. }
  700. else
  701. config->authtype &= ~CURLAUTH_NTLM;
  702. break;
  703. case 'M': /* --ntlm-wb */
  704. if(toggle) {
  705. if(curlinfo->features & CURL_VERSION_NTLM_WB)
  706. config->authtype |= CURLAUTH_NTLM_WB;
  707. else
  708. return PARAM_LIBCURL_DOESNT_SUPPORT;
  709. }
  710. else
  711. config->authtype &= ~CURLAUTH_NTLM_WB;
  712. break;
  713. case 'n': /* --basic for completeness */
  714. if(toggle)
  715. config->authtype |= CURLAUTH_BASIC;
  716. else
  717. config->authtype &= ~CURLAUTH_BASIC;
  718. break;
  719. case 'o': /* --anyauth, let libcurl pick it */
  720. if(toggle)
  721. config->authtype = CURLAUTH_ANY;
  722. /* --no-anyauth simply doesn't touch it */
  723. break;
  724. #ifdef USE_WATT32
  725. case 'p': /* --wdebug */
  726. dbug_init();
  727. break;
  728. #endif
  729. case 'q': /* --ftp-create-dirs */
  730. config->ftp_create_dirs = toggle;
  731. break;
  732. case 'r': /* --create-dirs */
  733. config->create_dirs = toggle;
  734. break;
  735. case 's': /* --max-redirs */
  736. /* specified max no of redirects (http(s)), this accepts -1 as a
  737. special condition */
  738. err = str2num(&config->maxredirs, nextarg);
  739. if(err)
  740. return err;
  741. if(config->maxredirs < -1)
  742. return PARAM_BAD_NUMERIC;
  743. break;
  744. case 't': /* --proxy-ntlm */
  745. if(curlinfo->features & CURL_VERSION_NTLM)
  746. config->proxyntlm = toggle;
  747. else
  748. return PARAM_LIBCURL_DOESNT_SUPPORT;
  749. break;
  750. case 'u': /* --crlf */
  751. /* LF -> CRLF conversion? */
  752. config->crlf = toggle;
  753. break;
  754. case 'v': /* --stderr */
  755. if(strcmp(nextarg, "-")) {
  756. FILE *newfile = fopen(nextarg, FOPEN_WRITETEXT);
  757. if(!newfile)
  758. warnf(global, "Failed to open %s!\n", nextarg);
  759. else {
  760. if(global->errors_fopened)
  761. fclose(global->errors);
  762. global->errors = newfile;
  763. global->errors_fopened = TRUE;
  764. }
  765. }
  766. else
  767. global->errors = stdout;
  768. break;
  769. case 'w': /* --interface */
  770. /* interface */
  771. GetStr(&config->iface, nextarg);
  772. break;
  773. case 'x': /* --krb */
  774. /* kerberos level string */
  775. if(curlinfo->features & CURL_VERSION_SPNEGO)
  776. GetStr(&config->krblevel, nextarg);
  777. else
  778. return PARAM_LIBCURL_DOESNT_SUPPORT;
  779. break;
  780. case 'X': /* --haproxy-protocol */
  781. config->haproxy_protocol = toggle;
  782. break;
  783. case 'y': /* --max-filesize */
  784. {
  785. curl_off_t value;
  786. ParameterError pe =
  787. GetSizeParameter(global, nextarg, "max-filesize", &value);
  788. if(pe != PARAM_OK)
  789. return pe;
  790. config->max_filesize = value;
  791. }
  792. break;
  793. case 'z': /* --disable-eprt */
  794. config->disable_eprt = toggle;
  795. break;
  796. case 'Z': /* --eprt */
  797. config->disable_eprt = (!toggle)?TRUE:FALSE;
  798. break;
  799. case '~': /* --xattr */
  800. config->xattr = toggle;
  801. break;
  802. case '@': /* the URL! */
  803. {
  804. struct getout *url;
  805. if(!config->url_get)
  806. config->url_get = config->url_list;
  807. if(config->url_get) {
  808. /* there's a node here, if it already is filled-in continue to find
  809. an "empty" node */
  810. while(config->url_get && (config->url_get->flags & GETOUT_URL))
  811. config->url_get = config->url_get->next;
  812. }
  813. /* now there might or might not be an available node to fill in! */
  814. if(config->url_get)
  815. /* existing node */
  816. url = config->url_get;
  817. else
  818. /* there was no free node, create one! */
  819. config->url_get = url = new_getout(config);
  820. if(!url)
  821. return PARAM_NO_MEM;
  822. /* fill in the URL */
  823. GetStr(&url->url, nextarg);
  824. url->flags |= GETOUT_URL;
  825. }
  826. }
  827. break;
  828. case '$': /* more options without a short option */
  829. switch(subletter) {
  830. case 'a': /* --ssl */
  831. if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
  832. return PARAM_LIBCURL_DOESNT_SUPPORT;
  833. config->ftp_ssl = toggle;
  834. break;
  835. case 'b': /* --ftp-pasv */
  836. Curl_safefree(config->ftpport);
  837. break;
  838. case 'c': /* --socks5 specifies a socks5 proxy to use, and resolves
  839. the name locally and passes on the resolved address */
  840. GetStr(&config->proxy, nextarg);
  841. config->proxyver = CURLPROXY_SOCKS5;
  842. break;
  843. case 't': /* --socks4 specifies a socks4 proxy to use */
  844. GetStr(&config->proxy, nextarg);
  845. config->proxyver = CURLPROXY_SOCKS4;
  846. break;
  847. case 'T': /* --socks4a specifies a socks4a proxy to use */
  848. GetStr(&config->proxy, nextarg);
  849. config->proxyver = CURLPROXY_SOCKS4A;
  850. break;
  851. case '2': /* --socks5-hostname specifies a socks5 proxy and enables name
  852. resolving with the proxy */
  853. GetStr(&config->proxy, nextarg);
  854. config->proxyver = CURLPROXY_SOCKS5_HOSTNAME;
  855. break;
  856. case 'd': /* --tcp-nodelay option */
  857. config->tcp_nodelay = toggle;
  858. break;
  859. case 'e': /* --proxy-digest */
  860. config->proxydigest = toggle;
  861. break;
  862. case 'f': /* --proxy-basic */
  863. config->proxybasic = toggle;
  864. break;
  865. case 'g': /* --retry */
  866. err = str2unum(&config->req_retry, nextarg);
  867. if(err)
  868. return err;
  869. break;
  870. case 'V': /* --retry-connrefused */
  871. config->retry_connrefused = toggle;
  872. break;
  873. case 'h': /* --retry-delay */
  874. err = str2unummax(&config->retry_delay, nextarg, LONG_MAX/1000);
  875. if(err)
  876. return err;
  877. break;
  878. case 'i': /* --retry-max-time */
  879. err = str2unummax(&config->retry_maxtime, nextarg, LONG_MAX/1000);
  880. if(err)
  881. return err;
  882. break;
  883. case '!': /* --retry-all-errors */
  884. config->retry_all_errors = toggle;
  885. break;
  886. case 'k': /* --proxy-negotiate */
  887. if(curlinfo->features & CURL_VERSION_SPNEGO)
  888. config->proxynegotiate = toggle;
  889. else
  890. return PARAM_LIBCURL_DOESNT_SUPPORT;
  891. break;
  892. case 'm': /* --ftp-account */
  893. GetStr(&config->ftp_account, nextarg);
  894. break;
  895. case 'n': /* --proxy-anyauth */
  896. config->proxyanyauth = toggle;
  897. break;
  898. case 'o': /* --trace-time */
  899. global->tracetime = toggle;
  900. break;
  901. case 'p': /* --ignore-content-length */
  902. config->ignorecl = toggle;
  903. break;
  904. case 'q': /* --ftp-skip-pasv-ip */
  905. config->ftp_skip_ip = toggle;
  906. break;
  907. case 'r': /* --ftp-method (undocumented at this point) */
  908. config->ftp_filemethod = ftpfilemethod(config, nextarg);
  909. break;
  910. case 's': { /* --local-port */
  911. char lrange[7]; /* 16bit base 10 is 5 digits, but we allow 6 so that
  912. this catches overflows, not just truncates */
  913. char *p = nextarg;
  914. while(ISDIGIT(*p))
  915. p++;
  916. if(*p) {
  917. /* if there's anything more than a plain decimal number */
  918. rc = sscanf(p, " - %6s", lrange);
  919. *p = 0; /* null-terminate to make str2unum() work below */
  920. }
  921. else
  922. rc = 0;
  923. err = str2unum(&config->localport, nextarg);
  924. if(err || (config->localport > 65535))
  925. return PARAM_BAD_USE;
  926. if(!rc)
  927. config->localportrange = 1; /* default number of ports to try */
  928. else {
  929. err = str2unum(&config->localportrange, lrange);
  930. if(err || (config->localportrange > 65535))
  931. return PARAM_BAD_USE;
  932. config->localportrange -= (config->localport-1);
  933. if(config->localportrange < 1)
  934. return PARAM_BAD_USE;
  935. }
  936. break;
  937. }
  938. case 'u': /* --ftp-alternative-to-user */
  939. GetStr(&config->ftp_alternative_to_user, nextarg);
  940. break;
  941. case 'v': /* --ssl-reqd */
  942. if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
  943. return PARAM_LIBCURL_DOESNT_SUPPORT;
  944. config->ftp_ssl_reqd = toggle;
  945. break;
  946. case 'w': /* --no-sessionid */
  947. config->disable_sessionid = (!toggle)?TRUE:FALSE;
  948. break;
  949. case 'x': /* --ftp-ssl-control */
  950. if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
  951. return PARAM_LIBCURL_DOESNT_SUPPORT;
  952. config->ftp_ssl_control = toggle;
  953. break;
  954. case 'y': /* --ftp-ssl-ccc */
  955. config->ftp_ssl_ccc = toggle;
  956. if(!config->ftp_ssl_ccc_mode)
  957. config->ftp_ssl_ccc_mode = CURLFTPSSL_CCC_PASSIVE;
  958. break;
  959. case 'j': /* --ftp-ssl-ccc-mode */
  960. config->ftp_ssl_ccc = TRUE;
  961. config->ftp_ssl_ccc_mode = ftpcccmethod(config, nextarg);
  962. break;
  963. case 'z': /* --libcurl */
  964. #ifdef CURL_DISABLE_LIBCURL_OPTION
  965. warnf(global,
  966. "--libcurl option was disabled at build-time!\n");
  967. return PARAM_OPTION_UNKNOWN;
  968. #else
  969. GetStr(&global->libcurl, nextarg);
  970. break;
  971. #endif
  972. case '#': /* --raw */
  973. config->raw = toggle;
  974. break;
  975. case '0': /* --post301 */
  976. config->post301 = toggle;
  977. break;
  978. case '1': /* --no-keepalive */
  979. config->nokeepalive = (!toggle)?TRUE:FALSE;
  980. break;
  981. case '3': /* --keepalive-time */
  982. err = str2unum(&config->alivetime, nextarg);
  983. if(err)
  984. return err;
  985. break;
  986. case '4': /* --post302 */
  987. config->post302 = toggle;
  988. break;
  989. case 'I': /* --post303 */
  990. config->post303 = toggle;
  991. break;
  992. case '5': /* --noproxy */
  993. /* This specifies the noproxy list */
  994. GetStr(&config->noproxy, nextarg);
  995. break;
  996. case '7': /* --socks5-gssapi-nec*/
  997. config->socks5_gssapi_nec = toggle;
  998. break;
  999. case '8': /* --proxy1.0 */
  1000. /* http 1.0 proxy */
  1001. GetStr(&config->proxy, nextarg);
  1002. config->proxyver = CURLPROXY_HTTP_1_0;
  1003. break;
  1004. case '9': /* --tftp-blksize */
  1005. err = str2unum(&config->tftp_blksize, nextarg);
  1006. if(err)
  1007. return err;
  1008. break;
  1009. case 'A': /* --mail-from */
  1010. GetStr(&config->mail_from, nextarg);
  1011. break;
  1012. case 'B': /* --mail-rcpt */
  1013. /* append receiver to a list */
  1014. err = add2list(&config->mail_rcpt, nextarg);
  1015. if(err)
  1016. return err;
  1017. break;
  1018. case 'C': /* --ftp-pret */
  1019. config->ftp_pret = toggle;
  1020. break;
  1021. case 'D': /* --proto */
  1022. config->proto_present = TRUE;
  1023. if(proto2num(config, &config->proto, nextarg))
  1024. return PARAM_BAD_USE;
  1025. break;
  1026. case 'E': /* --proto-redir */
  1027. config->proto_redir_present = TRUE;
  1028. if(proto2num(config, &config->proto_redir, nextarg))
  1029. return PARAM_BAD_USE;
  1030. break;
  1031. case 'F': /* --resolve */
  1032. err = add2list(&config->resolve, nextarg);
  1033. if(err)
  1034. return err;
  1035. break;
  1036. case 'G': /* --delegation LEVEL */
  1037. config->gssapi_delegation = delegation(config, nextarg);
  1038. break;
  1039. case 'H': /* --mail-auth */
  1040. GetStr(&config->mail_auth, nextarg);
  1041. break;
  1042. case 'J': /* --metalink */
  1043. {
  1044. #ifdef USE_METALINK
  1045. int mlmaj, mlmin, mlpatch;
  1046. metalink_get_version(&mlmaj, &mlmin, &mlpatch);
  1047. if((mlmaj*10000)+(mlmin*100) + mlpatch < CURL_REQ_LIBMETALINK_VERS) {
  1048. warnf(global,
  1049. "--metalink option cannot be used because the version of "
  1050. "the linked libmetalink library is too old. "
  1051. "Required: %d.%d.%d, found %d.%d.%d\n",
  1052. CURL_REQ_LIBMETALINK_MAJOR,
  1053. CURL_REQ_LIBMETALINK_MINOR,
  1054. CURL_REQ_LIBMETALINK_PATCH,
  1055. mlmaj, mlmin, mlpatch);
  1056. return PARAM_BAD_USE;
  1057. }
  1058. else
  1059. config->use_metalink = toggle;
  1060. #else
  1061. warnf(global, "--metalink option is ignored because the binary is "
  1062. "built without the Metalink support.\n");
  1063. #endif
  1064. break;
  1065. }
  1066. case '6': /* --sasl-authzid */
  1067. GetStr(&config->sasl_authzid, nextarg);
  1068. break;
  1069. case 'K': /* --sasl-ir */
  1070. config->sasl_ir = toggle;
  1071. break;
  1072. case 'L': /* --test-event */
  1073. #ifdef CURLDEBUG
  1074. global->test_event_based = toggle;
  1075. #else
  1076. warnf(global, "--test-event is ignored unless a debug build!\n");
  1077. #endif
  1078. break;
  1079. case 'M': /* --unix-socket */
  1080. config->abstract_unix_socket = FALSE;
  1081. GetStr(&config->unix_socket_path, nextarg);
  1082. break;
  1083. case 'N': /* --path-as-is */
  1084. config->path_as_is = toggle;
  1085. break;
  1086. case 'O': /* --proxy-service-name */
  1087. GetStr(&config->proxy_service_name, nextarg);
  1088. break;
  1089. case 'P': /* --service-name */
  1090. GetStr(&config->service_name, nextarg);
  1091. break;
  1092. case 'Q': /* --proto-default */
  1093. GetStr(&config->proto_default, nextarg);
  1094. err = check_protocol(config->proto_default);
  1095. if(err)
  1096. return err;
  1097. break;
  1098. case 'R': /* --expect100-timeout */
  1099. err = str2udouble(&config->expect100timeout, nextarg, LONG_MAX/1000);
  1100. if(err)
  1101. return err;
  1102. break;
  1103. case 'S': /* --tftp-no-options */
  1104. config->tftp_no_options = toggle;
  1105. break;
  1106. case 'U': /* --connect-to */
  1107. err = add2list(&config->connect_to, nextarg);
  1108. if(err)
  1109. return err;
  1110. break;
  1111. case 'W': /* --abstract-unix-socket */
  1112. config->abstract_unix_socket = TRUE;
  1113. GetStr(&config->unix_socket_path, nextarg);
  1114. break;
  1115. case 'X': /* --tls-max */
  1116. err = str2tls_max(&config->ssl_version_max, nextarg);
  1117. if(err)
  1118. return err;
  1119. break;
  1120. case 'Y': /* --suppress-connect-headers */
  1121. config->suppress_connect_headers = toggle;
  1122. break;
  1123. case 'Z': /* --compressed-ssh */
  1124. config->ssh_compression = toggle;
  1125. break;
  1126. case '~': /* --happy-eyeballs-timeout-ms */
  1127. err = str2unum(&config->happy_eyeballs_timeout_ms, nextarg);
  1128. if(err)
  1129. return err;
  1130. /* 0 is a valid value for this timeout */
  1131. break;
  1132. }
  1133. break;
  1134. case '#':
  1135. switch(subletter) {
  1136. case 'm': /* --progress-meter */
  1137. global->noprogress = !toggle;
  1138. break;
  1139. default: /* --progress-bar */
  1140. global->progressmode =
  1141. toggle ? CURL_PROGRESS_BAR : CURL_PROGRESS_STATS;
  1142. break;
  1143. }
  1144. break;
  1145. case ':': /* --next */
  1146. return PARAM_NEXT_OPERATION;
  1147. case '0': /* --http* options */
  1148. switch(subletter) {
  1149. case '\0':
  1150. /* HTTP version 1.0 */
  1151. config->httpversion = CURL_HTTP_VERSION_1_0;
  1152. break;
  1153. case '1':
  1154. /* HTTP version 1.1 */
  1155. config->httpversion = CURL_HTTP_VERSION_1_1;
  1156. break;
  1157. case '2':
  1158. /* HTTP version 2.0 */
  1159. config->httpversion = CURL_HTTP_VERSION_2_0;
  1160. break;
  1161. case '3': /* --http2-prior-knowledge */
  1162. /* HTTP version 2.0 over clean TCP*/
  1163. config->httpversion = CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE;
  1164. break;
  1165. case '4': /* --http3 */
  1166. /* HTTP version 3 go over QUIC - at once */
  1167. if(curlinfo->features & CURL_VERSION_HTTP3)
  1168. config->httpversion = CURL_HTTP_VERSION_3;
  1169. else
  1170. return PARAM_LIBCURL_DOESNT_SUPPORT;
  1171. break;
  1172. case '9':
  1173. /* Allow HTTP/0.9 responses! */
  1174. config->http09_allowed = toggle;
  1175. break;
  1176. }
  1177. break;
  1178. case '1': /* --tlsv1* options */
  1179. switch(subletter) {
  1180. case '\0':
  1181. /* TLS version 1.x */
  1182. config->ssl_version = CURL_SSLVERSION_TLSv1;
  1183. break;
  1184. case '0':
  1185. /* TLS version 1.0 */
  1186. config->ssl_version = CURL_SSLVERSION_TLSv1_0;
  1187. break;
  1188. case '1':
  1189. /* TLS version 1.1 */
  1190. config->ssl_version = CURL_SSLVERSION_TLSv1_1;
  1191. break;
  1192. case '2':
  1193. /* TLS version 1.2 */
  1194. config->ssl_version = CURL_SSLVERSION_TLSv1_2;
  1195. break;
  1196. case '3':
  1197. /* TLS version 1.3 */
  1198. config->ssl_version = CURL_SSLVERSION_TLSv1_3;
  1199. break;
  1200. case 'A': /* --tls13-ciphers */
  1201. GetStr(&config->cipher13_list, nextarg);
  1202. break;
  1203. case 'B': /* --proxy-tls13-ciphers */
  1204. GetStr(&config->proxy_cipher13_list, nextarg);
  1205. break;
  1206. }
  1207. break;
  1208. case '2':
  1209. /* SSL version 2 */
  1210. config->ssl_version = CURL_SSLVERSION_SSLv2;
  1211. break;
  1212. case '3':
  1213. /* SSL version 3 */
  1214. config->ssl_version = CURL_SSLVERSION_SSLv3;
  1215. break;
  1216. case '4':
  1217. /* IPv4 */
  1218. config->ip_version = 4;
  1219. break;
  1220. case '6':
  1221. /* IPv6 */
  1222. config->ip_version = 6;
  1223. break;
  1224. case 'a':
  1225. /* This makes the FTP sessions use APPE instead of STOR */
  1226. config->ftp_append = toggle;
  1227. break;
  1228. case 'A':
  1229. /* This specifies the User-Agent name */
  1230. GetStr(&config->useragent, nextarg);
  1231. break;
  1232. case 'b':
  1233. switch(subletter) {
  1234. case 'a': /* --alt-svc */
  1235. if(curlinfo->features & CURL_VERSION_ALTSVC)
  1236. GetStr(&config->altsvc, nextarg);
  1237. else
  1238. return PARAM_LIBCURL_DOESNT_SUPPORT;
  1239. break;
  1240. default: /* --cookie string coming up: */
  1241. if(nextarg[0] == '@') {
  1242. nextarg++;
  1243. }
  1244. else if(strchr(nextarg, '=')) {
  1245. /* A cookie string must have a =-letter */
  1246. GetStr(&config->cookie, nextarg);
  1247. break;
  1248. }
  1249. /* We have a cookie file to read from! */
  1250. GetStr(&config->cookiefile, nextarg);
  1251. }
  1252. break;
  1253. case 'B':
  1254. /* use ASCII/text when transferring */
  1255. config->use_ascii = toggle;
  1256. break;
  1257. case 'c':
  1258. /* get the file name to dump all cookies in */
  1259. GetStr(&config->cookiejar, nextarg);
  1260. break;
  1261. case 'C':
  1262. /* This makes us continue an ftp transfer at given position */
  1263. if(strcmp(nextarg, "-")) {
  1264. err = str2offset(&config->resume_from, nextarg);
  1265. if(err)
  1266. return err;
  1267. config->resume_from_current = FALSE;
  1268. }
  1269. else {
  1270. config->resume_from_current = TRUE;
  1271. config->resume_from = 0;
  1272. }
  1273. config->use_resume = TRUE;
  1274. break;
  1275. case 'd':
  1276. /* postfield data */
  1277. {
  1278. char *postdata = NULL;
  1279. FILE *file;
  1280. size_t size = 0;
  1281. bool raw_mode = (subletter == 'r');
  1282. if(subletter == 'e') { /* --data-urlencode*/
  1283. /* [name]=[content], we encode the content part only
  1284. * [name]@[file name]
  1285. *
  1286. * Case 2: we first load the file using that name and then encode
  1287. * the content.
  1288. */
  1289. const char *p = strchr(nextarg, '=');
  1290. size_t nlen;
  1291. char is_file;
  1292. if(!p)
  1293. /* there was no '=' letter, check for a '@' instead */
  1294. p = strchr(nextarg, '@');
  1295. if(p) {
  1296. nlen = p - nextarg; /* length of the name part */
  1297. is_file = *p++; /* pass the separator */
  1298. }
  1299. else {
  1300. /* neither @ nor =, so no name and it isn't a file */
  1301. nlen = is_file = 0;
  1302. p = nextarg;
  1303. }
  1304. if('@' == is_file) {
  1305. /* a '@' letter, it means that a file name or - (stdin) follows */
  1306. if(!strcmp("-", p)) {
  1307. file = stdin;
  1308. set_binmode(stdin);
  1309. }
  1310. else {
  1311. file = fopen(p, "rb");
  1312. if(!file)
  1313. warnf(global,
  1314. "Couldn't read data from file \"%s\", this makes "
  1315. "an empty POST.\n", nextarg);
  1316. }
  1317. err = file2memory(&postdata, &size, file);
  1318. if(file && (file != stdin))
  1319. fclose(file);
  1320. if(err)
  1321. return err;
  1322. }
  1323. else {
  1324. GetStr(&postdata, p);
  1325. if(postdata)
  1326. size = strlen(postdata);
  1327. }
  1328. if(!postdata) {
  1329. /* no data from the file, point to a zero byte string to make this
  1330. get sent as a POST anyway */
  1331. postdata = strdup("");
  1332. if(!postdata)
  1333. return PARAM_NO_MEM;
  1334. size = 0;
  1335. }
  1336. else {
  1337. char *enc = curl_easy_escape(NULL, postdata, (int)size);
  1338. Curl_safefree(postdata); /* no matter if it worked or not */
  1339. if(enc) {
  1340. /* now make a string with the name from above and append the
  1341. encoded string */
  1342. size_t outlen = nlen + strlen(enc) + 2;
  1343. char *n = malloc(outlen);
  1344. if(!n) {
  1345. curl_free(enc);
  1346. return PARAM_NO_MEM;
  1347. }
  1348. if(nlen > 0) { /* only append '=' if we have a name */
  1349. msnprintf(n, outlen, "%.*s=%s", nlen, nextarg, enc);
  1350. size = outlen-1;
  1351. }
  1352. else {
  1353. strcpy(n, enc);
  1354. size = outlen-2; /* since no '=' was inserted */
  1355. }
  1356. curl_free(enc);
  1357. postdata = n;
  1358. }
  1359. else
  1360. return PARAM_NO_MEM;
  1361. }
  1362. }
  1363. else if('@' == *nextarg && !raw_mode) {
  1364. /* the data begins with a '@' letter, it means that a file name
  1365. or - (stdin) follows */
  1366. nextarg++; /* pass the @ */
  1367. if(!strcmp("-", nextarg)) {
  1368. file = stdin;
  1369. if(subletter == 'b') /* forced data-binary */
  1370. set_binmode(stdin);
  1371. }
  1372. else {
  1373. file = fopen(nextarg, "rb");
  1374. if(!file)
  1375. warnf(global, "Couldn't read data from file \"%s\", this makes "
  1376. "an empty POST.\n", nextarg);
  1377. }
  1378. if(subletter == 'b')
  1379. /* forced binary */
  1380. err = file2memory(&postdata, &size, file);
  1381. else {
  1382. err = file2string(&postdata, file);
  1383. if(postdata)
  1384. size = strlen(postdata);
  1385. }
  1386. if(file && (file != stdin))
  1387. fclose(file);
  1388. if(err)
  1389. return err;
  1390. if(!postdata) {
  1391. /* no data from the file, point to a zero byte string to make this
  1392. get sent as a POST anyway */
  1393. postdata = strdup("");
  1394. if(!postdata)
  1395. return PARAM_NO_MEM;
  1396. }
  1397. }
  1398. else {
  1399. GetStr(&postdata, nextarg);
  1400. if(postdata)
  1401. size = strlen(postdata);
  1402. }
  1403. #ifdef CURL_DOES_CONVERSIONS
  1404. if(subletter != 'b') {
  1405. /* NOT forced binary, convert to ASCII */
  1406. if(convert_to_network(postdata, strlen(postdata))) {
  1407. Curl_safefree(postdata);
  1408. return PARAM_NO_MEM;
  1409. }
  1410. }
  1411. #endif
  1412. if(config->postfields) {
  1413. /* we already have a string, we append this one with a separating
  1414. &-letter */
  1415. char *oldpost = config->postfields;
  1416. curl_off_t oldlen = config->postfieldsize;
  1417. curl_off_t newlen = oldlen + curlx_uztoso(size) + 2;
  1418. config->postfields = malloc((size_t)newlen);
  1419. if(!config->postfields) {
  1420. Curl_safefree(oldpost);
  1421. Curl_safefree(postdata);
  1422. return PARAM_NO_MEM;
  1423. }
  1424. memcpy(config->postfields, oldpost, (size_t)oldlen);
  1425. /* use byte value 0x26 for '&' to accommodate non-ASCII platforms */
  1426. config->postfields[oldlen] = '\x26';
  1427. memcpy(&config->postfields[oldlen + 1], postdata, size);
  1428. config->postfields[oldlen + 1 + size] = '\0';
  1429. Curl_safefree(oldpost);
  1430. Curl_safefree(postdata);
  1431. config->postfieldsize += size + 1;
  1432. }
  1433. else {
  1434. config->postfields = postdata;
  1435. config->postfieldsize = curlx_uztoso(size);
  1436. }
  1437. }
  1438. /*
  1439. We can't set the request type here, as this data might be used in
  1440. a simple GET if -G is used. Already or soon.
  1441. if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq)) {
  1442. Curl_safefree(postdata);
  1443. return PARAM_BAD_USE;
  1444. }
  1445. */
  1446. break;
  1447. case 'D':
  1448. /* dump-header to given file name */
  1449. GetStr(&config->headerfile, nextarg);
  1450. break;
  1451. case 'e':
  1452. {
  1453. char *ptr = strstr(nextarg, ";auto");
  1454. if(ptr) {
  1455. /* Automatic referer requested, this may be combined with a
  1456. set initial one */
  1457. config->autoreferer = TRUE;
  1458. *ptr = 0; /* null-terminate here */
  1459. }
  1460. else
  1461. config->autoreferer = FALSE;
  1462. GetStr(&config->referer, nextarg);
  1463. }
  1464. break;
  1465. case 'E':
  1466. switch(subletter) {
  1467. case '\0': /* certificate file */
  1468. GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
  1469. break;
  1470. case 'a': /* CA info PEM file */
  1471. GetStr(&config->cacert, nextarg);
  1472. break;
  1473. case 'b': /* cert file type */
  1474. GetStr(&config->cert_type, nextarg);
  1475. break;
  1476. case 'c': /* private key file */
  1477. GetStr(&config->key, nextarg);
  1478. break;
  1479. case 'd': /* private key file type */
  1480. GetStr(&config->key_type, nextarg);
  1481. break;
  1482. case 'e': /* private key passphrase */
  1483. GetStr(&config->key_passwd, nextarg);
  1484. cleanarg(nextarg);
  1485. break;
  1486. case 'f': /* crypto engine */
  1487. GetStr(&config->engine, nextarg);
  1488. if(config->engine && curl_strequal(config->engine, "list"))
  1489. return PARAM_ENGINES_REQUESTED;
  1490. break;
  1491. case 'g': /* CA cert directory */
  1492. GetStr(&config->capath, nextarg);
  1493. break;
  1494. case 'h': /* --pubkey public key file */
  1495. GetStr(&config->pubkey, nextarg);
  1496. break;
  1497. case 'i': /* --hostpubmd5 md5 of the host public key */
  1498. GetStr(&config->hostpubmd5, nextarg);
  1499. if(!config->hostpubmd5 || strlen(config->hostpubmd5) != 32)
  1500. return PARAM_BAD_USE;
  1501. break;
  1502. case 'j': /* CRL file */
  1503. GetStr(&config->crlfile, nextarg);
  1504. break;
  1505. case 'k': /* TLS username */
  1506. if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
  1507. GetStr(&config->tls_username, nextarg);
  1508. else
  1509. return PARAM_LIBCURL_DOESNT_SUPPORT;
  1510. break;
  1511. case 'l': /* TLS password */
  1512. if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
  1513. GetStr(&config->tls_password, nextarg);
  1514. else
  1515. return PARAM_LIBCURL_DOESNT_SUPPORT;
  1516. break;
  1517. case 'm': /* TLS authentication type */
  1518. if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
  1519. GetStr(&config->tls_authtype, nextarg);
  1520. if(!curl_strequal(config->tls_authtype, "SRP"))
  1521. return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
  1522. }
  1523. else
  1524. return PARAM_LIBCURL_DOESNT_SUPPORT;
  1525. break;
  1526. case 'n': /* no empty SSL fragments, --ssl-allow-beast */
  1527. if(curlinfo->features & CURL_VERSION_SSL)
  1528. config->ssl_allow_beast = toggle;
  1529. break;
  1530. case 'p': /* Pinned public key DER file */
  1531. GetStr(&config->pinnedpubkey, nextarg);
  1532. break;
  1533. case 'P': /* proxy pinned public key */
  1534. GetStr(&config->proxy_pinnedpubkey, nextarg);
  1535. break;
  1536. case 'q': /* --cert-status */
  1537. config->verifystatus = TRUE;
  1538. break;
  1539. case 'r': /* --false-start */
  1540. config->falsestart = TRUE;
  1541. break;
  1542. case 's': /* --ssl-no-revoke */
  1543. if(curlinfo->features & CURL_VERSION_SSL)
  1544. config->ssl_no_revoke = TRUE;
  1545. break;
  1546. case 'S': /* --ssl-revoke-best-effort */
  1547. if(curlinfo->features & CURL_VERSION_SSL)
  1548. config->ssl_revoke_best_effort = TRUE;
  1549. break;
  1550. case 't': /* --tcp-fastopen */
  1551. config->tcp_fastopen = TRUE;
  1552. break;
  1553. case 'u': /* TLS username for proxy */
  1554. if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
  1555. GetStr(&config->proxy_tls_username, nextarg);
  1556. else
  1557. return PARAM_LIBCURL_DOESNT_SUPPORT;
  1558. break;
  1559. case 'v': /* TLS password for proxy */
  1560. if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
  1561. GetStr(&config->proxy_tls_password, nextarg);
  1562. else
  1563. return PARAM_LIBCURL_DOESNT_SUPPORT;
  1564. break;
  1565. case 'w': /* TLS authentication type for proxy */
  1566. if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
  1567. GetStr(&config->proxy_tls_authtype, nextarg);
  1568. if(!curl_strequal(config->proxy_tls_authtype, "SRP"))
  1569. return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
  1570. }
  1571. else
  1572. return PARAM_LIBCURL_DOESNT_SUPPORT;
  1573. break;
  1574. case 'x': /* certificate file for proxy */
  1575. GetFileAndPassword(nextarg, &config->proxy_cert,
  1576. &config->proxy_key_passwd);
  1577. break;
  1578. case 'y': /* cert file type for proxy */
  1579. GetStr(&config->proxy_cert_type, nextarg);
  1580. break;
  1581. case 'z': /* private key file for proxy */
  1582. GetStr(&config->proxy_key, nextarg);
  1583. break;
  1584. case '0': /* private key file type for proxy */
  1585. GetStr(&config->proxy_key_type, nextarg);
  1586. break;
  1587. case '1': /* private key passphrase for proxy */
  1588. GetStr(&config->proxy_key_passwd, nextarg);
  1589. cleanarg(nextarg);
  1590. break;
  1591. case '2': /* ciphers for proxy */
  1592. GetStr(&config->proxy_cipher_list, nextarg);
  1593. break;
  1594. case '3': /* CRL file for proxy */
  1595. GetStr(&config->proxy_crlfile, nextarg);
  1596. break;
  1597. case '4': /* no empty SSL fragments for proxy */
  1598. if(curlinfo->features & CURL_VERSION_SSL)
  1599. config->proxy_ssl_allow_beast = toggle;
  1600. break;
  1601. case '5': /* --login-options */
  1602. GetStr(&config->login_options, nextarg);
  1603. break;
  1604. case '6': /* CA info PEM file for proxy */
  1605. GetStr(&config->proxy_cacert, nextarg);
  1606. break;
  1607. case '7': /* CA cert directory for proxy */
  1608. GetStr(&config->proxy_capath, nextarg);
  1609. break;
  1610. case '8': /* allow insecure SSL connects for proxy */
  1611. config->proxy_insecure_ok = toggle;
  1612. break;
  1613. case '9': /* --proxy-tlsv1 */
  1614. /* TLS version 1 for proxy */
  1615. config->proxy_ssl_version = CURL_SSLVERSION_TLSv1;
  1616. break;
  1617. case 'A':
  1618. /* --socks5-basic */
  1619. if(toggle)
  1620. config->socks5_auth |= CURLAUTH_BASIC;
  1621. else
  1622. config->socks5_auth &= ~CURLAUTH_BASIC;
  1623. break;
  1624. case 'B':
  1625. /* --socks5-gssapi */
  1626. if(toggle)
  1627. config->socks5_auth |= CURLAUTH_GSSAPI;
  1628. else
  1629. config->socks5_auth &= ~CURLAUTH_GSSAPI;
  1630. break;
  1631. case 'C':
  1632. GetStr(&config->etag_save_file, nextarg);
  1633. break;
  1634. case 'D':
  1635. GetStr(&config->etag_compare_file, nextarg);
  1636. break;
  1637. case 'E':
  1638. GetStr(&config->ssl_ec_curves, nextarg);
  1639. break;
  1640. default: /* unknown flag */
  1641. return PARAM_OPTION_UNKNOWN;
  1642. }
  1643. break;
  1644. case 'f':
  1645. switch(subletter) {
  1646. case 'a': /* --fail-early */
  1647. global->fail_early = toggle;
  1648. break;
  1649. case 'b': /* --styled-output */
  1650. global->styled_output = toggle;
  1651. break;
  1652. case 'c': /* --mail-rcpt-allowfails */
  1653. config->mail_rcpt_allowfails = toggle;
  1654. break;
  1655. default: /* --fail (hard on errors) */
  1656. config->failonerror = toggle;
  1657. }
  1658. break;
  1659. case 'F':
  1660. /* "form data" simulation, this is a little advanced so lets do our best
  1661. to sort this out slowly and carefully */
  1662. if(formparse(config,
  1663. nextarg,
  1664. &config->mimeroot,
  1665. &config->mimecurrent,
  1666. (subletter == 's')?TRUE:FALSE)) /* 's' is literal string */
  1667. return PARAM_BAD_USE;
  1668. if(SetHTTPrequest(config, HTTPREQ_MIMEPOST, &config->httpreq))
  1669. return PARAM_BAD_USE;
  1670. break;
  1671. case 'g': /* g disables URLglobbing */
  1672. config->globoff = toggle;
  1673. break;
  1674. case 'G': /* HTTP GET */
  1675. if(subletter == 'a') { /* --request-target */
  1676. GetStr(&config->request_target, nextarg);
  1677. }
  1678. else
  1679. config->use_httpget = TRUE;
  1680. break;
  1681. case 'h': /* h for help */
  1682. if(toggle) {
  1683. return PARAM_HELP_REQUESTED;
  1684. }
  1685. /* we now actually support --no-help too! */
  1686. break;
  1687. case 'H':
  1688. /* A custom header to append to a list */
  1689. if(nextarg[0] == '@') {
  1690. /* read many headers from a file or stdin */
  1691. char *string;
  1692. size_t len;
  1693. bool use_stdin = !strcmp(&nextarg[1], "-");
  1694. FILE *file = use_stdin?stdin:fopen(&nextarg[1], FOPEN_READTEXT);
  1695. if(!file)
  1696. warnf(global, "Failed to open %s!\n", &nextarg[1]);
  1697. else {
  1698. err = file2memory(&string, &len, file);
  1699. if(!err && string) {
  1700. /* Allow strtok() here since this isn't used threaded */
  1701. /* !checksrc! disable BANNEDFUNC 2 */
  1702. char *h = strtok(string, "\r\n");
  1703. while(h) {
  1704. if(subletter == 'p') /* --proxy-header */
  1705. err = add2list(&config->proxyheaders, h);
  1706. else
  1707. err = add2list(&config->headers, h);
  1708. if(err)
  1709. break;
  1710. h = strtok(NULL, "\r\n");
  1711. }
  1712. free(string);
  1713. }
  1714. if(!use_stdin)
  1715. fclose(file);
  1716. if(err)
  1717. return err;
  1718. }
  1719. }
  1720. else {
  1721. if(subletter == 'p') /* --proxy-header */
  1722. err = add2list(&config->proxyheaders, nextarg);
  1723. else
  1724. err = add2list(&config->headers, nextarg);
  1725. if(err)
  1726. return err;
  1727. }
  1728. break;
  1729. case 'i':
  1730. if(config->content_disposition) {
  1731. warnf(global,
  1732. "--include and --remote-header-name cannot be combined.\n");
  1733. return PARAM_BAD_USE;
  1734. }
  1735. config->show_headers = toggle; /* show the headers as well in the
  1736. general output stream */
  1737. break;
  1738. case 'j':
  1739. config->cookiesession = toggle;
  1740. break;
  1741. case 'I': /* --head */
  1742. config->no_body = toggle;
  1743. config->show_headers = toggle;
  1744. if(SetHTTPrequest(config,
  1745. (config->no_body)?HTTPREQ_HEAD:HTTPREQ_GET,
  1746. &config->httpreq))
  1747. return PARAM_BAD_USE;
  1748. break;
  1749. case 'J': /* --remote-header-name */
  1750. if(config->show_headers) {
  1751. warnf(global,
  1752. "--include and --remote-header-name cannot be combined.\n");
  1753. return PARAM_BAD_USE;
  1754. }
  1755. config->content_disposition = toggle;
  1756. break;
  1757. case 'k': /* allow insecure SSL connects */
  1758. config->insecure_ok = toggle;
  1759. break;
  1760. case 'K': /* parse config file */
  1761. if(parseconfig(nextarg, global))
  1762. warnf(global, "error trying read config from the '%s' file\n",
  1763. nextarg);
  1764. break;
  1765. case 'l':
  1766. config->dirlistonly = toggle; /* only list the names of the FTP dir */
  1767. break;
  1768. case 'L':
  1769. config->followlocation = toggle; /* Follow Location: HTTP headers */
  1770. switch(subletter) {
  1771. case 't':
  1772. /* Continue to send authentication (user+password) when following
  1773. * locations, even when hostname changed */
  1774. config->unrestricted_auth = toggle;
  1775. break;
  1776. }
  1777. break;
  1778. case 'm':
  1779. /* specified max time */
  1780. err = str2udouble(&config->timeout, nextarg, LONG_MAX/1000);
  1781. if(err)
  1782. return err;
  1783. break;
  1784. case 'M': /* M for manual, huge help */
  1785. if(toggle) { /* --no-manual shows no manual... */
  1786. #ifdef USE_MANUAL
  1787. return PARAM_MANUAL_REQUESTED;
  1788. #else
  1789. warnf(global,
  1790. "built-in manual was disabled at build-time!\n");
  1791. return PARAM_OPTION_UNKNOWN;
  1792. #endif
  1793. }
  1794. break;
  1795. case 'n':
  1796. switch(subletter) {
  1797. case 'o': /* use .netrc or URL */
  1798. config->netrc_opt = toggle;
  1799. break;
  1800. case 'e': /* netrc-file */
  1801. GetStr(&config->netrc_file, nextarg);
  1802. break;
  1803. default:
  1804. /* pick info from .netrc, if this is used for http, curl will
  1805. automatically enfore user+password with the request */
  1806. config->netrc = toggle;
  1807. break;
  1808. }
  1809. break;
  1810. case 'N':
  1811. /* disable the output I/O buffering. note that the option is called
  1812. --buffer but is mostly used in the negative form: --no-buffer */
  1813. if(longopt)
  1814. config->nobuffer = (!toggle)?TRUE:FALSE;
  1815. else
  1816. config->nobuffer = toggle;
  1817. break;
  1818. case 'O': /* --remote-name */
  1819. if(subletter == 'a') { /* --remote-name-all */
  1820. config->default_node_flags = toggle?GETOUT_USEREMOTE:0;
  1821. break;
  1822. }
  1823. else if(subletter == 'b') { /* --output-dir */
  1824. GetStr(&config->output_dir, nextarg);
  1825. break;
  1826. }
  1827. /* FALLTHROUGH */
  1828. case 'o': /* --output */
  1829. /* output file */
  1830. {
  1831. struct getout *url;
  1832. if(!config->url_out)
  1833. config->url_out = config->url_list;
  1834. if(config->url_out) {
  1835. /* there's a node here, if it already is filled-in continue to find
  1836. an "empty" node */
  1837. while(config->url_out && (config->url_out->flags & GETOUT_OUTFILE))
  1838. config->url_out = config->url_out->next;
  1839. }
  1840. /* now there might or might not be an available node to fill in! */
  1841. if(config->url_out)
  1842. /* existing node */
  1843. url = config->url_out;
  1844. else
  1845. /* there was no free node, create one! */
  1846. config->url_out = url = new_getout(config);
  1847. if(!url)
  1848. return PARAM_NO_MEM;
  1849. /* fill in the outfile */
  1850. if('o' == letter) {
  1851. GetStr(&url->outfile, nextarg);
  1852. url->flags &= ~GETOUT_USEREMOTE; /* switch off */
  1853. }
  1854. else {
  1855. url->outfile = NULL; /* leave it */
  1856. if(toggle)
  1857. url->flags |= GETOUT_USEREMOTE; /* switch on */
  1858. else
  1859. url->flags &= ~GETOUT_USEREMOTE; /* switch off */
  1860. }
  1861. url->flags |= GETOUT_OUTFILE;
  1862. }
  1863. break;
  1864. case 'P':
  1865. /* This makes the FTP sessions use PORT instead of PASV */
  1866. /* use <eth0> or <192.168.10.10> style addresses. Anything except
  1867. this will make us try to get the "default" address.
  1868. NOTE: this is a changed behaviour since the released 4.1!
  1869. */
  1870. GetStr(&config->ftpport, nextarg);
  1871. break;
  1872. case 'p':
  1873. /* proxy tunnel for non-http protocols */
  1874. config->proxytunnel = toggle;
  1875. break;
  1876. case 'q': /* if used first, already taken care of, we do it like
  1877. this so we don't cause an error! */
  1878. break;
  1879. case 'Q':
  1880. /* QUOTE command to send to FTP server */
  1881. switch(nextarg[0]) {
  1882. case '-':
  1883. /* prefixed with a dash makes it a POST TRANSFER one */
  1884. nextarg++;
  1885. err = add2list(&config->postquote, nextarg);
  1886. break;
  1887. case '+':
  1888. /* prefixed with a plus makes it a just-before-transfer one */
  1889. nextarg++;
  1890. err = add2list(&config->prequote, nextarg);
  1891. break;
  1892. default:
  1893. err = add2list(&config->quote, nextarg);
  1894. break;
  1895. }
  1896. if(err)
  1897. return err;
  1898. break;
  1899. case 'r':
  1900. /* Specifying a range WITHOUT A DASH will create an illegal HTTP range
  1901. (and won't actually be range by definition). The man page previously
  1902. claimed that to be a good way, why this code is added to work-around
  1903. it. */
  1904. if(ISDIGIT(*nextarg) && !strchr(nextarg, '-')) {
  1905. char buffer[32];
  1906. curl_off_t off;
  1907. if(curlx_strtoofft(nextarg, NULL, 10, &off)) {
  1908. warnf(global, "unsupported range point\n");
  1909. return PARAM_BAD_USE;
  1910. }
  1911. warnf(global,
  1912. "A specified range MUST include at least one dash (-). "
  1913. "Appending one for you!\n");
  1914. msnprintf(buffer, sizeof(buffer), "%" CURL_FORMAT_CURL_OFF_T "-", off);
  1915. Curl_safefree(config->range);
  1916. config->range = strdup(buffer);
  1917. if(!config->range)
  1918. return PARAM_NO_MEM;
  1919. }
  1920. {
  1921. /* byte range requested */
  1922. const char *tmp_range = nextarg;
  1923. while(*tmp_range != '\0') {
  1924. if(!ISDIGIT(*tmp_range) && *tmp_range != '-' && *tmp_range != ',') {
  1925. warnf(global, "Invalid character is found in given range. "
  1926. "A specified range MUST have only digits in "
  1927. "\'start\'-\'stop\'. The server's response to this "
  1928. "request is uncertain.\n");
  1929. break;
  1930. }
  1931. tmp_range++;
  1932. }
  1933. /* byte range requested */
  1934. GetStr(&config->range, nextarg);
  1935. }
  1936. break;
  1937. case 'R':
  1938. /* use remote file's time */
  1939. config->remote_time = toggle;
  1940. break;
  1941. case 's':
  1942. /* don't show progress meter, don't show errors : */
  1943. if(toggle)
  1944. global->mute = global->noprogress = TRUE;
  1945. else
  1946. global->mute = global->noprogress = FALSE;
  1947. if(global->showerror < 0)
  1948. /* if still on the default value, set showerror to the reverse of
  1949. toggle. This is to allow -S and -s to be used in an independent
  1950. order but still have the same effect. */
  1951. global->showerror = (!toggle)?TRUE:FALSE; /* toggle off */
  1952. break;
  1953. case 'S':
  1954. /* show errors */
  1955. global->showerror = toggle?1:0; /* toggle on if used with -s */
  1956. break;
  1957. case 't':
  1958. /* Telnet options */
  1959. err = add2list(&config->telnet_options, nextarg);
  1960. if(err)
  1961. return err;
  1962. break;
  1963. case 'T':
  1964. /* we are uploading */
  1965. {
  1966. struct getout *url;
  1967. if(!config->url_ul)
  1968. config->url_ul = config->url_list;
  1969. if(config->url_ul) {
  1970. /* there's a node here, if it already is filled-in continue to find
  1971. an "empty" node */
  1972. while(config->url_ul && (config->url_ul->flags & GETOUT_UPLOAD))
  1973. config->url_ul = config->url_ul->next;
  1974. }
  1975. /* now there might or might not be an available node to fill in! */
  1976. if(config->url_ul)
  1977. /* existing node */
  1978. url = config->url_ul;
  1979. else
  1980. /* there was no free node, create one! */
  1981. config->url_ul = url = new_getout(config);
  1982. if(!url)
  1983. return PARAM_NO_MEM;
  1984. url->flags |= GETOUT_UPLOAD; /* mark -T used */
  1985. if(!*nextarg)
  1986. url->flags |= GETOUT_NOUPLOAD;
  1987. else {
  1988. /* "-" equals stdin, but keep the string around for now */
  1989. GetStr(&url->infile, nextarg);
  1990. }
  1991. }
  1992. break;
  1993. case 'u':
  1994. /* user:password */
  1995. GetStr(&config->userpwd, nextarg);
  1996. cleanarg(nextarg);
  1997. break;
  1998. case 'U':
  1999. /* Proxy user:password */
  2000. GetStr(&config->proxyuserpwd, nextarg);
  2001. cleanarg(nextarg);
  2002. break;
  2003. case 'v':
  2004. if(toggle) {
  2005. /* the '%' thing here will cause the trace get sent to stderr */
  2006. Curl_safefree(global->trace_dump);
  2007. global->trace_dump = strdup("%");
  2008. if(!global->trace_dump)
  2009. return PARAM_NO_MEM;
  2010. if(global->tracetype && (global->tracetype != TRACE_PLAIN))
  2011. warnf(global,
  2012. "-v, --verbose overrides an earlier trace/verbose option\n");
  2013. global->tracetype = TRACE_PLAIN;
  2014. }
  2015. else
  2016. /* verbose is disabled here */
  2017. global->tracetype = TRACE_NONE;
  2018. break;
  2019. case 'V':
  2020. if(toggle) /* --no-version yields no output! */
  2021. return PARAM_VERSION_INFO_REQUESTED;
  2022. break;
  2023. case 'w':
  2024. /* get the output string */
  2025. if('@' == *nextarg) {
  2026. /* the data begins with a '@' letter, it means that a file name
  2027. or - (stdin) follows */
  2028. FILE *file;
  2029. const char *fname;
  2030. nextarg++; /* pass the @ */
  2031. if(!strcmp("-", nextarg)) {
  2032. fname = "<stdin>";
  2033. file = stdin;
  2034. }
  2035. else {
  2036. fname = nextarg;
  2037. file = fopen(nextarg, FOPEN_READTEXT);
  2038. }
  2039. Curl_safefree(config->writeout);
  2040. err = file2string(&config->writeout, file);
  2041. if(file && (file != stdin))
  2042. fclose(file);
  2043. if(err)
  2044. return err;
  2045. if(!config->writeout)
  2046. warnf(global, "Failed to read %s", fname);
  2047. }
  2048. else
  2049. GetStr(&config->writeout, nextarg);
  2050. break;
  2051. case 'x':
  2052. switch(subletter) {
  2053. case 'a': /* --preproxy */
  2054. GetStr(&config->preproxy, nextarg);
  2055. break;
  2056. default:
  2057. /* --proxy */
  2058. GetStr(&config->proxy, nextarg);
  2059. config->proxyver = CURLPROXY_HTTP;
  2060. break;
  2061. }
  2062. break;
  2063. case 'X':
  2064. /* set custom request */
  2065. GetStr(&config->customrequest, nextarg);
  2066. break;
  2067. case 'y':
  2068. /* low speed time */
  2069. err = str2unum(&config->low_speed_time, nextarg);
  2070. if(err)
  2071. return err;
  2072. if(!config->low_speed_limit)
  2073. config->low_speed_limit = 1;
  2074. break;
  2075. case 'Y':
  2076. /* low speed limit */
  2077. err = str2unum(&config->low_speed_limit, nextarg);
  2078. if(err)
  2079. return err;
  2080. if(!config->low_speed_time)
  2081. config->low_speed_time = 30;
  2082. break;
  2083. case 'Z':
  2084. switch(subletter) {
  2085. case '\0': /* --parallel */
  2086. global->parallel = toggle;
  2087. break;
  2088. case 'b': /* --parallel-max */
  2089. err = str2unum(&global->parallel_max, nextarg);
  2090. if(err)
  2091. return err;
  2092. if((global->parallel_max > MAX_PARALLEL) ||
  2093. (global->parallel_max < 1))
  2094. global->parallel_max = PARALLEL_DEFAULT;
  2095. break;
  2096. case 'c': /* --parallel-connect */
  2097. global->parallel_connect = toggle;
  2098. break;
  2099. }
  2100. break;
  2101. case 'z': /* time condition coming up */
  2102. switch(*nextarg) {
  2103. case '+':
  2104. nextarg++;
  2105. /* FALLTHROUGH */
  2106. default:
  2107. /* If-Modified-Since: (section 14.28 in RFC2068) */
  2108. config->timecond = CURL_TIMECOND_IFMODSINCE;
  2109. break;
  2110. case '-':
  2111. /* If-Unmodified-Since: (section 14.24 in RFC2068) */
  2112. config->timecond = CURL_TIMECOND_IFUNMODSINCE;
  2113. nextarg++;
  2114. break;
  2115. case '=':
  2116. /* Last-Modified: (section 14.29 in RFC2068) */
  2117. config->timecond = CURL_TIMECOND_LASTMOD;
  2118. nextarg++;
  2119. break;
  2120. }
  2121. now = time(NULL);
  2122. config->condtime = (curl_off_t)curl_getdate(nextarg, &now);
  2123. if(-1 == config->condtime) {
  2124. /* now let's see if it is a file name to get the time from instead! */
  2125. curl_off_t filetime = getfiletime(nextarg, config->global->errors);
  2126. if(filetime >= 0) {
  2127. /* pull the time out from the file */
  2128. config->condtime = filetime;
  2129. }
  2130. else {
  2131. /* failed, remove time condition */
  2132. config->timecond = CURL_TIMECOND_NONE;
  2133. warnf(global,
  2134. "Illegal date format for -z, --time-cond (and not "
  2135. "a file name). Disabling time condition. "
  2136. "See curl_getdate(3) for valid date syntax.\n");
  2137. }
  2138. }
  2139. break;
  2140. default: /* unknown flag */
  2141. return PARAM_OPTION_UNKNOWN;
  2142. }
  2143. hit = -1;
  2144. } while(!longopt && !singleopt && *++parse && !*usedarg);
  2145. return PARAM_OK;
  2146. }
  2147. ParameterError parse_args(struct GlobalConfig *global, int argc,
  2148. argv_item_t argv[])
  2149. {
  2150. int i;
  2151. bool stillflags;
  2152. char *orig_opt = NULL;
  2153. ParameterError result = PARAM_OK;
  2154. struct OperationConfig *config = global->first;
  2155. for(i = 1, stillflags = TRUE; i < argc && !result; i++) {
  2156. orig_opt = curlx_convert_tchar_to_UTF8(argv[i]);
  2157. if(stillflags && ('-' == orig_opt[0])) {
  2158. bool passarg;
  2159. if(!strcmp("--", orig_opt))
  2160. /* This indicates the end of the flags and thus enables the
  2161. following (URL) argument to start with -. */
  2162. stillflags = FALSE;
  2163. else {
  2164. char *nextarg = (i < (argc - 1))
  2165. ? curlx_convert_tchar_to_UTF8(argv[i + 1])
  2166. : NULL;
  2167. result = getparameter(orig_opt, nextarg, &passarg, global, config);
  2168. curlx_unicodefree(nextarg);
  2169. config = global->last;
  2170. if(result == PARAM_NEXT_OPERATION) {
  2171. /* Reset result as PARAM_NEXT_OPERATION is only used here and not
  2172. returned from this function */
  2173. result = PARAM_OK;
  2174. if(config->url_list && config->url_list->url) {
  2175. /* Allocate the next config */
  2176. config->next = malloc(sizeof(struct OperationConfig));
  2177. if(config->next) {
  2178. /* Initialise the newly created config */
  2179. config_init(config->next);
  2180. /* Set the global config pointer */
  2181. config->next->global = global;
  2182. /* Update the last config pointer */
  2183. global->last = config->next;
  2184. /* Move onto the new config */
  2185. config->next->prev = config;
  2186. config = config->next;
  2187. }
  2188. else
  2189. result = PARAM_NO_MEM;
  2190. }
  2191. }
  2192. else if(!result && passarg)
  2193. i++; /* we're supposed to skip this */
  2194. }
  2195. }
  2196. else {
  2197. bool used;
  2198. /* Just add the URL please */
  2199. result = getparameter("--url", orig_opt, &used, global,
  2200. config);
  2201. }
  2202. if(!result)
  2203. curlx_unicodefree(orig_opt);
  2204. }
  2205. if(result && result != PARAM_HELP_REQUESTED &&
  2206. result != PARAM_MANUAL_REQUESTED &&
  2207. result != PARAM_VERSION_INFO_REQUESTED &&
  2208. result != PARAM_ENGINES_REQUESTED) {
  2209. const char *reason = param2text(result);
  2210. if(orig_opt && strcmp(":", orig_opt))
  2211. helpf(global->errors, "option %s: %s\n", orig_opt, reason);
  2212. else
  2213. helpf(global->errors, "%s\n", reason);
  2214. }
  2215. curlx_unicodefree(orig_opt);
  2216. return result;
  2217. }