tool_getparam.c 94 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * SPDX-License-Identifier: curl
  22. *
  23. ***************************************************************************/
  24. #include "tool_setup.h"
  25. #include "strcase.h"
  26. #define ENABLE_CURLX_PRINTF
  27. /* use our own printf() functions */
  28. #include "curlx.h"
  29. #include "tool_binmode.h"
  30. #include "tool_cfgable.h"
  31. #include "tool_cb_prg.h"
  32. #include "tool_filetime.h"
  33. #include "tool_formparse.h"
  34. #include "tool_getparam.h"
  35. #include "tool_helpers.h"
  36. #include "tool_libinfo.h"
  37. #include "tool_msgs.h"
  38. #include "tool_paramhlp.h"
  39. #include "tool_parsecfg.h"
  40. #include "tool_main.h"
  41. #include "dynbuf.h"
  42. #include "tool_stderr.h"
  43. #include "var.h"
  44. #include "memdebug.h" /* keep this as LAST include */
  45. #ifdef MSDOS
  46. # define USE_WATT32
  47. #endif
  48. #define ALLOW_BLANK TRUE
  49. #define DENY_BLANK FALSE
  50. static ParameterError getstr(char **str, const char *val, bool allowblank)
  51. {
  52. if(*str) {
  53. free(*str);
  54. *str = NULL;
  55. }
  56. if(val) {
  57. if(!allowblank && !val[0])
  58. return PARAM_BLANK_STRING;
  59. *str = strdup(val);
  60. if(!*str)
  61. return PARAM_NO_MEM;
  62. }
  63. return PARAM_OK;
  64. }
  65. /* one enum for every command line option. The name is the verbatim long
  66. option name, but in uppercase with periods and minuses replaced with
  67. underscores using a "C_" prefix. */
  68. typedef enum {
  69. C_ABSTRACT_UNIX_SOCKET,
  70. C_ALPN,
  71. C_ALT_SVC,
  72. C_ANYAUTH,
  73. C_APPEND,
  74. C_AWS_SIGV4,
  75. C_BASIC,
  76. C_BUFFER,
  77. C_CA_NATIVE,
  78. C_CACERT,
  79. C_CAPATH,
  80. C_CERT,
  81. C_CERT_STATUS,
  82. C_CERT_TYPE,
  83. C_CIPHERS,
  84. C_CLOBBER,
  85. C_COMPRESSED,
  86. C_COMPRESSED_SSH,
  87. C_CONFIG,
  88. C_CONNECT_TIMEOUT,
  89. C_CONNECT_TO,
  90. C_CONTINUE_AT,
  91. C_COOKIE,
  92. C_COOKIE_JAR,
  93. C_CREATE_DIRS,
  94. C_CREATE_FILE_MODE,
  95. C_CRLF,
  96. C_CRLFILE,
  97. C_CURVES,
  98. C_DATA,
  99. C_DATA_ASCII,
  100. C_DATA_BINARY,
  101. C_DATA_RAW,
  102. C_DATA_URLENCODE,
  103. C_DELEGATION,
  104. C_DIGEST,
  105. C_DISABLE,
  106. C_DISABLE_EPRT,
  107. C_DISABLE_EPSV,
  108. C_DISALLOW_USERNAME_IN_URL,
  109. C_DNS_INTERFACE,
  110. C_DNS_IPV4_ADDR,
  111. C_DNS_IPV6_ADDR,
  112. C_DNS_SERVERS,
  113. C_DOH_CERT_STATUS,
  114. C_DOH_INSECURE,
  115. C_DOH_URL,
  116. C_DUMP_HEADER,
  117. C_ECH,
  118. C_EGD_FILE,
  119. C_ENGINE,
  120. C_EPRT,
  121. C_EPSV,
  122. C_ETAG_COMPARE,
  123. C_ETAG_SAVE,
  124. C_EXPECT100_TIMEOUT,
  125. C_FAIL,
  126. C_FAIL_EARLY,
  127. C_FAIL_WITH_BODY,
  128. C_FALSE_START,
  129. C_FORM,
  130. C_FORM_ESCAPE,
  131. C_FORM_STRING,
  132. C_FTP_ACCOUNT,
  133. C_FTP_ALTERNATIVE_TO_USER,
  134. C_FTP_CREATE_DIRS,
  135. C_FTP_METHOD,
  136. C_FTP_PASV,
  137. C_FTP_PORT,
  138. C_FTP_PRET,
  139. C_FTP_SKIP_PASV_IP,
  140. C_FTP_SSL,
  141. C_FTP_SSL_CCC,
  142. C_FTP_SSL_CCC_MODE,
  143. C_FTP_SSL_CONTROL,
  144. C_FTP_SSL_REQD,
  145. C_GET,
  146. C_GLOBOFF,
  147. C_HAPPY_EYEBALLS_TIMEOUT_MS,
  148. C_HAPROXY_CLIENTIP,
  149. C_HAPROXY_PROTOCOL,
  150. C_HEAD,
  151. C_HEADER,
  152. C_HELP,
  153. C_HOSTPUBMD5,
  154. C_HOSTPUBSHA256,
  155. C_HSTS,
  156. C_HTTP0_9,
  157. C_HTTP1_0,
  158. C_HTTP1_1,
  159. C_HTTP2,
  160. C_HTTP2_PRIOR_KNOWLEDGE,
  161. C_HTTP3,
  162. C_HTTP3_ONLY,
  163. C_IGNORE_CONTENT_LENGTH,
  164. C_INCLUDE,
  165. C_INSECURE,
  166. C_INTERFACE,
  167. C_IPFS_GATEWAY,
  168. C_IPV4,
  169. C_IPV6,
  170. C_JSON,
  171. C_JUNK_SESSION_COOKIES,
  172. C_KEEPALIVE,
  173. C_KEEPALIVE_TIME,
  174. C_KEY,
  175. C_KEY_TYPE,
  176. C_KRB,
  177. C_KRB4,
  178. C_LIBCURL,
  179. C_LIMIT_RATE,
  180. C_LIST_ONLY,
  181. C_LOCAL_PORT,
  182. C_LOCATION,
  183. C_LOCATION_TRUSTED,
  184. C_LOGIN_OPTIONS,
  185. C_MAIL_AUTH,
  186. C_MAIL_FROM,
  187. C_MAIL_RCPT,
  188. C_MAIL_RCPT_ALLOWFAILS,
  189. C_MANUAL,
  190. C_MAX_FILESIZE,
  191. C_MAX_REDIRS,
  192. C_MAX_TIME,
  193. C_METALINK,
  194. C_NEGOTIATE,
  195. C_NETRC,
  196. C_NETRC_FILE,
  197. C_NETRC_OPTIONAL,
  198. C_NEXT,
  199. C_NOPROXY,
  200. C_NPN,
  201. C_NTLM,
  202. C_NTLM_WB,
  203. C_OAUTH2_BEARER,
  204. C_OUTPUT,
  205. C_OUTPUT_DIR,
  206. C_PARALLEL,
  207. C_PARALLEL_IMMEDIATE,
  208. C_PARALLEL_MAX,
  209. C_PASS,
  210. C_PATH_AS_IS,
  211. C_PINNEDPUBKEY,
  212. C_POST301,
  213. C_POST302,
  214. C_POST303,
  215. C_PREPROXY,
  216. C_PROGRESS_BAR,
  217. C_PROGRESS_METER,
  218. C_PROTO,
  219. C_PROTO_DEFAULT,
  220. C_PROTO_REDIR,
  221. C_PROXY,
  222. C_PROXY_ANYAUTH,
  223. C_PROXY_BASIC,
  224. C_PROXY_CA_NATIVE,
  225. C_PROXY_CACERT,
  226. C_PROXY_CAPATH,
  227. C_PROXY_CERT,
  228. C_PROXY_CERT_TYPE,
  229. C_PROXY_CIPHERS,
  230. C_PROXY_CRLFILE,
  231. C_PROXY_DIGEST,
  232. C_PROXY_HEADER,
  233. C_PROXY_HTTP2,
  234. C_PROXY_INSECURE,
  235. C_PROXY_KEY,
  236. C_PROXY_KEY_TYPE,
  237. C_PROXY_NEGOTIATE,
  238. C_PROXY_NTLM,
  239. C_PROXY_PASS,
  240. C_PROXY_PINNEDPUBKEY,
  241. C_PROXY_SERVICE_NAME,
  242. C_PROXY_SSL_ALLOW_BEAST,
  243. C_PROXY_SSL_AUTO_CLIENT_CERT,
  244. C_PROXY_TLS13_CIPHERS,
  245. C_PROXY_TLSAUTHTYPE,
  246. C_PROXY_TLSPASSWORD,
  247. C_PROXY_TLSUSER,
  248. C_PROXY_TLSV1,
  249. C_PROXY_USER,
  250. C_PROXY1_0,
  251. C_PROXYTUNNEL,
  252. C_PUBKEY,
  253. C_QUOTE,
  254. C_RANDOM_FILE,
  255. C_RANGE,
  256. C_RATE,
  257. C_RAW,
  258. C_REFERER,
  259. C_REMOTE_HEADER_NAME,
  260. C_REMOTE_NAME,
  261. C_REMOTE_NAME_ALL,
  262. C_REMOTE_TIME,
  263. C_REMOVE_ON_ERROR,
  264. C_REQUEST,
  265. C_REQUEST_TARGET,
  266. C_RESOLVE,
  267. C_RETRY,
  268. C_RETRY_ALL_ERRORS,
  269. C_RETRY_CONNREFUSED,
  270. C_RETRY_DELAY,
  271. C_RETRY_MAX_TIME,
  272. C_SASL_AUTHZID,
  273. C_SASL_IR,
  274. C_SERVICE_NAME,
  275. C_SESSIONID,
  276. C_SHOW_ERROR,
  277. C_SILENT,
  278. C_SOCKS4,
  279. C_SOCKS4A,
  280. C_SOCKS5,
  281. C_SOCKS5_BASIC,
  282. C_SOCKS5_GSSAPI,
  283. C_SOCKS5_GSSAPI_NEC,
  284. C_SOCKS5_GSSAPI_SERVICE,
  285. C_SOCKS5_HOSTNAME,
  286. C_SPEED_LIMIT,
  287. C_SPEED_TIME,
  288. C_SSL,
  289. C_SSL_ALLOW_BEAST,
  290. C_SSL_AUTO_CLIENT_CERT,
  291. C_SSL_NO_REVOKE,
  292. C_SSL_REQD,
  293. C_SSL_REVOKE_BEST_EFFORT,
  294. C_SSLV2,
  295. C_SSLV3,
  296. C_STDERR,
  297. C_STYLED_OUTPUT,
  298. C_SUPPRESS_CONNECT_HEADERS,
  299. C_TCP_FASTOPEN,
  300. C_TCP_NODELAY,
  301. C_TELNET_OPTION,
  302. C_TEST_EVENT,
  303. C_TFTP_BLKSIZE,
  304. C_TFTP_NO_OPTIONS,
  305. C_TIME_COND,
  306. C_TLS_MAX,
  307. C_TLS13_CIPHERS,
  308. C_TLSAUTHTYPE,
  309. C_TLSPASSWORD,
  310. C_TLSUSER,
  311. C_TLSV1,
  312. C_TLSV1_0,
  313. C_TLSV1_1,
  314. C_TLSV1_2,
  315. C_TLSV1_3,
  316. C_TR_ENCODING,
  317. C_TRACE,
  318. C_TRACE_ASCII,
  319. C_TRACE_CONFIG,
  320. C_TRACE_IDS,
  321. C_TRACE_TIME,
  322. C_UNIX_SOCKET,
  323. C_UPLOAD_FILE,
  324. C_URL,
  325. C_URL_QUERY,
  326. C_USE_ASCII,
  327. C_USER,
  328. C_USER_AGENT,
  329. C_VARIABLE,
  330. C_VERBOSE,
  331. C_VERSION,
  332. C_WDEBUG,
  333. C_WRITE_OUT,
  334. C_XATTR
  335. } cmdline_t;
  336. struct LongShort {
  337. const char *lname; /* long name option */
  338. enum {
  339. ARG_NONE, /* stand-alone but not a boolean */
  340. ARG_BOOL, /* accepts a --no-[name] prefix */
  341. ARG_STRG, /* requires an argument */
  342. ARG_FILE /* requires an argument, usually a file name */
  343. } desc;
  344. char letter; /* short name option or ' ' */
  345. cmdline_t cmd;
  346. };
  347. /* this array MUST be alphasorted based on the 'lname' */
  348. static const struct LongShort aliases[]= {
  349. {"abstract-unix-socket", ARG_FILE, ' ', C_ABSTRACT_UNIX_SOCKET},
  350. {"alpn", ARG_BOOL, ' ', C_ALPN},
  351. {"alt-svc", ARG_STRG, ' ', C_ALT_SVC},
  352. {"anyauth", ARG_BOOL, ' ', C_ANYAUTH},
  353. {"append", ARG_BOOL, 'a', C_APPEND},
  354. {"aws-sigv4", ARG_STRG, ' ', C_AWS_SIGV4},
  355. {"basic", ARG_BOOL, ' ', C_BASIC},
  356. {"buffer", ARG_BOOL, 'N', C_BUFFER},
  357. {"ca-native", ARG_BOOL, ' ', C_CA_NATIVE},
  358. {"cacert", ARG_FILE, ' ', C_CACERT},
  359. {"capath", ARG_FILE, ' ', C_CAPATH},
  360. {"cert", ARG_FILE, 'E', C_CERT},
  361. {"cert-status", ARG_BOOL, ' ', C_CERT_STATUS},
  362. {"cert-type", ARG_STRG, ' ', C_CERT_TYPE},
  363. {"ciphers", ARG_STRG, ' ', C_CIPHERS},
  364. {"clobber", ARG_BOOL, ' ', C_CLOBBER},
  365. {"compressed", ARG_BOOL, ' ', C_COMPRESSED},
  366. {"compressed-ssh", ARG_BOOL, ' ', C_COMPRESSED_SSH},
  367. {"config", ARG_FILE, 'K', C_CONFIG},
  368. {"connect-timeout", ARG_STRG, ' ', C_CONNECT_TIMEOUT},
  369. {"connect-to", ARG_STRG, ' ', C_CONNECT_TO},
  370. {"continue-at", ARG_STRG, 'C', C_CONTINUE_AT},
  371. {"cookie", ARG_STRG, 'b', C_COOKIE},
  372. {"cookie-jar", ARG_STRG, 'c', C_COOKIE_JAR},
  373. {"create-dirs", ARG_BOOL, ' ', C_CREATE_DIRS},
  374. {"create-file-mode", ARG_STRG, ' ', C_CREATE_FILE_MODE},
  375. {"crlf", ARG_BOOL, ' ', C_CRLF},
  376. {"crlfile", ARG_FILE, ' ', C_CRLFILE},
  377. {"curves", ARG_STRG, ' ', C_CURVES},
  378. {"data", ARG_STRG, 'd', C_DATA},
  379. {"data-ascii", ARG_STRG, ' ', C_DATA_ASCII},
  380. {"data-binary", ARG_STRG, ' ', C_DATA_BINARY},
  381. {"data-raw", ARG_STRG, ' ', C_DATA_RAW},
  382. {"data-urlencode", ARG_STRG, ' ', C_DATA_URLENCODE},
  383. {"delegation", ARG_STRG, ' ', C_DELEGATION},
  384. {"digest", ARG_BOOL, ' ', C_DIGEST},
  385. {"disable", ARG_BOOL, 'q', C_DISABLE},
  386. {"disable-eprt", ARG_BOOL, ' ', C_DISABLE_EPRT},
  387. {"disable-epsv", ARG_BOOL, ' ', C_DISABLE_EPSV},
  388. {"disallow-username-in-url", ARG_BOOL, ' ', C_DISALLOW_USERNAME_IN_URL},
  389. {"dns-interface", ARG_STRG, ' ', C_DNS_INTERFACE},
  390. {"dns-ipv4-addr", ARG_STRG, ' ', C_DNS_IPV4_ADDR},
  391. {"dns-ipv6-addr", ARG_STRG, ' ', C_DNS_IPV6_ADDR},
  392. {"dns-servers", ARG_STRG, ' ', C_DNS_SERVERS},
  393. {"doh-cert-status", ARG_BOOL, ' ', C_DOH_CERT_STATUS},
  394. {"doh-insecure", ARG_BOOL, ' ', C_DOH_INSECURE},
  395. {"doh-url" , ARG_STRG, ' ', C_DOH_URL},
  396. {"dump-header", ARG_FILE, 'D', C_DUMP_HEADER},
  397. {"ech", ARG_STRG, ' ', C_ECH},
  398. {"egd-file", ARG_STRG, ' ', C_EGD_FILE},
  399. {"engine", ARG_STRG, ' ', C_ENGINE},
  400. {"eprt", ARG_BOOL, ' ', C_EPRT},
  401. {"epsv", ARG_BOOL, ' ', C_EPSV},
  402. {"etag-compare", ARG_FILE, ' ', C_ETAG_COMPARE},
  403. {"etag-save", ARG_FILE, ' ', C_ETAG_SAVE},
  404. {"expect100-timeout", ARG_STRG, ' ', C_EXPECT100_TIMEOUT},
  405. {"fail", ARG_BOOL, 'f', C_FAIL},
  406. {"fail-early", ARG_BOOL, ' ', C_FAIL_EARLY},
  407. {"fail-with-body", ARG_BOOL, ' ', C_FAIL_WITH_BODY},
  408. {"false-start", ARG_BOOL, ' ', C_FALSE_START},
  409. {"form", ARG_STRG, 'F', C_FORM},
  410. {"form-escape", ARG_BOOL, ' ', C_FORM_ESCAPE},
  411. {"form-string", ARG_STRG, ' ', C_FORM_STRING},
  412. {"ftp-account", ARG_STRG, ' ', C_FTP_ACCOUNT},
  413. {"ftp-alternative-to-user", ARG_STRG, ' ', C_FTP_ALTERNATIVE_TO_USER},
  414. {"ftp-create-dirs", ARG_BOOL, ' ', C_FTP_CREATE_DIRS},
  415. {"ftp-method", ARG_STRG, ' ', C_FTP_METHOD},
  416. {"ftp-pasv", ARG_BOOL, ' ', C_FTP_PASV},
  417. {"ftp-port", ARG_STRG, 'P', C_FTP_PORT},
  418. {"ftp-pret", ARG_BOOL, ' ', C_FTP_PRET},
  419. {"ftp-skip-pasv-ip", ARG_BOOL, ' ', C_FTP_SKIP_PASV_IP},
  420. {"ftp-ssl", ARG_BOOL, ' ', C_FTP_SSL},
  421. {"ftp-ssl-ccc", ARG_BOOL, ' ', C_FTP_SSL_CCC},
  422. {"ftp-ssl-ccc-mode", ARG_STRG, ' ', C_FTP_SSL_CCC_MODE},
  423. {"ftp-ssl-control", ARG_BOOL, ' ', C_FTP_SSL_CONTROL},
  424. {"ftp-ssl-reqd", ARG_BOOL, ' ', C_FTP_SSL_REQD},
  425. {"get", ARG_BOOL, 'G', C_GET},
  426. {"globoff", ARG_BOOL, 'g', C_GLOBOFF},
  427. {"happy-eyeballs-timeout-ms", ARG_STRG, ' ', C_HAPPY_EYEBALLS_TIMEOUT_MS},
  428. {"haproxy-clientip", ARG_STRG, ' ', C_HAPROXY_CLIENTIP},
  429. {"haproxy-protocol", ARG_BOOL, ' ', C_HAPROXY_PROTOCOL},
  430. {"head", ARG_BOOL, 'I', C_HEAD},
  431. {"header", ARG_STRG, 'H', C_HEADER},
  432. {"help", ARG_BOOL, 'h', C_HELP},
  433. {"hostpubmd5", ARG_STRG, ' ', C_HOSTPUBMD5},
  434. {"hostpubsha256", ARG_STRG, ' ', C_HOSTPUBSHA256},
  435. {"hsts", ARG_STRG, ' ', C_HSTS},
  436. {"http0.9", ARG_BOOL, ' ', C_HTTP0_9},
  437. {"http1.0", ARG_NONE, '0', C_HTTP1_0},
  438. {"http1.1", ARG_NONE, ' ', C_HTTP1_1},
  439. {"http2", ARG_NONE, ' ', C_HTTP2},
  440. {"http2-prior-knowledge", ARG_NONE, ' ', C_HTTP2_PRIOR_KNOWLEDGE},
  441. {"http3", ARG_NONE, ' ', C_HTTP3},
  442. {"http3-only", ARG_NONE, ' ', C_HTTP3_ONLY},
  443. {"ignore-content-length", ARG_BOOL, ' ', C_IGNORE_CONTENT_LENGTH},
  444. {"include", ARG_BOOL, 'i', C_INCLUDE},
  445. {"insecure", ARG_BOOL, 'k', C_INSECURE},
  446. {"interface", ARG_STRG, ' ', C_INTERFACE},
  447. {"ipfs-gateway", ARG_STRG, ' ', C_IPFS_GATEWAY},
  448. {"ipv4", ARG_NONE, '4', C_IPV4},
  449. {"ipv6", ARG_NONE, '6', C_IPV6},
  450. {"json", ARG_STRG, ' ', C_JSON},
  451. {"junk-session-cookies", ARG_BOOL, 'j', C_JUNK_SESSION_COOKIES},
  452. {"keepalive", ARG_BOOL, ' ', C_KEEPALIVE},
  453. {"keepalive-time", ARG_STRG, ' ', C_KEEPALIVE_TIME},
  454. {"key", ARG_FILE, ' ', C_KEY},
  455. {"key-type", ARG_STRG, ' ', C_KEY_TYPE},
  456. {"krb", ARG_STRG, ' ', C_KRB},
  457. {"krb4", ARG_STRG, ' ', C_KRB4},
  458. {"libcurl", ARG_STRG, ' ', C_LIBCURL},
  459. {"limit-rate", ARG_STRG, ' ', C_LIMIT_RATE},
  460. {"list-only", ARG_BOOL, 'l', C_LIST_ONLY},
  461. {"local-port", ARG_STRG, ' ', C_LOCAL_PORT},
  462. {"location", ARG_BOOL, 'L', C_LOCATION},
  463. {"location-trusted", ARG_BOOL, ' ', C_LOCATION_TRUSTED},
  464. {"login-options", ARG_STRG, ' ', C_LOGIN_OPTIONS},
  465. {"mail-auth", ARG_STRG, ' ', C_MAIL_AUTH},
  466. {"mail-from", ARG_STRG, ' ', C_MAIL_FROM},
  467. {"mail-rcpt", ARG_STRG, ' ', C_MAIL_RCPT},
  468. {"mail-rcpt-allowfails", ARG_BOOL, ' ', C_MAIL_RCPT_ALLOWFAILS},
  469. {"manual", ARG_BOOL, 'M', C_MANUAL},
  470. {"max-filesize", ARG_STRG, ' ', C_MAX_FILESIZE},
  471. {"max-redirs", ARG_STRG, ' ', C_MAX_REDIRS},
  472. {"max-time", ARG_STRG, 'm', C_MAX_TIME},
  473. {"metalink", ARG_BOOL, ' ', C_METALINK},
  474. {"negotiate", ARG_BOOL, ' ', C_NEGOTIATE},
  475. {"netrc", ARG_BOOL, 'n', C_NETRC},
  476. {"netrc-file", ARG_FILE, ' ', C_NETRC_FILE},
  477. {"netrc-optional", ARG_BOOL, ' ', C_NETRC_OPTIONAL},
  478. {"next", ARG_NONE, ':', C_NEXT},
  479. {"noproxy", ARG_STRG, ' ', C_NOPROXY},
  480. {"npn", ARG_BOOL, ' ', C_NPN},
  481. {"ntlm", ARG_BOOL, ' ', C_NTLM},
  482. {"ntlm-wb", ARG_BOOL, ' ', C_NTLM_WB},
  483. {"oauth2-bearer", ARG_STRG, ' ', C_OAUTH2_BEARER},
  484. {"output", ARG_FILE, 'o', C_OUTPUT},
  485. {"output-dir", ARG_STRG, ' ', C_OUTPUT_DIR},
  486. {"parallel", ARG_BOOL, 'Z', C_PARALLEL},
  487. {"parallel-immediate", ARG_BOOL, ' ', C_PARALLEL_IMMEDIATE},
  488. {"parallel-max", ARG_STRG, ' ', C_PARALLEL_MAX},
  489. {"pass", ARG_STRG, ' ', C_PASS},
  490. {"path-as-is", ARG_BOOL, ' ', C_PATH_AS_IS},
  491. {"pinnedpubkey", ARG_STRG, ' ', C_PINNEDPUBKEY},
  492. {"post301", ARG_BOOL, ' ', C_POST301},
  493. {"post302", ARG_BOOL, ' ', C_POST302},
  494. {"post303", ARG_BOOL, ' ', C_POST303},
  495. {"preproxy", ARG_STRG, ' ', C_PREPROXY},
  496. {"progress-bar", ARG_BOOL, '#', C_PROGRESS_BAR},
  497. {"progress-meter", ARG_BOOL, ' ', C_PROGRESS_METER},
  498. {"proto", ARG_STRG, ' ', C_PROTO},
  499. {"proto-default", ARG_STRG, ' ', C_PROTO_DEFAULT},
  500. {"proto-redir", ARG_STRG, ' ', C_PROTO_REDIR},
  501. {"proxy", ARG_STRG, 'x', C_PROXY},
  502. {"proxy-anyauth", ARG_BOOL, ' ', C_PROXY_ANYAUTH},
  503. {"proxy-basic", ARG_BOOL, ' ', C_PROXY_BASIC},
  504. {"proxy-ca-native", ARG_BOOL, ' ', C_PROXY_CA_NATIVE},
  505. {"proxy-cacert", ARG_FILE, ' ', C_PROXY_CACERT},
  506. {"proxy-capath", ARG_FILE, ' ', C_PROXY_CAPATH},
  507. {"proxy-cert", ARG_FILE, ' ', C_PROXY_CERT},
  508. {"proxy-cert-type", ARG_STRG, ' ', C_PROXY_CERT_TYPE},
  509. {"proxy-ciphers", ARG_STRG, ' ', C_PROXY_CIPHERS},
  510. {"proxy-crlfile", ARG_FILE, ' ', C_PROXY_CRLFILE},
  511. {"proxy-digest", ARG_BOOL, ' ', C_PROXY_DIGEST},
  512. {"proxy-header", ARG_STRG, ' ', C_PROXY_HEADER},
  513. {"proxy-http2", ARG_BOOL, ' ', C_PROXY_HTTP2},
  514. {"proxy-insecure", ARG_BOOL, ' ', C_PROXY_INSECURE},
  515. {"proxy-key", ARG_FILE, ' ', C_PROXY_KEY},
  516. {"proxy-key-type", ARG_STRG, ' ', C_PROXY_KEY_TYPE},
  517. {"proxy-negotiate", ARG_BOOL, ' ', C_PROXY_NEGOTIATE},
  518. {"proxy-ntlm", ARG_BOOL, ' ', C_PROXY_NTLM},
  519. {"proxy-pass", ARG_STRG, ' ', C_PROXY_PASS},
  520. {"proxy-pinnedpubkey", ARG_STRG, ' ', C_PROXY_PINNEDPUBKEY},
  521. {"proxy-service-name", ARG_STRG, ' ', C_PROXY_SERVICE_NAME},
  522. {"proxy-ssl-allow-beast", ARG_BOOL, ' ', C_PROXY_SSL_ALLOW_BEAST},
  523. {"proxy-ssl-auto-client-cert", ARG_BOOL, ' ', C_PROXY_SSL_AUTO_CLIENT_CERT},
  524. {"proxy-tls13-ciphers", ARG_STRG, ' ', C_PROXY_TLS13_CIPHERS},
  525. {"proxy-tlsauthtype", ARG_STRG, ' ', C_PROXY_TLSAUTHTYPE},
  526. {"proxy-tlspassword", ARG_STRG, ' ', C_PROXY_TLSPASSWORD},
  527. {"proxy-tlsuser", ARG_STRG, ' ', C_PROXY_TLSUSER},
  528. {"proxy-tlsv1", ARG_NONE, ' ', C_PROXY_TLSV1},
  529. {"proxy-user", ARG_STRG, 'U', C_PROXY_USER},
  530. {"proxy1.0", ARG_STRG, ' ', C_PROXY1_0},
  531. {"proxytunnel", ARG_BOOL, 'p', C_PROXYTUNNEL},
  532. {"pubkey", ARG_STRG, ' ', C_PUBKEY},
  533. {"quote", ARG_STRG, 'Q', C_QUOTE},
  534. {"random-file", ARG_FILE, ' ', C_RANDOM_FILE},
  535. {"range", ARG_STRG, 'r', C_RANGE},
  536. {"rate", ARG_STRG, ' ', C_RATE},
  537. {"raw", ARG_BOOL, ' ', C_RAW},
  538. {"referer", ARG_STRG, 'e', C_REFERER},
  539. {"remote-header-name", ARG_BOOL, 'J', C_REMOTE_HEADER_NAME},
  540. {"remote-name", ARG_BOOL, 'O', C_REMOTE_NAME},
  541. {"remote-name-all", ARG_BOOL, ' ', C_REMOTE_NAME_ALL},
  542. {"remote-time", ARG_BOOL, 'R', C_REMOTE_TIME},
  543. {"remove-on-error", ARG_BOOL, ' ', C_REMOVE_ON_ERROR},
  544. {"request", ARG_STRG, 'X', C_REQUEST},
  545. {"request-target", ARG_STRG, ' ', C_REQUEST_TARGET},
  546. {"resolve", ARG_STRG, ' ', C_RESOLVE},
  547. {"retry", ARG_STRG, ' ', C_RETRY},
  548. {"retry-all-errors", ARG_BOOL, ' ', C_RETRY_ALL_ERRORS},
  549. {"retry-connrefused", ARG_BOOL, ' ', C_RETRY_CONNREFUSED},
  550. {"retry-delay", ARG_STRG, ' ', C_RETRY_DELAY},
  551. {"retry-max-time", ARG_STRG, ' ', C_RETRY_MAX_TIME},
  552. {"sasl-authzid", ARG_STRG, ' ', C_SASL_AUTHZID},
  553. {"sasl-ir", ARG_BOOL, ' ', C_SASL_IR},
  554. {"service-name", ARG_STRG, ' ', C_SERVICE_NAME},
  555. {"sessionid", ARG_BOOL, ' ', C_SESSIONID},
  556. {"show-error", ARG_BOOL, 'S', C_SHOW_ERROR},
  557. {"silent", ARG_BOOL, 's', C_SILENT},
  558. {"socks4", ARG_STRG, ' ', C_SOCKS4},
  559. {"socks4a", ARG_STRG, ' ', C_SOCKS4A},
  560. {"socks5", ARG_STRG, ' ', C_SOCKS5},
  561. {"socks5-basic", ARG_BOOL, ' ', C_SOCKS5_BASIC},
  562. {"socks5-gssapi", ARG_BOOL, ' ', C_SOCKS5_GSSAPI},
  563. {"socks5-gssapi-nec", ARG_BOOL, ' ', C_SOCKS5_GSSAPI_NEC},
  564. {"socks5-gssapi-service", ARG_STRG, ' ', C_SOCKS5_GSSAPI_SERVICE},
  565. {"socks5-hostname", ARG_STRG, ' ', C_SOCKS5_HOSTNAME},
  566. {"speed-limit", ARG_STRG, 'Y', C_SPEED_LIMIT},
  567. {"speed-time", ARG_STRG, 'y', C_SPEED_TIME},
  568. {"ssl", ARG_BOOL, ' ', C_SSL},
  569. {"ssl-allow-beast", ARG_BOOL, ' ', C_SSL_ALLOW_BEAST},
  570. {"ssl-auto-client-cert", ARG_BOOL, ' ', C_SSL_AUTO_CLIENT_CERT},
  571. {"ssl-no-revoke", ARG_BOOL, ' ', C_SSL_NO_REVOKE},
  572. {"ssl-reqd", ARG_BOOL, ' ', C_SSL_REQD},
  573. {"ssl-revoke-best-effort", ARG_BOOL, ' ', C_SSL_REVOKE_BEST_EFFORT},
  574. {"sslv2", ARG_NONE, '2', C_SSLV2},
  575. {"sslv3", ARG_NONE, '3', C_SSLV3},
  576. {"stderr", ARG_FILE, ' ', C_STDERR},
  577. {"styled-output", ARG_BOOL, ' ', C_STYLED_OUTPUT},
  578. {"suppress-connect-headers", ARG_BOOL, ' ', C_SUPPRESS_CONNECT_HEADERS},
  579. {"tcp-fastopen", ARG_BOOL, ' ', C_TCP_FASTOPEN},
  580. {"tcp-nodelay", ARG_BOOL, ' ', C_TCP_NODELAY},
  581. {"telnet-option", ARG_STRG, 't', C_TELNET_OPTION},
  582. {"test-event", ARG_BOOL, ' ', C_TEST_EVENT},
  583. {"tftp-blksize", ARG_STRG, ' ', C_TFTP_BLKSIZE},
  584. {"tftp-no-options", ARG_BOOL, ' ', C_TFTP_NO_OPTIONS},
  585. {"time-cond", ARG_STRG, 'z', C_TIME_COND},
  586. {"tls-max", ARG_STRG, ' ', C_TLS_MAX},
  587. {"tls13-ciphers", ARG_STRG, ' ', C_TLS13_CIPHERS},
  588. {"tlsauthtype", ARG_STRG, ' ', C_TLSAUTHTYPE},
  589. {"tlspassword", ARG_STRG, ' ', C_TLSPASSWORD},
  590. {"tlsuser", ARG_STRG, ' ', C_TLSUSER},
  591. {"tlsv1", ARG_NONE, '1', C_TLSV1},
  592. {"tlsv1.0", ARG_NONE, ' ', C_TLSV1_0},
  593. {"tlsv1.1", ARG_NONE, ' ', C_TLSV1_1},
  594. {"tlsv1.2", ARG_NONE, ' ', C_TLSV1_2},
  595. {"tlsv1.3", ARG_NONE, ' ', C_TLSV1_3},
  596. {"tr-encoding", ARG_BOOL, ' ', C_TR_ENCODING},
  597. {"trace", ARG_FILE, ' ', C_TRACE},
  598. {"trace-ascii", ARG_FILE, ' ', C_TRACE_ASCII},
  599. {"trace-config", ARG_STRG, ' ', C_TRACE_CONFIG},
  600. {"trace-ids", ARG_BOOL, ' ', C_TRACE_IDS},
  601. {"trace-time", ARG_BOOL, ' ', C_TRACE_TIME},
  602. {"unix-socket", ARG_FILE, ' ', C_UNIX_SOCKET},
  603. {"upload-file", ARG_FILE, 'T', C_UPLOAD_FILE},
  604. {"url", ARG_STRG, ' ', C_URL},
  605. {"url-query", ARG_STRG, ' ', C_URL_QUERY},
  606. {"use-ascii", ARG_BOOL, 'B', C_USE_ASCII},
  607. {"user", ARG_STRG, 'u', C_USER},
  608. {"user-agent", ARG_STRG, 'A', C_USER_AGENT},
  609. {"variable", ARG_STRG, ' ', C_VARIABLE},
  610. {"verbose", ARG_BOOL, 'v', C_VERBOSE},
  611. {"version", ARG_BOOL, 'V', C_VERSION},
  612. #ifdef USE_WATT32
  613. {"wdebug", ARG_BOOL, ' ', C_WDEBUG},
  614. #endif
  615. {"write-out", ARG_STRG, 'w', C_WRITE_OUT},
  616. {"xattr", ARG_BOOL, ' ', C_XATTR},
  617. };
  618. /* Split the argument of -E to 'certname' and 'passphrase' separated by colon.
  619. * We allow ':' and '\' to be escaped by '\' so that we can use certificate
  620. * nicknames containing ':'. See <https://sourceforge.net/p/curl/bugs/1196/>
  621. * for details. */
  622. #ifndef UNITTESTS
  623. static
  624. #endif
  625. void parse_cert_parameter(const char *cert_parameter,
  626. char **certname,
  627. char **passphrase)
  628. {
  629. size_t param_length = strlen(cert_parameter);
  630. size_t span;
  631. const char *param_place = NULL;
  632. char *certname_place = NULL;
  633. *certname = NULL;
  634. *passphrase = NULL;
  635. /* most trivial assumption: cert_parameter is empty */
  636. if(param_length == 0)
  637. return;
  638. /* next less trivial: cert_parameter starts 'pkcs11:' and thus
  639. * looks like a RFC7512 PKCS#11 URI which can be used as-is.
  640. * Also if cert_parameter contains no colon nor backslash, this
  641. * means no passphrase was given and no characters escaped */
  642. if(curl_strnequal(cert_parameter, "pkcs11:", 7) ||
  643. !strpbrk(cert_parameter, ":\\")) {
  644. *certname = strdup(cert_parameter);
  645. return;
  646. }
  647. /* deal with escaped chars; find unescaped colon if it exists */
  648. certname_place = malloc(param_length + 1);
  649. if(!certname_place)
  650. return;
  651. *certname = certname_place;
  652. param_place = cert_parameter;
  653. while(*param_place) {
  654. span = strcspn(param_place, ":\\");
  655. strncpy(certname_place, param_place, span);
  656. param_place += span;
  657. certname_place += span;
  658. /* we just ate all the non-special chars. now we're on either a special
  659. * char or the end of the string. */
  660. switch(*param_place) {
  661. case '\0':
  662. break;
  663. case '\\':
  664. param_place++;
  665. switch(*param_place) {
  666. case '\0':
  667. *certname_place++ = '\\';
  668. break;
  669. case '\\':
  670. *certname_place++ = '\\';
  671. param_place++;
  672. break;
  673. case ':':
  674. *certname_place++ = ':';
  675. param_place++;
  676. break;
  677. default:
  678. *certname_place++ = '\\';
  679. *certname_place++ = *param_place;
  680. param_place++;
  681. break;
  682. }
  683. break;
  684. case ':':
  685. /* Since we live in a world of weirdness and confusion, the win32
  686. dudes can use : when using drive letters and thus c:\file:password
  687. needs to work. In order not to break compatibility, we still use : as
  688. separator, but we try to detect when it is used for a file name! On
  689. windows. */
  690. #ifdef _WIN32
  691. if((param_place == &cert_parameter[1]) &&
  692. (cert_parameter[2] == '\\' || cert_parameter[2] == '/') &&
  693. (ISALPHA(cert_parameter[0])) ) {
  694. /* colon in the second column, followed by a backslash, and the
  695. first character is an alphabetic letter:
  696. this is a drive letter colon */
  697. *certname_place++ = ':';
  698. param_place++;
  699. break;
  700. }
  701. #endif
  702. /* escaped colons and Windows drive letter colons were handled
  703. * above; if we're still here, this is a separating colon */
  704. param_place++;
  705. if(*param_place) {
  706. *passphrase = strdup(param_place);
  707. }
  708. goto done;
  709. }
  710. }
  711. done:
  712. *certname_place = '\0';
  713. }
  714. /* Replace (in-place) '%20' by '+' according to RFC1866 */
  715. static size_t replace_url_encoded_space_by_plus(char *url)
  716. {
  717. size_t orig_len = strlen(url);
  718. size_t orig_index = 0;
  719. size_t new_index = 0;
  720. while(orig_index < orig_len) {
  721. if((url[orig_index] == '%') &&
  722. (url[orig_index + 1] == '2') &&
  723. (url[orig_index + 2] == '0')) {
  724. url[new_index] = '+';
  725. orig_index += 3;
  726. }
  727. else{
  728. if(new_index != orig_index) {
  729. url[new_index] = url[orig_index];
  730. }
  731. orig_index++;
  732. }
  733. new_index++;
  734. }
  735. url[new_index] = 0; /* terminate string */
  736. return new_index; /* new size */
  737. }
  738. static void
  739. GetFileAndPassword(char *nextarg, char **file, char **password)
  740. {
  741. char *certname, *passphrase;
  742. if(nextarg) {
  743. parse_cert_parameter(nextarg, &certname, &passphrase);
  744. Curl_safefree(*file);
  745. *file = certname;
  746. if(passphrase) {
  747. Curl_safefree(*password);
  748. *password = passphrase;
  749. }
  750. }
  751. }
  752. /* Get a size parameter for '--limit-rate' or '--max-filesize'.
  753. * We support a 'G', 'M' or 'K' suffix too.
  754. */
  755. static ParameterError GetSizeParameter(struct GlobalConfig *global,
  756. const char *arg,
  757. const char *which,
  758. curl_off_t *value_out)
  759. {
  760. char *unit;
  761. curl_off_t value;
  762. if(curlx_strtoofft(arg, &unit, 10, &value)) {
  763. warnf(global, "invalid number specified for %s", which);
  764. return PARAM_BAD_USE;
  765. }
  766. if(!*unit)
  767. unit = (char *)"b";
  768. else if(strlen(unit) > 1)
  769. unit = (char *)"w"; /* unsupported */
  770. switch(*unit) {
  771. case 'G':
  772. case 'g':
  773. if(value > (CURL_OFF_T_MAX / (1024*1024*1024)))
  774. return PARAM_NUMBER_TOO_LARGE;
  775. value *= 1024*1024*1024;
  776. break;
  777. case 'M':
  778. case 'm':
  779. if(value > (CURL_OFF_T_MAX / (1024*1024)))
  780. return PARAM_NUMBER_TOO_LARGE;
  781. value *= 1024*1024;
  782. break;
  783. case 'K':
  784. case 'k':
  785. if(value > (CURL_OFF_T_MAX / 1024))
  786. return PARAM_NUMBER_TOO_LARGE;
  787. value *= 1024;
  788. break;
  789. case 'b':
  790. case 'B':
  791. /* for plain bytes, leave as-is */
  792. break;
  793. default:
  794. warnf(global, "unsupported %s unit. Use G, M, K or B", which);
  795. return PARAM_BAD_USE;
  796. }
  797. *value_out = value;
  798. return PARAM_OK;
  799. }
  800. #ifdef HAVE_WRITABLE_ARGV
  801. static void cleanarg(argv_item_t str)
  802. {
  803. /* now that getstr has copied the contents of nextarg, wipe the next
  804. * argument out so that the username:password isn't displayed in the
  805. * system process list */
  806. if(str) {
  807. size_t len = strlen(str);
  808. memset(str, ' ', len);
  809. }
  810. }
  811. #else
  812. #define cleanarg(x)
  813. #endif
  814. /* --data-urlencode */
  815. static ParameterError data_urlencode(struct GlobalConfig *global,
  816. char *nextarg,
  817. char **postp,
  818. size_t *lenp)
  819. {
  820. /* [name]=[content], we encode the content part only
  821. * [name]@[file name]
  822. *
  823. * Case 2: we first load the file using that name and then encode
  824. * the content.
  825. */
  826. ParameterError err;
  827. const char *p = strchr(nextarg, '=');
  828. size_t nlen;
  829. char is_file;
  830. char *postdata = NULL;
  831. size_t size = 0;
  832. if(!p)
  833. /* there was no '=' letter, check for a '@' instead */
  834. p = strchr(nextarg, '@');
  835. if(p) {
  836. nlen = p - nextarg; /* length of the name part */
  837. is_file = *p++; /* pass the separator */
  838. }
  839. else {
  840. /* neither @ nor =, so no name and it isn't a file */
  841. nlen = is_file = 0;
  842. p = nextarg;
  843. }
  844. if('@' == is_file) {
  845. FILE *file;
  846. /* a '@' letter, it means that a file name or - (stdin) follows */
  847. if(!strcmp("-", p)) {
  848. file = stdin;
  849. set_binmode(stdin);
  850. }
  851. else {
  852. file = fopen(p, "rb");
  853. if(!file) {
  854. errorf(global, "Failed to open %s", p);
  855. return PARAM_READ_ERROR;
  856. }
  857. }
  858. err = file2memory(&postdata, &size, file);
  859. if(file && (file != stdin))
  860. fclose(file);
  861. if(err)
  862. return err;
  863. }
  864. else {
  865. err = getstr(&postdata, p, ALLOW_BLANK);
  866. if(err)
  867. goto error;
  868. if(postdata)
  869. size = strlen(postdata);
  870. }
  871. if(!postdata) {
  872. /* no data from the file, point to a zero byte string to make this
  873. get sent as a POST anyway */
  874. postdata = strdup("");
  875. if(!postdata)
  876. return PARAM_NO_MEM;
  877. size = 0;
  878. }
  879. else {
  880. char *enc = curl_easy_escape(NULL, postdata, (int)size);
  881. Curl_safefree(postdata); /* no matter if it worked or not */
  882. if(enc) {
  883. char *n;
  884. replace_url_encoded_space_by_plus(enc);
  885. if(nlen > 0) { /* only append '=' if we have a name */
  886. n = aprintf("%.*s=%s", (int)nlen, nextarg, enc);
  887. curl_free(enc);
  888. if(!n)
  889. return PARAM_NO_MEM;
  890. }
  891. else
  892. n = enc;
  893. size = strlen(n);
  894. postdata = n;
  895. }
  896. else
  897. return PARAM_NO_MEM;
  898. }
  899. *postp = postdata;
  900. *lenp = size;
  901. return PARAM_OK;
  902. error:
  903. return err;
  904. }
  905. static void sethttpver(struct GlobalConfig *global,
  906. struct OperationConfig *config,
  907. long httpversion)
  908. {
  909. if(config->httpversion &&
  910. (config->httpversion != httpversion))
  911. warnf(global, "Overrides previous HTTP version option");
  912. config->httpversion = httpversion;
  913. }
  914. static CURLcode set_trace_config(struct GlobalConfig *global,
  915. const char *config)
  916. {
  917. CURLcode result = CURLE_OK;
  918. char *token, *tmp, *name;
  919. bool toggle;
  920. tmp = strdup(config);
  921. if(!tmp)
  922. return CURLE_OUT_OF_MEMORY;
  923. /* Allow strtok() here since this isn't used threaded */
  924. /* !checksrc! disable BANNEDFUNC 2 */
  925. token = strtok(tmp, ", ");
  926. while(token) {
  927. switch(*token) {
  928. case '-':
  929. toggle = FALSE;
  930. name = token + 1;
  931. break;
  932. case '+':
  933. toggle = TRUE;
  934. name = token + 1;
  935. break;
  936. default:
  937. toggle = TRUE;
  938. name = token;
  939. break;
  940. }
  941. if(strcasecompare(name, "all")) {
  942. global->traceids = toggle;
  943. global->tracetime = toggle;
  944. result = curl_global_trace(token);
  945. if(result)
  946. goto out;
  947. }
  948. else if(strcasecompare(name, "ids")) {
  949. global->traceids = toggle;
  950. }
  951. else if(strcasecompare(name, "time")) {
  952. global->tracetime = toggle;
  953. }
  954. else {
  955. result = curl_global_trace(token);
  956. if(result)
  957. goto out;
  958. }
  959. token = strtok(NULL, ", ");
  960. }
  961. out:
  962. free(tmp);
  963. return result;
  964. }
  965. static int findarg(const void *a, const void *b)
  966. {
  967. const struct LongShort *aa = a;
  968. const struct LongShort *bb = b;
  969. return strcmp(aa->lname, bb->lname);
  970. }
  971. static const struct LongShort *single(char letter)
  972. {
  973. static const struct LongShort *singles[128 - ' ']; /* ASCII => pointer */
  974. static bool singles_done = FALSE;
  975. if((letter >= 127) || (letter <= ' '))
  976. return NULL;
  977. if(!singles_done) {
  978. unsigned int j;
  979. for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
  980. if(aliases[j].letter != ' ') {
  981. unsigned char l = aliases[j].letter;
  982. singles[l - ' '] = &aliases[j];
  983. }
  984. }
  985. singles_done = TRUE;
  986. }
  987. return singles[letter - ' '];
  988. }
  989. #define MAX_QUERY_LEN 100000 /* larger is not likely to ever work */
  990. static ParameterError url_query(char *nextarg,
  991. struct GlobalConfig *global,
  992. struct OperationConfig *config)
  993. {
  994. size_t size = 0;
  995. ParameterError err = PARAM_OK;
  996. char *query;
  997. struct curlx_dynbuf dyn;
  998. curlx_dyn_init(&dyn, MAX_QUERY_LEN);
  999. if(*nextarg == '+') {
  1000. /* use without encoding */
  1001. query = strdup(&nextarg[1]);
  1002. if(!query)
  1003. err = PARAM_NO_MEM;
  1004. }
  1005. else
  1006. err = data_urlencode(global, nextarg, &query, &size);
  1007. if(!err) {
  1008. if(config->query) {
  1009. CURLcode result = curlx_dyn_addf(&dyn, "%s&%s", config->query, query);
  1010. free(query);
  1011. if(result)
  1012. err = PARAM_NO_MEM;
  1013. else {
  1014. free(config->query);
  1015. config->query = curlx_dyn_ptr(&dyn);
  1016. }
  1017. }
  1018. else
  1019. config->query = query;
  1020. }
  1021. return err;
  1022. }
  1023. static ParameterError set_data(cmdline_t cmd,
  1024. char *nextarg,
  1025. struct GlobalConfig *global,
  1026. struct OperationConfig *config)
  1027. {
  1028. char *postdata = NULL;
  1029. FILE *file;
  1030. size_t size = 0;
  1031. ParameterError err = PARAM_OK;
  1032. if(cmd == C_DATA_URLENCODE) { /* --data-urlencode */
  1033. err = data_urlencode(global, nextarg, &postdata, &size);
  1034. if(err)
  1035. return err;
  1036. }
  1037. else if('@' == *nextarg && (cmd != C_DATA_RAW)) {
  1038. /* the data begins with a '@' letter, it means that a file name
  1039. or - (stdin) follows */
  1040. nextarg++; /* pass the @ */
  1041. if(!strcmp("-", nextarg)) {
  1042. file = stdin;
  1043. if(cmd == C_DATA_BINARY) /* forced data-binary */
  1044. set_binmode(stdin);
  1045. }
  1046. else {
  1047. file = fopen(nextarg, "rb");
  1048. if(!file) {
  1049. errorf(global, "Failed to open %s", nextarg);
  1050. return PARAM_READ_ERROR;
  1051. }
  1052. }
  1053. if((cmd == C_DATA_BINARY) || /* --data-binary */
  1054. (cmd == C_JSON) /* --json */)
  1055. /* forced binary */
  1056. err = file2memory(&postdata, &size, file);
  1057. else {
  1058. err = file2string(&postdata, file);
  1059. if(postdata)
  1060. size = strlen(postdata);
  1061. }
  1062. if(file && (file != stdin))
  1063. fclose(file);
  1064. if(err)
  1065. return err;
  1066. if(!postdata) {
  1067. /* no data from the file, point to a zero byte string to make this
  1068. get sent as a POST anyway */
  1069. postdata = strdup("");
  1070. if(!postdata)
  1071. return PARAM_NO_MEM;
  1072. }
  1073. }
  1074. else {
  1075. err = getstr(&postdata, nextarg, ALLOW_BLANK);
  1076. if(err)
  1077. return err;
  1078. if(postdata)
  1079. size = strlen(postdata);
  1080. }
  1081. if(cmd == C_JSON)
  1082. config->jsoned = TRUE;
  1083. if(curlx_dyn_len(&config->postdata)) {
  1084. /* skip separator append for --json */
  1085. if(!err && (cmd != C_JSON) &&
  1086. curlx_dyn_addn(&config->postdata, "&", 1))
  1087. err = PARAM_NO_MEM;
  1088. }
  1089. if(!err && curlx_dyn_addn(&config->postdata, postdata, size))
  1090. err = PARAM_NO_MEM;
  1091. Curl_safefree(postdata);
  1092. config->postfields = curlx_dyn_ptr(&config->postdata);
  1093. return err;
  1094. }
  1095. static ParameterError set_rate(struct GlobalConfig *global,
  1096. char *nextarg)
  1097. {
  1098. /* --rate */
  1099. /* support a few different suffixes, extract the suffix first, then
  1100. get the number and convert to per hour.
  1101. /s == per second
  1102. /m == per minute
  1103. /h == per hour (default)
  1104. /d == per day (24 hours)
  1105. */
  1106. ParameterError err = PARAM_OK;
  1107. char *div = strchr(nextarg, '/');
  1108. char number[26];
  1109. long denominator;
  1110. long numerator = 60*60*1000; /* default per hour */
  1111. size_t numlen = div ? (size_t)(div - nextarg) : strlen(nextarg);
  1112. if(numlen > sizeof(number) -1)
  1113. return PARAM_NUMBER_TOO_LARGE;
  1114. strncpy(number, nextarg, numlen);
  1115. number[numlen] = 0;
  1116. err = str2unum(&denominator, number);
  1117. if(err)
  1118. return err;
  1119. if(denominator < 1)
  1120. return PARAM_BAD_USE;
  1121. if(div) {
  1122. char unit = div[1];
  1123. switch(unit) {
  1124. case 's': /* per second */
  1125. numerator = 1000;
  1126. break;
  1127. case 'm': /* per minute */
  1128. numerator = 60*1000;
  1129. break;
  1130. case 'h': /* per hour */
  1131. break;
  1132. case 'd': /* per day */
  1133. numerator = 24*60*60*1000;
  1134. break;
  1135. default:
  1136. errorf(global, "unsupported --rate unit");
  1137. err = PARAM_BAD_USE;
  1138. break;
  1139. }
  1140. }
  1141. if(err)
  1142. ;
  1143. else if(denominator > numerator)
  1144. err = PARAM_NUMBER_TOO_LARGE;
  1145. else
  1146. global->ms_per_transfer = numerator/denominator;
  1147. return err;
  1148. }
  1149. ParameterError getparameter(const char *flag, /* f or -long-flag */
  1150. char *nextarg, /* NULL if unset */
  1151. argv_item_t cleararg,
  1152. bool *usedarg, /* set to TRUE if the arg
  1153. has been used */
  1154. struct GlobalConfig *global,
  1155. struct OperationConfig *config)
  1156. {
  1157. int rc;
  1158. const char *parse = NULL;
  1159. time_t now;
  1160. bool longopt = FALSE;
  1161. bool singleopt = FALSE; /* when true means '-o foo' used '-ofoo' */
  1162. ParameterError err = PARAM_OK;
  1163. bool toggle = TRUE; /* how to switch boolean options, on or off. Controlled
  1164. by using --OPTION or --no-OPTION */
  1165. bool nextalloc = FALSE; /* if nextarg is allocated */
  1166. struct getout *url;
  1167. static const char *redir_protos[] = {
  1168. "http",
  1169. "https",
  1170. "ftp",
  1171. "ftps",
  1172. NULL
  1173. };
  1174. const struct LongShort *a = NULL;
  1175. curl_off_t value;
  1176. #ifdef HAVE_WRITABLE_ARGV
  1177. argv_item_t clearthis = NULL;
  1178. #else
  1179. (void)cleararg;
  1180. #endif
  1181. *usedarg = FALSE; /* default is that we don't use the arg */
  1182. if(('-' != flag[0]) || ('-' == flag[1])) {
  1183. /* this should be a long name */
  1184. const char *word = ('-' == flag[0]) ? flag + 2 : flag;
  1185. bool noflagged = FALSE;
  1186. bool expand = FALSE;
  1187. struct LongShort key;
  1188. if(!strncmp(word, "no-", 3)) {
  1189. /* disable this option but ignore the "no-" part when looking for it */
  1190. word += 3;
  1191. toggle = FALSE;
  1192. noflagged = TRUE;
  1193. }
  1194. else if(!strncmp(word, "expand-", 7)) {
  1195. /* variable expansions is to be done on the argument */
  1196. word += 7;
  1197. expand = TRUE;
  1198. }
  1199. key.lname = word;
  1200. a = bsearch(&key, aliases, sizeof(aliases)/sizeof(aliases[0]),
  1201. sizeof(aliases[0]), findarg);
  1202. if(a) {
  1203. longopt = TRUE;
  1204. }
  1205. else {
  1206. err = PARAM_OPTION_UNKNOWN;
  1207. goto error;
  1208. }
  1209. if(noflagged && (a->desc != ARG_BOOL)) {
  1210. /* --no- prefixed an option that isn't boolean! */
  1211. err = PARAM_NO_NOT_BOOLEAN;
  1212. goto error;
  1213. }
  1214. else if(expand && nextarg) {
  1215. struct curlx_dynbuf nbuf;
  1216. bool replaced;
  1217. if((a->desc != ARG_STRG) &&
  1218. (a->desc != ARG_FILE)) {
  1219. /* --expand on an option that isn't a string or a filename */
  1220. err = PARAM_EXPAND_ERROR;
  1221. goto error;
  1222. }
  1223. err = varexpand(global, nextarg, &nbuf, &replaced);
  1224. if(err) {
  1225. curlx_dyn_free(&nbuf);
  1226. goto error;
  1227. }
  1228. if(replaced) {
  1229. nextarg = curlx_dyn_ptr(&nbuf);
  1230. nextalloc = TRUE;
  1231. }
  1232. }
  1233. }
  1234. else {
  1235. flag++; /* prefixed with one dash, pass it */
  1236. parse = flag;
  1237. }
  1238. do {
  1239. /* we can loop here if we have multiple single-letters */
  1240. char letter;
  1241. cmdline_t cmd;
  1242. if(!longopt && !a) {
  1243. a = single(*parse);
  1244. if(!a) {
  1245. err = PARAM_OPTION_UNKNOWN;
  1246. break;
  1247. }
  1248. }
  1249. letter = a->letter;
  1250. cmd = a->cmd;
  1251. if(a->desc >= ARG_STRG) {
  1252. /* this option requires an extra parameter */
  1253. if(!longopt && parse[1]) {
  1254. nextarg = (char *)&parse[1]; /* this is the actual extra parameter */
  1255. singleopt = TRUE; /* don't loop anymore after this */
  1256. }
  1257. else if(!nextarg) {
  1258. err = PARAM_REQUIRES_PARAMETER;
  1259. break;
  1260. }
  1261. else {
  1262. #ifdef HAVE_WRITABLE_ARGV
  1263. clearthis = cleararg;
  1264. #endif
  1265. *usedarg = TRUE; /* mark it as used */
  1266. }
  1267. if((a->desc == ARG_FILE) &&
  1268. (nextarg[0] == '-') && nextarg[1]) {
  1269. /* if the file name looks like a command line option */
  1270. warnf(global, "The file name argument '%s' looks like a flag.",
  1271. nextarg);
  1272. }
  1273. else if(!strncmp("\xe2\x80\x9c", nextarg, 3)) {
  1274. warnf(global, "The argument '%s' starts with a unicode quote where "
  1275. "maybe an ASCII \" was intended?",
  1276. nextarg);
  1277. }
  1278. }
  1279. else if((a->desc == ARG_NONE) && !toggle) {
  1280. err = PARAM_NO_PREFIX;
  1281. break;
  1282. }
  1283. if(!nextarg)
  1284. /* this is a precaution mostly to please scan-build, as all arguments
  1285. that use nextarg should be marked as such and they will check that
  1286. nextarg is set before continuing, but code analyzers are not always
  1287. that aware of that state */
  1288. nextarg = (char *)"";
  1289. switch(cmd) {
  1290. case C_RANDOM_FILE: /* --random-file */
  1291. case C_EGD_FILE: /* --egd-file */
  1292. case C_NTLM_WB: /* --ntlm-wb */
  1293. warnf(global, "--%s is deprecated and has no function anymore",
  1294. a->lname);
  1295. break;
  1296. case C_DNS_IPV4_ADDR: /* --dns-ipv4-addr */
  1297. if(!curlinfo->ares_num) /* c-ares is needed for this */
  1298. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1299. else
  1300. /* addr in dot notation */
  1301. err = getstr(&config->dns_ipv4_addr, nextarg, DENY_BLANK);
  1302. break;
  1303. case C_DNS_IPV6_ADDR: /* --dns-ipv6-addr */
  1304. if(!curlinfo->ares_num) /* c-ares is needed for this */
  1305. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1306. else
  1307. /* addr in dot notation */
  1308. err = getstr(&config->dns_ipv6_addr, nextarg, DENY_BLANK);
  1309. break;
  1310. case C_OAUTH2_BEARER: /* --oauth2-bearer */
  1311. err = getstr(&config->oauth_bearer, nextarg, DENY_BLANK);
  1312. if(!err) {
  1313. cleanarg(clearthis);
  1314. config->authtype |= CURLAUTH_BEARER;
  1315. }
  1316. break;
  1317. case C_CONNECT_TIMEOUT: /* --connect-timeout */
  1318. err = secs2ms(&config->connecttimeout_ms, nextarg);
  1319. break;
  1320. case C_DOH_URL: /* --doh-url */
  1321. err = getstr(&config->doh_url, nextarg, ALLOW_BLANK);
  1322. if(!err && config->doh_url && !config->doh_url[0])
  1323. /* if given a blank string, make it NULL again */
  1324. Curl_safefree(config->doh_url);
  1325. break;
  1326. case C_CIPHERS: /* -- ciphers */
  1327. err = getstr(&config->cipher_list, nextarg, DENY_BLANK);
  1328. break;
  1329. case C_DNS_INTERFACE: /* --dns-interface */
  1330. if(!curlinfo->ares_num) /* c-ares is needed for this */
  1331. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1332. else
  1333. /* interface name */
  1334. err = getstr(&config->dns_interface, nextarg, DENY_BLANK);
  1335. break;
  1336. case C_DISABLE_EPSV: /* --disable-epsv */
  1337. config->disable_epsv = toggle;
  1338. break;
  1339. case C_DISALLOW_USERNAME_IN_URL: /* --disallow-username-in-url */
  1340. config->disallow_username_in_url = toggle;
  1341. break;
  1342. case C_EPSV: /* --epsv */
  1343. config->disable_epsv = (!toggle)?TRUE:FALSE;
  1344. break;
  1345. case C_DNS_SERVERS: /* --dns-servers */
  1346. if(!curlinfo->ares_num) /* c-ares is needed for this */
  1347. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1348. else
  1349. /* IP addrs of DNS servers */
  1350. err = getstr(&config->dns_servers, nextarg, DENY_BLANK);
  1351. break;
  1352. case C_TRACE: /* --trace */
  1353. err = getstr(&global->trace_dump, nextarg, DENY_BLANK);
  1354. if(!err) {
  1355. if(global->tracetype && (global->tracetype != TRACE_BIN))
  1356. warnf(global, "--trace overrides an earlier trace/verbose option");
  1357. global->tracetype = TRACE_BIN;
  1358. }
  1359. break;
  1360. case C_NPN: /* --npn */
  1361. warnf(global, "--npn is no longer supported");
  1362. break;
  1363. case C_TRACE_ASCII: /* --trace-ascii */
  1364. err = getstr(&global->trace_dump, nextarg, DENY_BLANK);
  1365. if(!err) {
  1366. if(global->tracetype && (global->tracetype != TRACE_ASCII))
  1367. warnf(global,
  1368. "--trace-ascii overrides an earlier trace/verbose option");
  1369. global->tracetype = TRACE_ASCII;
  1370. }
  1371. break;
  1372. case C_ALPN: /* --alpn */
  1373. config->noalpn = (!toggle)?TRUE:FALSE;
  1374. break;
  1375. case C_LIMIT_RATE: /* --limit-rate */
  1376. err = GetSizeParameter(global, nextarg, "rate", &value);
  1377. if(!err) {
  1378. config->recvpersecond = value;
  1379. config->sendpersecond = value;
  1380. }
  1381. break;
  1382. case C_RATE:
  1383. err = set_rate(global, nextarg);
  1384. break;
  1385. case C_COMPRESSED: /* --compressed */
  1386. if(toggle && !(feature_libz || feature_brotli || feature_zstd))
  1387. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1388. else
  1389. config->encoding = toggle;
  1390. break;
  1391. case C_TR_ENCODING: /* --tr-encoding */
  1392. config->tr_encoding = toggle;
  1393. break;
  1394. case C_DIGEST: /* --digest */
  1395. if(toggle)
  1396. config->authtype |= CURLAUTH_DIGEST;
  1397. else
  1398. config->authtype &= ~CURLAUTH_DIGEST;
  1399. break;
  1400. case C_NEGOTIATE: /* --negotiate */
  1401. if(!toggle)
  1402. config->authtype &= ~CURLAUTH_NEGOTIATE;
  1403. else if(feature_spnego)
  1404. config->authtype |= CURLAUTH_NEGOTIATE;
  1405. else
  1406. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1407. break;
  1408. case C_NTLM: /* --ntlm */
  1409. if(!toggle)
  1410. config->authtype &= ~CURLAUTH_NTLM;
  1411. else if(feature_ntlm)
  1412. config->authtype |= CURLAUTH_NTLM;
  1413. else
  1414. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1415. break;
  1416. case C_BASIC: /* --basic */
  1417. if(toggle)
  1418. config->authtype |= CURLAUTH_BASIC;
  1419. else
  1420. config->authtype &= ~CURLAUTH_BASIC;
  1421. break;
  1422. case C_ANYAUTH: /* --anyauth */
  1423. if(toggle)
  1424. config->authtype = CURLAUTH_ANY;
  1425. /* --no-anyauth simply doesn't touch it */
  1426. break;
  1427. #ifdef USE_WATT32
  1428. case C_WDEBUG: /* --wdebug */
  1429. dbug_init();
  1430. break;
  1431. #endif
  1432. case C_FTP_CREATE_DIRS: /* --ftp-create-dirs */
  1433. config->ftp_create_dirs = toggle;
  1434. break;
  1435. case C_CREATE_DIRS: /* --create-dirs */
  1436. config->create_dirs = toggle;
  1437. break;
  1438. case C_CREATE_FILE_MODE: /* --create-file-mode */
  1439. err = oct2nummax(&config->create_file_mode, nextarg, 0777);
  1440. break;
  1441. case C_MAX_REDIRS: /* --max-redirs */
  1442. /* specified max no of redirects (http(s)), this accepts -1 as a
  1443. special condition */
  1444. err = str2num(&config->maxredirs, nextarg);
  1445. if(!err && (config->maxredirs < -1))
  1446. err = PARAM_BAD_NUMERIC;
  1447. break;
  1448. case C_IPFS_GATEWAY: /* --ipfs-gateway */
  1449. err = getstr(&config->ipfs_gateway, nextarg, DENY_BLANK);
  1450. break;
  1451. case C_PROXY_NTLM: /* --proxy-ntlm */
  1452. if(!feature_ntlm)
  1453. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1454. else
  1455. config->proxyntlm = toggle;
  1456. break;
  1457. case C_CRLF: /* --crlf */
  1458. /* LF -> CRLF conversion? */
  1459. config->crlf = toggle;
  1460. break;
  1461. case C_AWS_SIGV4: /* --aws-sigv4 */
  1462. config->authtype |= CURLAUTH_AWS_SIGV4;
  1463. err = getstr(&config->aws_sigv4, nextarg, DENY_BLANK);
  1464. break;
  1465. case C_STDERR: /* --stderr */
  1466. tool_set_stderr_file(global, nextarg);
  1467. break;
  1468. case C_INTERFACE: /* --interface */
  1469. /* interface */
  1470. err = getstr(&config->iface, nextarg, DENY_BLANK);
  1471. break;
  1472. case C_KRB: /* --krb */
  1473. /* kerberos level string */
  1474. if(!feature_spnego)
  1475. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1476. else
  1477. err = getstr(&config->krblevel, nextarg, DENY_BLANK);
  1478. break;
  1479. case C_HAPROXY_PROTOCOL: /* --haproxy-protocol */
  1480. config->haproxy_protocol = toggle;
  1481. break;
  1482. case C_HAPROXY_CLIENTIP: /* --haproxy-clientip */
  1483. err = getstr(&config->haproxy_clientip, nextarg, DENY_BLANK);
  1484. break;
  1485. case C_MAX_FILESIZE: /* --max-filesize */
  1486. err = GetSizeParameter(global, nextarg, "max-filesize", &value);
  1487. if(!err)
  1488. config->max_filesize = value;
  1489. break;
  1490. case C_DISABLE_EPRT: /* --disable-eprt */
  1491. config->disable_eprt = toggle;
  1492. break;
  1493. case C_EPRT: /* --eprt */
  1494. config->disable_eprt = (!toggle)?TRUE:FALSE;
  1495. break;
  1496. case C_XATTR: /* --xattr */
  1497. config->xattr = toggle;
  1498. break;
  1499. case C_URL: /* --url */
  1500. if(!config->url_get)
  1501. config->url_get = config->url_list;
  1502. if(config->url_get) {
  1503. /* there's a node here, if it already is filled-in continue to find
  1504. an "empty" node */
  1505. while(config->url_get && (config->url_get->flags & GETOUT_URL))
  1506. config->url_get = config->url_get->next;
  1507. }
  1508. /* now there might or might not be an available node to fill in! */
  1509. if(config->url_get)
  1510. /* existing node */
  1511. url = config->url_get;
  1512. else
  1513. /* there was no free node, create one! */
  1514. config->url_get = url = new_getout(config);
  1515. if(!url)
  1516. err = PARAM_NO_MEM;
  1517. else {
  1518. /* fill in the URL */
  1519. err = getstr(&url->url, nextarg, DENY_BLANK);
  1520. url->flags |= GETOUT_URL;
  1521. }
  1522. break;
  1523. case C_FTP_SSL: /* --ftp-ssl */
  1524. case C_SSL: /* --ssl */
  1525. if(toggle && !feature_ssl)
  1526. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1527. else {
  1528. config->ftp_ssl = toggle;
  1529. if(config->ftp_ssl)
  1530. warnf(global,
  1531. "--%s is an insecure option, consider --ssl-reqd instead",
  1532. a->lname);
  1533. }
  1534. break;
  1535. case C_FTP_PASV: /* --ftp-pasv */
  1536. Curl_safefree(config->ftpport);
  1537. break;
  1538. case C_SOCKS5: /* --socks5 */
  1539. /* socks5 proxy to use, and resolves the name locally and passes on the
  1540. resolved address */
  1541. err = getstr(&config->proxy, nextarg, DENY_BLANK);
  1542. config->proxyver = CURLPROXY_SOCKS5;
  1543. break;
  1544. case C_SOCKS4: /* --socks4 */
  1545. err = getstr(&config->proxy, nextarg, DENY_BLANK);
  1546. config->proxyver = CURLPROXY_SOCKS4;
  1547. break;
  1548. case C_SOCKS4A: /* --socks4a */
  1549. err = getstr(&config->proxy, nextarg, DENY_BLANK);
  1550. config->proxyver = CURLPROXY_SOCKS4A;
  1551. break;
  1552. case C_SOCKS5_HOSTNAME: /* --socks5-hostname */
  1553. err = getstr(&config->proxy, nextarg, DENY_BLANK);
  1554. config->proxyver = CURLPROXY_SOCKS5_HOSTNAME;
  1555. break;
  1556. case C_TCP_NODELAY: /* --tcp-nodelay */
  1557. config->tcp_nodelay = toggle;
  1558. break;
  1559. case C_PROXY_DIGEST: /* --proxy-digest */
  1560. config->proxydigest = toggle;
  1561. break;
  1562. case C_PROXY_BASIC: /* --proxy-basic */
  1563. config->proxybasic = toggle;
  1564. break;
  1565. case C_RETRY: /* --retry */
  1566. err = str2unum(&config->req_retry, nextarg);
  1567. break;
  1568. case C_RETRY_CONNREFUSED: /* --retry-connrefused */
  1569. config->retry_connrefused = toggle;
  1570. break;
  1571. case C_RETRY_DELAY: /* --retry-delay */
  1572. err = str2unummax(&config->retry_delay, nextarg, LONG_MAX/1000);
  1573. break;
  1574. case C_RETRY_MAX_TIME: /* --retry-max-time */
  1575. err = str2unummax(&config->retry_maxtime, nextarg, LONG_MAX/1000);
  1576. break;
  1577. case C_RETRY_ALL_ERRORS: /* --retry-all-errors */
  1578. config->retry_all_errors = toggle;
  1579. break;
  1580. case C_PROXY_NEGOTIATE: /* --proxy-negotiate */
  1581. if(!feature_spnego)
  1582. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1583. else
  1584. config->proxynegotiate = toggle;
  1585. break;
  1586. case C_FORM_ESCAPE: /* --form-escape */
  1587. config->mime_options &= ~CURLMIMEOPT_FORMESCAPE;
  1588. if(toggle)
  1589. config->mime_options |= CURLMIMEOPT_FORMESCAPE;
  1590. break;
  1591. case C_FTP_ACCOUNT: /* --ftp-account */
  1592. err = getstr(&config->ftp_account, nextarg, DENY_BLANK);
  1593. break;
  1594. case C_PROXY_ANYAUTH: /* --proxy-anyauth */
  1595. config->proxyanyauth = toggle;
  1596. break;
  1597. case C_TRACE_TIME: /* --trace-time */
  1598. global->tracetime = toggle;
  1599. break;
  1600. case C_IGNORE_CONTENT_LENGTH: /* --ignore-content-length */
  1601. config->ignorecl = toggle;
  1602. break;
  1603. case C_FTP_SKIP_PASV_IP: /* --ftp-skip-pasv-ip */
  1604. config->ftp_skip_ip = toggle;
  1605. break;
  1606. case C_FTP_METHOD: /* --ftp-method */
  1607. config->ftp_filemethod = ftpfilemethod(config, nextarg);
  1608. break;
  1609. case C_LOCAL_PORT: { /* --local-port */
  1610. /* 16bit base 10 is 5 digits, but we allow 6 so that this catches
  1611. overflows, not just truncates */
  1612. char lrange[7]="";
  1613. char *p = nextarg;
  1614. while(ISDIGIT(*p))
  1615. p++;
  1616. if(*p) {
  1617. /* if there's anything more than a plain decimal number */
  1618. rc = sscanf(p, " - %6s", lrange);
  1619. *p = 0; /* null-terminate to make str2unum() work below */
  1620. }
  1621. else
  1622. rc = 0;
  1623. err = str2unum(&config->localport, nextarg);
  1624. if(err || (config->localport > 65535)) {
  1625. err = PARAM_BAD_USE;
  1626. break;
  1627. }
  1628. if(!rc)
  1629. config->localportrange = 1; /* default number of ports to try */
  1630. else {
  1631. err = str2unum(&config->localportrange, lrange);
  1632. if(err || (config->localportrange > 65535))
  1633. err = PARAM_BAD_USE;
  1634. else {
  1635. config->localportrange -= (config->localport-1);
  1636. if(config->localportrange < 1)
  1637. err = PARAM_BAD_USE;
  1638. }
  1639. }
  1640. break;
  1641. }
  1642. case C_FTP_ALTERNATIVE_TO_USER: /* --ftp-alternative-to-user */
  1643. err = getstr(&config->ftp_alternative_to_user, nextarg, DENY_BLANK);
  1644. break;
  1645. case C_FTP_SSL_REQD: /* --ftp-ssl-reqd */
  1646. case C_SSL_REQD: /* --ssl-reqd */
  1647. if(toggle && !feature_ssl) {
  1648. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1649. break;
  1650. }
  1651. config->ftp_ssl_reqd = toggle;
  1652. break;
  1653. case C_SESSIONID: /* --sessionid */
  1654. config->disable_sessionid = (!toggle)?TRUE:FALSE;
  1655. break;
  1656. case C_FTP_SSL_CONTROL: /* --ftp-ssl-control */
  1657. if(toggle && !feature_ssl)
  1658. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1659. else
  1660. config->ftp_ssl_control = toggle;
  1661. break;
  1662. case C_FTP_SSL_CCC: /* --ftp-ssl-ccc */
  1663. config->ftp_ssl_ccc = toggle;
  1664. if(!config->ftp_ssl_ccc_mode)
  1665. config->ftp_ssl_ccc_mode = CURLFTPSSL_CCC_PASSIVE;
  1666. break;
  1667. case C_FTP_SSL_CCC_MODE: /* --ftp-ssl-ccc-mode */
  1668. config->ftp_ssl_ccc = TRUE;
  1669. config->ftp_ssl_ccc_mode = ftpcccmethod(config, nextarg);
  1670. break;
  1671. case C_LIBCURL: /* --libcurl */
  1672. #ifdef CURL_DISABLE_LIBCURL_OPTION
  1673. warnf(global,
  1674. "--libcurl option was disabled at build-time");
  1675. err = PARAM_OPTION_UNKNOWN;
  1676. #else
  1677. err = getstr(&global->libcurl, nextarg, DENY_BLANK);
  1678. #endif
  1679. break;
  1680. case C_RAW: /* --raw */
  1681. config->raw = toggle;
  1682. break;
  1683. case C_KEEPALIVE: /* --keepalive */
  1684. config->nokeepalive = (!toggle)?TRUE:FALSE;
  1685. break;
  1686. case C_KEEPALIVE_TIME: /* --keepalive-time */
  1687. err = str2unum(&config->alivetime, nextarg);
  1688. break;
  1689. case C_POST301: /* --post301 */
  1690. config->post301 = toggle;
  1691. break;
  1692. case C_POST302: /* --post302 */
  1693. config->post302 = toggle;
  1694. break;
  1695. case C_POST303: /* --post303 */
  1696. config->post303 = toggle;
  1697. break;
  1698. case C_NOPROXY: /* --noproxy */
  1699. /* This specifies the noproxy list */
  1700. err = getstr(&config->noproxy, nextarg, ALLOW_BLANK);
  1701. break;
  1702. case C_SOCKS5_GSSAPI_NEC: /* --socks5-gssapi-nec */
  1703. config->socks5_gssapi_nec = toggle;
  1704. break;
  1705. case C_PROXY1_0: /* --proxy1.0 */
  1706. /* http 1.0 proxy */
  1707. err = getstr(&config->proxy, nextarg, DENY_BLANK);
  1708. config->proxyver = CURLPROXY_HTTP_1_0;
  1709. break;
  1710. case C_TFTP_BLKSIZE: /* --tftp-blksize */
  1711. err = str2unum(&config->tftp_blksize, nextarg);
  1712. break;
  1713. case C_MAIL_FROM: /* --mail-from */
  1714. err = getstr(&config->mail_from, nextarg, DENY_BLANK);
  1715. break;
  1716. case C_MAIL_RCPT: /* --mail-rcpt */
  1717. /* append receiver to a list */
  1718. err = add2list(&config->mail_rcpt, nextarg);
  1719. break;
  1720. case C_FTP_PRET: /* --ftp-pret */
  1721. config->ftp_pret = toggle;
  1722. break;
  1723. case C_PROTO: /* --proto */
  1724. config->proto_present = TRUE;
  1725. err = proto2num(config, built_in_protos, &config->proto_str, nextarg);
  1726. break;
  1727. case C_PROTO_REDIR: /* --proto-redir */
  1728. config->proto_redir_present = TRUE;
  1729. if(proto2num(config, redir_protos, &config->proto_redir_str,
  1730. nextarg))
  1731. err = PARAM_BAD_USE;
  1732. break;
  1733. case C_RESOLVE: /* --resolve */
  1734. err = add2list(&config->resolve, nextarg);
  1735. break;
  1736. case C_DELEGATION: /* --delegation */
  1737. config->gssapi_delegation = delegation(config, nextarg);
  1738. break;
  1739. case C_MAIL_AUTH: /* --mail-auth */
  1740. err = getstr(&config->mail_auth, nextarg, DENY_BLANK);
  1741. break;
  1742. case C_METALINK: /* --metalink */
  1743. errorf(global, "--metalink is disabled");
  1744. err = PARAM_BAD_USE;
  1745. break;
  1746. case C_SASL_AUTHZID: /* --sasl-authzid */
  1747. err = getstr(&config->sasl_authzid, nextarg, DENY_BLANK);
  1748. break;
  1749. case C_SASL_IR: /* --sasl-ir */
  1750. config->sasl_ir = toggle;
  1751. break;
  1752. case C_TEST_EVENT: /* --test-event */
  1753. #ifdef CURLDEBUG
  1754. global->test_event_based = toggle;
  1755. #else
  1756. warnf(global, "--test-event is ignored unless a debug build");
  1757. #endif
  1758. break;
  1759. case C_UNIX_SOCKET: /* --unix-socket */
  1760. config->abstract_unix_socket = FALSE;
  1761. err = getstr(&config->unix_socket_path, nextarg, DENY_BLANK);
  1762. break;
  1763. case C_PATH_AS_IS: /* --path-as-is */
  1764. config->path_as_is = toggle;
  1765. break;
  1766. case C_PROXY_SERVICE_NAME: /* --proxy-service-name */
  1767. err = getstr(&config->proxy_service_name, nextarg, DENY_BLANK);
  1768. break;
  1769. case C_SERVICE_NAME: /* --service-name */
  1770. err = getstr(&config->service_name, nextarg, DENY_BLANK);
  1771. break;
  1772. case C_PROTO_DEFAULT: /* --proto-default */
  1773. err = getstr(&config->proto_default, nextarg, DENY_BLANK);
  1774. if(!err)
  1775. err = check_protocol(config->proto_default);
  1776. break;
  1777. case C_EXPECT100_TIMEOUT: /* --expect100-timeout */
  1778. err = secs2ms(&config->expect100timeout_ms, nextarg);
  1779. break;
  1780. case C_TFTP_NO_OPTIONS: /* --tftp-no-options */
  1781. config->tftp_no_options = toggle;
  1782. break;
  1783. case C_CONNECT_TO: /* --connect-to */
  1784. err = add2list(&config->connect_to, nextarg);
  1785. break;
  1786. case C_ABSTRACT_UNIX_SOCKET: /* --abstract-unix-socket */
  1787. config->abstract_unix_socket = TRUE;
  1788. err = getstr(&config->unix_socket_path, nextarg, DENY_BLANK);
  1789. break;
  1790. case C_TLS_MAX: /* --tls-max */
  1791. err = str2tls_max(&config->ssl_version_max, nextarg);
  1792. break;
  1793. case C_SUPPRESS_CONNECT_HEADERS: /* --suppress-connect-headers */
  1794. config->suppress_connect_headers = toggle;
  1795. break;
  1796. case C_COMPRESSED_SSH: /* --compressed-ssh */
  1797. config->ssh_compression = toggle;
  1798. break;
  1799. case C_HAPPY_EYEBALLS_TIMEOUT_MS: /* --happy-eyeballs-timeout-ms */
  1800. err = str2unum(&config->happy_eyeballs_timeout_ms, nextarg);
  1801. /* 0 is a valid value for this timeout */
  1802. break;
  1803. case C_TRACE_IDS: /* --trace-ids */
  1804. global->traceids = toggle;
  1805. break;
  1806. case C_TRACE_CONFIG: /* --trace-config */
  1807. if(set_trace_config(global, nextarg))
  1808. err = PARAM_NO_MEM;
  1809. break;
  1810. case C_PROGRESS_METER: /* --progress-meter */
  1811. global->noprogress = !toggle;
  1812. break;
  1813. case C_PROGRESS_BAR: /* --progress-bar */
  1814. global->progressmode = toggle ? CURL_PROGRESS_BAR : CURL_PROGRESS_STATS;
  1815. break;
  1816. case C_VARIABLE: /* --Variable */
  1817. err = setvariable(global, nextarg);
  1818. break;
  1819. case C_NEXT: /* --next */
  1820. err = PARAM_NEXT_OPERATION;
  1821. break;
  1822. case C_HTTP1_0: /* --http1.0 */
  1823. /* HTTP version 1.0 */
  1824. sethttpver(global, config, CURL_HTTP_VERSION_1_0);
  1825. break;
  1826. case C_HTTP1_1: /* --http1.1 */
  1827. /* HTTP version 1.1 */
  1828. sethttpver(global, config, CURL_HTTP_VERSION_1_1);
  1829. break;
  1830. case C_HTTP2: /* --http2 */
  1831. /* HTTP version 2.0 */
  1832. if(!feature_http2)
  1833. return PARAM_LIBCURL_DOESNT_SUPPORT;
  1834. sethttpver(global, config, CURL_HTTP_VERSION_2_0);
  1835. break;
  1836. case C_HTTP2_PRIOR_KNOWLEDGE: /* --http2-prior-knowledge */
  1837. /* HTTP version 2.0 over clean TCP */
  1838. if(!feature_http2)
  1839. return PARAM_LIBCURL_DOESNT_SUPPORT;
  1840. sethttpver(global, config, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
  1841. break;
  1842. case C_HTTP3: /* --http3: */
  1843. /* Try HTTP/3, allow fallback */
  1844. if(!feature_http3)
  1845. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1846. else
  1847. sethttpver(global, config, CURL_HTTP_VERSION_3);
  1848. break;
  1849. case C_HTTP3_ONLY: /* --http3-only */
  1850. /* Try HTTP/3 without fallback */
  1851. if(!feature_http3)
  1852. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1853. else
  1854. sethttpver(global, config, CURL_HTTP_VERSION_3ONLY);
  1855. break;
  1856. case C_HTTP0_9: /* --http0.9 */
  1857. /* Allow HTTP/0.9 responses! */
  1858. config->http09_allowed = toggle;
  1859. break;
  1860. case C_PROXY_HTTP2: /* --proxy-http2 */
  1861. if(!feature_httpsproxy || !feature_http2)
  1862. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1863. else
  1864. config->proxyver = CURLPROXY_HTTPS2;
  1865. break;
  1866. case C_TLSV1: /* --tlsv1 */
  1867. config->ssl_version = CURL_SSLVERSION_TLSv1;
  1868. break;
  1869. case C_TLSV1_0: /* --tlsv1.0 */
  1870. config->ssl_version = CURL_SSLVERSION_TLSv1_0;
  1871. break;
  1872. case C_TLSV1_1: /* --tlsv1.1 */
  1873. config->ssl_version = CURL_SSLVERSION_TLSv1_1;
  1874. break;
  1875. case C_TLSV1_2: /* --tlsv1.2 */
  1876. config->ssl_version = CURL_SSLVERSION_TLSv1_2;
  1877. break;
  1878. case C_TLSV1_3: /* --tlsv1.3 */
  1879. config->ssl_version = CURL_SSLVERSION_TLSv1_3;
  1880. break;
  1881. case C_TLS13_CIPHERS: /* --tls13-ciphers */
  1882. err = getstr(&config->cipher13_list, nextarg, DENY_BLANK);
  1883. break;
  1884. case C_PROXY_TLS13_CIPHERS: /* --proxy-tls13-ciphers */
  1885. err = getstr(&config->proxy_cipher13_list, nextarg, DENY_BLANK);
  1886. break;
  1887. case C_SSLV2: /* --sslv2 */
  1888. warnf(global, "Ignores instruction to use SSLv2");
  1889. break;
  1890. case C_SSLV3: /* --sslv3 */
  1891. warnf(global, "Ignores instruction to use SSLv3");
  1892. break;
  1893. case C_IPV4: /* --ipv4 */
  1894. config->ip_version = CURL_IPRESOLVE_V4;
  1895. break;
  1896. case C_IPV6: /* --ipv6 */
  1897. config->ip_version = CURL_IPRESOLVE_V6;
  1898. break;
  1899. case C_APPEND: /* --append */
  1900. /* This makes the FTP sessions use APPE instead of STOR */
  1901. config->ftp_append = toggle;
  1902. break;
  1903. case C_USER_AGENT: /* --user-agent */
  1904. err = getstr(&config->useragent, nextarg, ALLOW_BLANK);
  1905. break;
  1906. case C_ALT_SVC: /* --alt-svc */
  1907. if(!feature_altsvc)
  1908. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1909. else
  1910. err = getstr(&config->altsvc, nextarg, ALLOW_BLANK);
  1911. break;
  1912. case C_HSTS: /* --hsts */
  1913. if(!feature_hsts)
  1914. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  1915. else
  1916. err = getstr(&config->hsts, nextarg, ALLOW_BLANK);
  1917. break;
  1918. case C_COOKIE: /* --cookie */
  1919. if(strchr(nextarg, '=')) {
  1920. /* A cookie string must have a =-letter */
  1921. err = add2list(&config->cookies, nextarg);
  1922. break;
  1923. }
  1924. else {
  1925. /* We have a cookie file to read from! */
  1926. err = add2list(&config->cookiefiles, nextarg);
  1927. }
  1928. break;
  1929. case C_USE_ASCII: /* --use-ascii */
  1930. config->use_ascii = toggle;
  1931. break;
  1932. case C_COOKIE_JAR: /* --cookie-jar */
  1933. err = getstr(&config->cookiejar, nextarg, DENY_BLANK);
  1934. break;
  1935. case C_CONTINUE_AT: /* --continue-at */
  1936. /* This makes us continue an ftp transfer at given position */
  1937. if(strcmp(nextarg, "-")) {
  1938. err = str2offset(&config->resume_from, nextarg);
  1939. config->resume_from_current = FALSE;
  1940. }
  1941. else {
  1942. config->resume_from_current = TRUE;
  1943. config->resume_from = 0;
  1944. }
  1945. config->use_resume = TRUE;
  1946. break;
  1947. case C_DATA: /* --data */
  1948. case C_DATA_ASCII: /* --data-ascii */
  1949. case C_DATA_BINARY: /* --data-binary */
  1950. case C_DATA_URLENCODE: /* --data-urlencode */
  1951. case C_JSON: /* --json */
  1952. case C_DATA_RAW: /* --data-raw */
  1953. err = set_data(cmd, nextarg, global, config);
  1954. break;
  1955. case C_URL_QUERY: /* --url-query */
  1956. err = url_query(nextarg, global, config);
  1957. break;
  1958. case C_DUMP_HEADER: /* --dump-header */
  1959. err = getstr(&config->headerfile, nextarg, DENY_BLANK);
  1960. break;
  1961. case C_REFERER: { /* --referer */
  1962. char *ptr = strstr(nextarg, ";auto");
  1963. if(ptr) {
  1964. /* Automatic referer requested, this may be combined with a
  1965. set initial one */
  1966. config->autoreferer = TRUE;
  1967. *ptr = 0; /* null-terminate here */
  1968. }
  1969. else
  1970. config->autoreferer = FALSE;
  1971. ptr = *nextarg ? nextarg : NULL;
  1972. err = getstr(&config->referer, ptr, ALLOW_BLANK);
  1973. }
  1974. break;
  1975. case C_CERT: /* --cert */
  1976. cleanarg(clearthis);
  1977. GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
  1978. break;
  1979. case C_CACERT: /* --cacert */
  1980. err = getstr(&config->cacert, nextarg, DENY_BLANK);
  1981. break;
  1982. case C_CA_NATIVE: /* --ca-native */
  1983. config->native_ca_store = toggle;
  1984. break;
  1985. case C_PROXY_CA_NATIVE: /* --proxy-ca-native */
  1986. config->proxy_native_ca_store = toggle;
  1987. break;
  1988. case C_CERT_TYPE: /* --cert-type */
  1989. err = getstr(&config->cert_type, nextarg, DENY_BLANK);
  1990. break;
  1991. case C_KEY: /* --key */
  1992. err = getstr(&config->key, nextarg, DENY_BLANK);
  1993. break;
  1994. case C_KEY_TYPE: /* --key-type */
  1995. err = getstr(&config->key_type, nextarg, DENY_BLANK);
  1996. break;
  1997. case C_PASS: /* --pass */
  1998. err = getstr(&config->key_passwd, nextarg, DENY_BLANK);
  1999. cleanarg(clearthis);
  2000. break;
  2001. case C_ENGINE: /* --engine */
  2002. err = getstr(&config->engine, nextarg, DENY_BLANK);
  2003. if(!err &&
  2004. config->engine && !strcmp(config->engine, "list")) {
  2005. err = PARAM_ENGINES_REQUESTED;
  2006. }
  2007. break;
  2008. #ifndef USE_ECH
  2009. case C_ECH: /* --ech, not implemented by default */
  2010. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  2011. break;
  2012. #else
  2013. case C_ECH: /* --ech */
  2014. if(strlen(nextarg) > 4 && strncasecompare("pn:", nextarg, 3)) {
  2015. /* a public_name */
  2016. err = getstr(&config->ech_public, nextarg, DENY_BLANK);
  2017. }
  2018. else if(strlen(nextarg) > 5 && strncasecompare("ecl:", nextarg, 4)) {
  2019. /* an ECHConfigList */
  2020. if('@' != *(nextarg + 4)) {
  2021. err = getstr(&config->ech_config, nextarg, DENY_BLANK);
  2022. }
  2023. else {
  2024. /* Indirect case: @filename or @- for stdin */
  2025. char *tmpcfg = NULL;
  2026. FILE *file;
  2027. nextarg++; /* skip over '@' */
  2028. if(!strcmp("-", nextarg)) {
  2029. file = stdin;
  2030. }
  2031. else {
  2032. file = fopen(nextarg, FOPEN_READTEXT);
  2033. }
  2034. if(!file) {
  2035. warnf(global,
  2036. "Couldn't read file \"%s\" "
  2037. "specified for \"--ech ecl:\" option",
  2038. nextarg);
  2039. return PARAM_BAD_USE; /* */
  2040. }
  2041. err = file2string(&tmpcfg, file);
  2042. if(file != stdin)
  2043. fclose(file);
  2044. if(err)
  2045. return err;
  2046. config->ech_config = aprintf("ecl:%s",tmpcfg);
  2047. if(!config->ech_config)
  2048. return PARAM_NO_MEM;
  2049. free(tmpcfg);
  2050. } /* file done */
  2051. }
  2052. else {
  2053. /* Simple case: just a string, with a keyword */
  2054. err = getstr(&config->ech, nextarg, DENY_BLANK);
  2055. }
  2056. break;
  2057. #endif
  2058. case C_CAPATH: /* --capath */
  2059. err = getstr(&config->capath, nextarg, DENY_BLANK);
  2060. break;
  2061. case C_PUBKEY: /* --pubkey */
  2062. err = getstr(&config->pubkey, nextarg, DENY_BLANK);
  2063. break;
  2064. case C_HOSTPUBMD5: /* --hostpubmd5 */
  2065. err = getstr(&config->hostpubmd5, nextarg, DENY_BLANK);
  2066. if(!err) {
  2067. if(!config->hostpubmd5 || strlen(config->hostpubmd5) != 32)
  2068. err = PARAM_BAD_USE;
  2069. }
  2070. break;
  2071. case C_HOSTPUBSHA256: /* --hostpubsha256 */
  2072. err = getstr(&config->hostpubsha256, nextarg, DENY_BLANK);
  2073. break;
  2074. case C_CRLFILE: /* --crlfile */
  2075. err = getstr(&config->crlfile, nextarg, DENY_BLANK);
  2076. break;
  2077. case C_TLSUSER: /* --tlsuser */
  2078. if(!feature_tls_srp)
  2079. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  2080. else
  2081. err = getstr(&config->tls_username, nextarg, DENY_BLANK);
  2082. cleanarg(clearthis);
  2083. break;
  2084. case C_TLSPASSWORD: /* --tlspassword */
  2085. if(!feature_tls_srp)
  2086. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  2087. else
  2088. err = getstr(&config->tls_password, nextarg, ALLOW_BLANK);
  2089. cleanarg(clearthis);
  2090. break;
  2091. case C_TLSAUTHTYPE: /* --tlsauthtype */
  2092. if(!feature_tls_srp)
  2093. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  2094. else {
  2095. err = getstr(&config->tls_authtype, nextarg, DENY_BLANK);
  2096. if(!err && strcmp(config->tls_authtype, "SRP"))
  2097. err = PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
  2098. }
  2099. break;
  2100. case C_SSL_ALLOW_BEAST: /* --ssl-allow-beast */
  2101. if(feature_ssl)
  2102. config->ssl_allow_beast = toggle;
  2103. break;
  2104. case C_SSL_AUTO_CLIENT_CERT: /* --ssl-auto-client-cert */
  2105. if(feature_ssl)
  2106. config->ssl_auto_client_cert = toggle;
  2107. break;
  2108. case C_PROXY_SSL_AUTO_CLIENT_CERT: /* --proxy-ssl-auto-client-cert */
  2109. if(feature_ssl)
  2110. config->proxy_ssl_auto_client_cert = toggle;
  2111. break;
  2112. case C_PINNEDPUBKEY: /* --pinnedpubkey */
  2113. err = getstr(&config->pinnedpubkey, nextarg, DENY_BLANK);
  2114. break;
  2115. case C_PROXY_PINNEDPUBKEY: /* --proxy-pinnedpubkey */
  2116. err = getstr(&config->proxy_pinnedpubkey, nextarg, DENY_BLANK);
  2117. break;
  2118. case C_CERT_STATUS: /* --cert-status */
  2119. config->verifystatus = TRUE;
  2120. break;
  2121. case C_DOH_CERT_STATUS: /* --doh-cert-status */
  2122. config->doh_verifystatus = TRUE;
  2123. break;
  2124. case C_FALSE_START: /* --false-start */
  2125. config->falsestart = TRUE;
  2126. break;
  2127. case C_SSL_NO_REVOKE: /* --ssl-no-revoke */
  2128. if(feature_ssl)
  2129. config->ssl_no_revoke = TRUE;
  2130. break;
  2131. case C_SSL_REVOKE_BEST_EFFORT: /* --ssl-revoke-best-effort */
  2132. if(feature_ssl)
  2133. config->ssl_revoke_best_effort = TRUE;
  2134. break;
  2135. case C_TCP_FASTOPEN: /* --tcp-fastopen */
  2136. config->tcp_fastopen = TRUE;
  2137. break;
  2138. case C_PROXY_TLSUSER: /* --proxy-tlsuser */
  2139. cleanarg(clearthis);
  2140. if(!feature_tls_srp)
  2141. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  2142. else
  2143. err = getstr(&config->proxy_tls_username, nextarg, ALLOW_BLANK);
  2144. break;
  2145. case C_PROXY_TLSPASSWORD: /* --proxy-tlspassword */
  2146. cleanarg(clearthis);
  2147. if(!feature_tls_srp)
  2148. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  2149. else
  2150. err = getstr(&config->proxy_tls_password, nextarg, DENY_BLANK);
  2151. break;
  2152. case C_PROXY_TLSAUTHTYPE: /* --proxy-tlsauthtype */
  2153. if(!feature_tls_srp)
  2154. err = PARAM_LIBCURL_DOESNT_SUPPORT;
  2155. else {
  2156. err = getstr(&config->proxy_tls_authtype, nextarg, DENY_BLANK);
  2157. if(!err && strcmp(config->proxy_tls_authtype, "SRP"))
  2158. err = PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
  2159. }
  2160. break;
  2161. case C_PROXY_CERT: /* --proxy-cert */
  2162. cleanarg(clearthis);
  2163. GetFileAndPassword(nextarg, &config->proxy_cert,
  2164. &config->proxy_key_passwd);
  2165. break;
  2166. case C_PROXY_CERT_TYPE: /* --proxy-cert-type */
  2167. err = getstr(&config->proxy_cert_type, nextarg, DENY_BLANK);
  2168. break;
  2169. case C_PROXY_KEY: /* --proxy-key */
  2170. err = getstr(&config->proxy_key, nextarg, ALLOW_BLANK);
  2171. break;
  2172. case C_PROXY_KEY_TYPE: /* --proxy-key-type */
  2173. err = getstr(&config->proxy_key_type, nextarg, DENY_BLANK);
  2174. break;
  2175. case C_PROXY_PASS: /* --proxy-pass */
  2176. err = getstr(&config->proxy_key_passwd, nextarg, ALLOW_BLANK);
  2177. cleanarg(clearthis);
  2178. break;
  2179. case C_PROXY_CIPHERS: /* --proxy-ciphers */
  2180. err = getstr(&config->proxy_cipher_list, nextarg, DENY_BLANK);
  2181. break;
  2182. case C_PROXY_CRLFILE: /* --proxy-crlfile */
  2183. err = getstr(&config->proxy_crlfile, nextarg, DENY_BLANK);
  2184. break;
  2185. case C_PROXY_SSL_ALLOW_BEAST: /* --proxy-ssl-allow-beast */
  2186. if(feature_ssl)
  2187. config->proxy_ssl_allow_beast = toggle;
  2188. break;
  2189. case C_LOGIN_OPTIONS: /* --login-options */
  2190. err = getstr(&config->login_options, nextarg, ALLOW_BLANK);
  2191. break;
  2192. case C_PROXY_CACERT: /* --proxy-cacert */
  2193. err = getstr(&config->proxy_cacert, nextarg, DENY_BLANK);
  2194. break;
  2195. case C_PROXY_CAPATH: /* --proxy-capath */
  2196. err = getstr(&config->proxy_capath, nextarg, DENY_BLANK);
  2197. break;
  2198. case C_PROXY_INSECURE: /* --proxy-insecure */
  2199. config->proxy_insecure_ok = toggle;
  2200. break;
  2201. case C_PROXY_TLSV1: /* --proxy-tlsv1 */
  2202. /* TLS version 1 for proxy */
  2203. config->proxy_ssl_version = CURL_SSLVERSION_TLSv1;
  2204. break;
  2205. case C_SOCKS5_BASIC: /* --socks5-basic */
  2206. if(toggle)
  2207. config->socks5_auth |= CURLAUTH_BASIC;
  2208. else
  2209. config->socks5_auth &= ~CURLAUTH_BASIC;
  2210. break;
  2211. case C_SOCKS5_GSSAPI: /* --socks5-gssapi */
  2212. if(toggle)
  2213. config->socks5_auth |= CURLAUTH_GSSAPI;
  2214. else
  2215. config->socks5_auth &= ~CURLAUTH_GSSAPI;
  2216. break;
  2217. case C_ETAG_SAVE: /* --etag-save */
  2218. err = getstr(&config->etag_save_file, nextarg, DENY_BLANK);
  2219. break;
  2220. case C_ETAG_COMPARE: /* --etag-compare */
  2221. err = getstr(&config->etag_compare_file, nextarg, DENY_BLANK);
  2222. break;
  2223. case C_CURVES: /* --curves */
  2224. err = getstr(&config->ssl_ec_curves, nextarg, DENY_BLANK);
  2225. break;
  2226. case C_FAIL_EARLY: /* --fail-early */
  2227. global->fail_early = toggle;
  2228. break;
  2229. case C_STYLED_OUTPUT: /* --styled-output */
  2230. global->styled_output = toggle;
  2231. break;
  2232. case C_MAIL_RCPT_ALLOWFAILS: /* --mail-rcpt-allowfails */
  2233. config->mail_rcpt_allowfails = toggle;
  2234. break;
  2235. case C_FAIL_WITH_BODY: /* --fail-with-body */
  2236. config->failwithbody = toggle;
  2237. if(config->failonerror && config->failwithbody) {
  2238. errorf(config->global, "You must select either --fail or "
  2239. "--fail-with-body, not both.");
  2240. err = PARAM_BAD_USE;
  2241. }
  2242. break;
  2243. case C_REMOVE_ON_ERROR: /* --remove-on-error */
  2244. config->rm_partial = toggle;
  2245. break;
  2246. case C_FAIL: /* --fail */
  2247. config->failonerror = toggle;
  2248. if(config->failonerror && config->failwithbody) {
  2249. errorf(config->global, "You must select either --fail or "
  2250. "--fail-with-body, not both.");
  2251. err = PARAM_BAD_USE;
  2252. }
  2253. break;
  2254. case C_FORM: /* --form */
  2255. case C_FORM_STRING: /* --form-string */
  2256. /* "form data" simulation, this is a little advanced so lets do our best
  2257. to sort this out slowly and carefully */
  2258. if(formparse(config,
  2259. nextarg,
  2260. &config->mimeroot,
  2261. &config->mimecurrent,
  2262. (cmd == C_FORM_STRING)?TRUE:FALSE)) /* literal string */
  2263. err = PARAM_BAD_USE;
  2264. else if(SetHTTPrequest(config, HTTPREQ_MIMEPOST, &config->httpreq))
  2265. err = PARAM_BAD_USE;
  2266. break;
  2267. case C_GLOBOFF: /* --globoff */
  2268. config->globoff = toggle;
  2269. break;
  2270. case C_GET: /* --get */
  2271. config->use_httpget = toggle;
  2272. break;
  2273. case C_REQUEST_TARGET: /* --request-target */
  2274. err = getstr(&config->request_target, nextarg, DENY_BLANK);
  2275. break;
  2276. case C_HELP: /* --help */
  2277. if(toggle) {
  2278. if(*nextarg) {
  2279. global->help_category = strdup(nextarg);
  2280. if(!global->help_category) {
  2281. err = PARAM_NO_MEM;
  2282. break;
  2283. }
  2284. }
  2285. err = PARAM_HELP_REQUESTED;
  2286. }
  2287. /* we now actually support --no-help too! */
  2288. break;
  2289. case C_HEADER: /* --header */
  2290. case C_PROXY_HEADER: /* --proxy-header */
  2291. /* A custom header to append to a list */
  2292. if(nextarg[0] == '@') {
  2293. /* read many headers from a file or stdin */
  2294. char *string;
  2295. size_t len;
  2296. bool use_stdin = !strcmp(&nextarg[1], "-");
  2297. FILE *file = use_stdin?stdin:fopen(&nextarg[1], FOPEN_READTEXT);
  2298. if(!file) {
  2299. errorf(global, "Failed to open %s", &nextarg[1]);
  2300. err = PARAM_READ_ERROR;
  2301. }
  2302. else {
  2303. err = file2memory(&string, &len, file);
  2304. if(!err && string) {
  2305. /* Allow strtok() here since this isn't used threaded */
  2306. /* !checksrc! disable BANNEDFUNC 2 */
  2307. char *h = strtok(string, "\r\n");
  2308. while(h) {
  2309. if(cmd == C_PROXY_HEADER) /* --proxy-header */
  2310. err = add2list(&config->proxyheaders, h);
  2311. else
  2312. err = add2list(&config->headers, h);
  2313. if(err)
  2314. break;
  2315. h = strtok(NULL, "\r\n");
  2316. }
  2317. free(string);
  2318. }
  2319. if(!use_stdin)
  2320. fclose(file);
  2321. }
  2322. }
  2323. else {
  2324. if(cmd == C_PROXY_HEADER) /* --proxy-header */
  2325. err = add2list(&config->proxyheaders, nextarg);
  2326. else
  2327. err = add2list(&config->headers, nextarg);
  2328. }
  2329. break;
  2330. case C_INCLUDE: /* --include */
  2331. config->show_headers = toggle; /* show the headers as well in the
  2332. general output stream */
  2333. break;
  2334. case C_JUNK_SESSION_COOKIES: /* --junk-session-cookies */
  2335. config->cookiesession = toggle;
  2336. break;
  2337. case C_HEAD: /* --head */
  2338. config->no_body = toggle;
  2339. config->show_headers = toggle;
  2340. if(SetHTTPrequest(config,
  2341. (config->no_body)?HTTPREQ_HEAD:HTTPREQ_GET,
  2342. &config->httpreq))
  2343. err = PARAM_BAD_USE;
  2344. break;
  2345. case C_REMOTE_HEADER_NAME: /* --remote-header-name */
  2346. config->content_disposition = toggle;
  2347. break;
  2348. case C_INSECURE: /* --insecure */
  2349. config->insecure_ok = toggle;
  2350. break;
  2351. case C_DOH_INSECURE: /* --doh-insecure */
  2352. config->doh_insecure_ok = toggle;
  2353. break;
  2354. case C_CONFIG: /* --config */
  2355. if(parseconfig(nextarg, global)) {
  2356. errorf(global, "cannot read config from '%s'", nextarg);
  2357. err = PARAM_READ_ERROR;
  2358. }
  2359. break;
  2360. case C_LIST_ONLY: /* --list-only */
  2361. config->dirlistonly = toggle; /* only list the names of the FTP dir */
  2362. break;
  2363. case C_LOCATION_TRUSTED: /* --location-trusted */
  2364. /* Continue to send authentication (user+password) when following
  2365. * locations, even when hostname changed */
  2366. config->unrestricted_auth = toggle;
  2367. FALLTHROUGH();
  2368. case C_LOCATION: /* --location */
  2369. config->followlocation = toggle; /* Follow Location: HTTP headers */
  2370. break;
  2371. case C_MAX_TIME: /* --max-time */
  2372. /* specified max time */
  2373. err = secs2ms(&config->timeout_ms, nextarg);
  2374. break;
  2375. case C_MANUAL: /* --manual */
  2376. if(toggle) { /* --no-manual shows no manual... */
  2377. #ifndef USE_MANUAL
  2378. warnf(global,
  2379. "built-in manual was disabled at build-time");
  2380. #endif
  2381. err = PARAM_MANUAL_REQUESTED;
  2382. }
  2383. break;
  2384. case C_NETRC_OPTIONAL: /* --netrc-optional */
  2385. config->netrc_opt = toggle;
  2386. break;
  2387. case C_NETRC_FILE: /* --netrc-file */
  2388. err = getstr(&config->netrc_file, nextarg, DENY_BLANK);
  2389. break;
  2390. case C_NETRC: /* --netrc */
  2391. /* pick info from .netrc, if this is used for http, curl will
  2392. automatically enforce user+password with the request */
  2393. config->netrc = toggle;
  2394. break;
  2395. case C_BUFFER: /* --buffer */
  2396. /* disable the output I/O buffering. note that the option is called
  2397. --buffer but is mostly used in the negative form: --no-buffer */
  2398. config->nobuffer = longopt ? !toggle : TRUE;
  2399. break;
  2400. case C_REMOTE_NAME_ALL: /* --remote-name-all */
  2401. config->default_node_flags = toggle?GETOUT_USEREMOTE:0;
  2402. break;
  2403. case C_OUTPUT_DIR: /* --output-dir */
  2404. err = getstr(&config->output_dir, nextarg, DENY_BLANK);
  2405. break;
  2406. case C_CLOBBER: /* --clobber */
  2407. config->file_clobber_mode = toggle ? CLOBBER_ALWAYS : CLOBBER_NEVER;
  2408. break;
  2409. case C_OUTPUT: /* --output */
  2410. case C_REMOTE_NAME: /* --remote-name */
  2411. /* output file */
  2412. if(!config->url_out)
  2413. config->url_out = config->url_list;
  2414. if(config->url_out) {
  2415. /* there's a node here, if it already is filled-in continue to find
  2416. an "empty" node */
  2417. while(config->url_out && (config->url_out->flags & GETOUT_OUTFILE))
  2418. config->url_out = config->url_out->next;
  2419. }
  2420. /* now there might or might not be an available node to fill in! */
  2421. if(config->url_out)
  2422. /* existing node */
  2423. url = config->url_out;
  2424. else {
  2425. if(!toggle && !config->default_node_flags)
  2426. break;
  2427. /* there was no free node, create one! */
  2428. config->url_out = url = new_getout(config);
  2429. }
  2430. if(!url) {
  2431. err = PARAM_NO_MEM;
  2432. break;
  2433. }
  2434. /* fill in the outfile */
  2435. if('o' == letter) {
  2436. err = getstr(&url->outfile, nextarg, DENY_BLANK);
  2437. url->flags &= ~GETOUT_USEREMOTE; /* switch off */
  2438. }
  2439. else {
  2440. url->outfile = NULL; /* leave it */
  2441. if(toggle)
  2442. url->flags |= GETOUT_USEREMOTE; /* switch on */
  2443. else
  2444. url->flags &= ~GETOUT_USEREMOTE; /* switch off */
  2445. }
  2446. url->flags |= GETOUT_OUTFILE;
  2447. break;
  2448. case C_FTP_PORT: /* --ftp-port */
  2449. /* This makes the FTP sessions use PORT instead of PASV */
  2450. /* use <eth0> or <192.168.10.10> style addresses. Anything except
  2451. this will make us try to get the "default" address.
  2452. NOTE: this is a changed behavior since the released 4.1!
  2453. */
  2454. err = getstr(&config->ftpport, nextarg, DENY_BLANK);
  2455. break;
  2456. case C_PROXYTUNNEL: /* --proxytunnel */
  2457. /* proxy tunnel for non-http protocols */
  2458. config->proxytunnel = toggle;
  2459. break;
  2460. case C_DISABLE: /* --disable */
  2461. /* if used first, already taken care of, we do it like this so we don't
  2462. cause an error! */
  2463. break;
  2464. case C_QUOTE: /* --quote */
  2465. /* QUOTE command to send to FTP server */
  2466. switch(nextarg[0]) {
  2467. case '-':
  2468. /* prefixed with a dash makes it a POST TRANSFER one */
  2469. nextarg++;
  2470. err = add2list(&config->postquote, nextarg);
  2471. break;
  2472. case '+':
  2473. /* prefixed with a plus makes it a just-before-transfer one */
  2474. nextarg++;
  2475. err = add2list(&config->prequote, nextarg);
  2476. break;
  2477. default:
  2478. err = add2list(&config->quote, nextarg);
  2479. break;
  2480. }
  2481. break;
  2482. case C_RANGE: /* --range */
  2483. /* Specifying a range WITHOUT A DASH will create an illegal HTTP range
  2484. (and won't actually be range by definition). The man page previously
  2485. claimed that to be a good way, why this code is added to work-around
  2486. it. */
  2487. if(ISDIGIT(*nextarg) && !strchr(nextarg, '-')) {
  2488. char buffer[32];
  2489. if(curlx_strtoofft(nextarg, NULL, 10, &value)) {
  2490. warnf(global, "unsupported range point");
  2491. err = PARAM_BAD_USE;
  2492. }
  2493. else {
  2494. warnf(global,
  2495. "A specified range MUST include at least one dash (-). "
  2496. "Appending one for you");
  2497. msnprintf(buffer, sizeof(buffer), "%" CURL_FORMAT_CURL_OFF_T "-",
  2498. value);
  2499. Curl_safefree(config->range);
  2500. config->range = strdup(buffer);
  2501. if(!config->range)
  2502. err = PARAM_NO_MEM;
  2503. }
  2504. }
  2505. else {
  2506. /* byte range requested */
  2507. const char *tmp_range = nextarg;
  2508. while(*tmp_range) {
  2509. if(!ISDIGIT(*tmp_range) && *tmp_range != '-' && *tmp_range != ',') {
  2510. warnf(global, "Invalid character is found in given range. "
  2511. "A specified range MUST have only digits in "
  2512. "\'start\'-\'stop\'. The server's response to this "
  2513. "request is uncertain.");
  2514. break;
  2515. }
  2516. tmp_range++;
  2517. }
  2518. err = getstr(&config->range, nextarg, DENY_BLANK);
  2519. }
  2520. break;
  2521. case C_REMOTE_TIME: /* --remote-time */
  2522. /* use remote file's time */
  2523. config->remote_time = toggle;
  2524. break;
  2525. case C_SILENT: /* --silent */
  2526. global->silent = toggle;
  2527. break;
  2528. case C_SHOW_ERROR: /* --show-error */
  2529. global->showerror = toggle;
  2530. break;
  2531. case C_TELNET_OPTION: /* --telnet-option */
  2532. /* Telnet options */
  2533. err = add2list(&config->telnet_options, nextarg);
  2534. break;
  2535. case C_UPLOAD_FILE: /* --upload-file */
  2536. /* we are uploading */
  2537. if(!config->url_ul)
  2538. config->url_ul = config->url_list;
  2539. if(config->url_ul) {
  2540. /* there's a node here, if it already is filled-in continue to find
  2541. an "empty" node */
  2542. while(config->url_ul && (config->url_ul->flags & GETOUT_UPLOAD))
  2543. config->url_ul = config->url_ul->next;
  2544. }
  2545. /* now there might or might not be an available node to fill in! */
  2546. if(config->url_ul)
  2547. /* existing node */
  2548. url = config->url_ul;
  2549. else
  2550. /* there was no free node, create one! */
  2551. config->url_ul = url = new_getout(config);
  2552. if(!url) {
  2553. err = PARAM_NO_MEM;
  2554. break;
  2555. }
  2556. url->flags |= GETOUT_UPLOAD; /* mark -T used */
  2557. if(!*nextarg)
  2558. url->flags |= GETOUT_NOUPLOAD;
  2559. else {
  2560. /* "-" equals stdin, but keep the string around for now */
  2561. err = getstr(&url->infile, nextarg, DENY_BLANK);
  2562. }
  2563. break;
  2564. case C_USER: /* --user */
  2565. /* user:password */
  2566. err = getstr(&config->userpwd, nextarg, ALLOW_BLANK);
  2567. cleanarg(clearthis);
  2568. break;
  2569. case C_PROXY_USER: /* --proxy-user */
  2570. /* Proxy user:password */
  2571. err = getstr(&config->proxyuserpwd, nextarg, ALLOW_BLANK);
  2572. cleanarg(clearthis);
  2573. break;
  2574. case C_VERBOSE: /* --verbose */
  2575. if(toggle) {
  2576. /* the '%' thing here will cause the trace get sent to stderr */
  2577. Curl_safefree(global->trace_dump);
  2578. global->trace_dump = strdup("%");
  2579. if(!global->trace_dump)
  2580. err = PARAM_NO_MEM;
  2581. else {
  2582. if(global->tracetype && (global->tracetype != TRACE_PLAIN))
  2583. warnf(global,
  2584. "-v, --verbose overrides an earlier trace/verbose option");
  2585. global->tracetype = TRACE_PLAIN;
  2586. }
  2587. }
  2588. else
  2589. /* verbose is disabled here */
  2590. global->tracetype = TRACE_NONE;
  2591. break;
  2592. case C_VERSION: /* --version */
  2593. if(toggle) /* --no-version yields no output! */
  2594. err = PARAM_VERSION_INFO_REQUESTED;
  2595. break;
  2596. case C_WRITE_OUT: /* --write-out */
  2597. /* get the output string */
  2598. if('@' == *nextarg) {
  2599. /* the data begins with a '@' letter, it means that a file name
  2600. or - (stdin) follows */
  2601. FILE *file;
  2602. const char *fname;
  2603. nextarg++; /* pass the @ */
  2604. if(!strcmp("-", nextarg)) {
  2605. fname = "<stdin>";
  2606. file = stdin;
  2607. }
  2608. else {
  2609. fname = nextarg;
  2610. file = fopen(fname, FOPEN_READTEXT);
  2611. if(!file) {
  2612. errorf(global, "Failed to open %s", fname);
  2613. err = PARAM_READ_ERROR;
  2614. break;
  2615. }
  2616. }
  2617. Curl_safefree(config->writeout);
  2618. err = file2string(&config->writeout, file);
  2619. if(file && (file != stdin))
  2620. fclose(file);
  2621. if(err)
  2622. break;
  2623. if(!config->writeout)
  2624. warnf(global, "Failed to read %s", fname);
  2625. }
  2626. else
  2627. err = getstr(&config->writeout, nextarg, ALLOW_BLANK);
  2628. break;
  2629. case C_PREPROXY: /* --preproxy */
  2630. err = getstr(&config->preproxy, nextarg, DENY_BLANK);
  2631. break;
  2632. case C_PROXY: /* --proxy */
  2633. /* --proxy */
  2634. err = getstr(&config->proxy, nextarg, ALLOW_BLANK);
  2635. if(config->proxyver != CURLPROXY_HTTPS2)
  2636. config->proxyver = CURLPROXY_HTTP;
  2637. break;
  2638. case C_REQUEST: /* --request */
  2639. /* set custom request */
  2640. err = getstr(&config->customrequest, nextarg, DENY_BLANK);
  2641. break;
  2642. case C_SPEED_TIME: /* --speed-time */
  2643. /* low speed time */
  2644. err = str2unum(&config->low_speed_time, nextarg);
  2645. if(!err && !config->low_speed_limit)
  2646. config->low_speed_limit = 1;
  2647. break;
  2648. case C_SPEED_LIMIT: /* --speed-limit */
  2649. /* low speed limit */
  2650. err = str2unum(&config->low_speed_limit, nextarg);
  2651. if(!err && !config->low_speed_time)
  2652. config->low_speed_time = 30;
  2653. break;
  2654. case C_PARALLEL: /* --parallel */
  2655. global->parallel = toggle;
  2656. break;
  2657. case C_PARALLEL_MAX: { /* --parallel-max */
  2658. long val;
  2659. err = str2unum(&val, nextarg);
  2660. if(err)
  2661. break;
  2662. if(val > MAX_PARALLEL)
  2663. global->parallel_max = MAX_PARALLEL;
  2664. else if(val < 1)
  2665. global->parallel_max = PARALLEL_DEFAULT;
  2666. else
  2667. global->parallel_max = (unsigned short)val;
  2668. break;
  2669. }
  2670. case C_PARALLEL_IMMEDIATE: /* --parallel-immediate */
  2671. global->parallel_connect = toggle;
  2672. break;
  2673. case C_TIME_COND: /* --time-cond */
  2674. switch(*nextarg) {
  2675. case '+':
  2676. nextarg++;
  2677. FALLTHROUGH();
  2678. default:
  2679. /* If-Modified-Since: (section 14.28 in RFC2068) */
  2680. config->timecond = CURL_TIMECOND_IFMODSINCE;
  2681. break;
  2682. case '-':
  2683. /* If-Unmodified-Since: (section 14.24 in RFC2068) */
  2684. config->timecond = CURL_TIMECOND_IFUNMODSINCE;
  2685. nextarg++;
  2686. break;
  2687. case '=':
  2688. /* Last-Modified: (section 14.29 in RFC2068) */
  2689. config->timecond = CURL_TIMECOND_LASTMOD;
  2690. nextarg++;
  2691. break;
  2692. }
  2693. now = time(NULL);
  2694. config->condtime = (curl_off_t)curl_getdate(nextarg, &now);
  2695. if(-1 == config->condtime) {
  2696. /* now let's see if it is a file name to get the time from instead! */
  2697. rc = getfiletime(nextarg, global, &value);
  2698. if(!rc)
  2699. /* pull the time out from the file */
  2700. config->condtime = value;
  2701. else {
  2702. /* failed, remove time condition */
  2703. config->timecond = CURL_TIMECOND_NONE;
  2704. warnf(global,
  2705. "Illegal date format for -z, --time-cond (and not "
  2706. "a file name). Disabling time condition. "
  2707. "See curl_getdate(3) for valid date syntax.");
  2708. }
  2709. }
  2710. break;
  2711. default: /* unknown flag */
  2712. err = PARAM_OPTION_UNKNOWN;
  2713. break;
  2714. }
  2715. a = NULL;
  2716. } while(!longopt && !singleopt && *++parse && !*usedarg && !err);
  2717. error:
  2718. if(nextalloc)
  2719. free(nextarg);
  2720. return err;
  2721. }
  2722. ParameterError parse_args(struct GlobalConfig *global, int argc,
  2723. argv_item_t argv[])
  2724. {
  2725. int i;
  2726. bool stillflags;
  2727. char *orig_opt = NULL;
  2728. ParameterError result = PARAM_OK;
  2729. struct OperationConfig *config = global->first;
  2730. for(i = 1, stillflags = TRUE; i < argc && !result; i++) {
  2731. orig_opt = curlx_convert_tchar_to_UTF8(argv[i]);
  2732. if(!orig_opt)
  2733. return PARAM_NO_MEM;
  2734. if(stillflags && ('-' == orig_opt[0])) {
  2735. bool passarg;
  2736. if(!strcmp("--", orig_opt))
  2737. /* This indicates the end of the flags and thus enables the
  2738. following (URL) argument to start with -. */
  2739. stillflags = FALSE;
  2740. else {
  2741. char *nextarg = NULL;
  2742. if(i < (argc - 1)) {
  2743. nextarg = curlx_convert_tchar_to_UTF8(argv[i + 1]);
  2744. if(!nextarg) {
  2745. curlx_unicodefree(orig_opt);
  2746. return PARAM_NO_MEM;
  2747. }
  2748. }
  2749. result = getparameter(orig_opt, nextarg, argv[i + 1], &passarg,
  2750. global, config);
  2751. curlx_unicodefree(nextarg);
  2752. config = global->last;
  2753. if(result == PARAM_NEXT_OPERATION) {
  2754. /* Reset result as PARAM_NEXT_OPERATION is only used here and not
  2755. returned from this function */
  2756. result = PARAM_OK;
  2757. if(config->url_list && config->url_list->url) {
  2758. /* Allocate the next config */
  2759. config->next = malloc(sizeof(struct OperationConfig));
  2760. if(config->next) {
  2761. /* Initialise the newly created config */
  2762. config_init(config->next);
  2763. /* Set the global config pointer */
  2764. config->next->global = global;
  2765. /* Update the last config pointer */
  2766. global->last = config->next;
  2767. /* Move onto the new config */
  2768. config->next->prev = config;
  2769. config = config->next;
  2770. }
  2771. else
  2772. result = PARAM_NO_MEM;
  2773. }
  2774. else {
  2775. errorf(global, "missing URL before --next");
  2776. result = PARAM_BAD_USE;
  2777. }
  2778. }
  2779. else if(!result && passarg)
  2780. i++; /* we're supposed to skip this */
  2781. }
  2782. }
  2783. else {
  2784. bool used;
  2785. /* Just add the URL please */
  2786. result = getparameter("--url", orig_opt, argv[i], &used, global, config);
  2787. }
  2788. if(!result)
  2789. curlx_unicodefree(orig_opt);
  2790. }
  2791. if(!result && config->content_disposition) {
  2792. if(config->show_headers)
  2793. result = PARAM_CONTDISP_SHOW_HEADER;
  2794. else if(config->resume_from_current)
  2795. result = PARAM_CONTDISP_RESUME_FROM;
  2796. }
  2797. if(result && result != PARAM_HELP_REQUESTED &&
  2798. result != PARAM_MANUAL_REQUESTED &&
  2799. result != PARAM_VERSION_INFO_REQUESTED &&
  2800. result != PARAM_ENGINES_REQUESTED) {
  2801. const char *reason = param2text(result);
  2802. if(orig_opt && strcmp(":", orig_opt))
  2803. helpf(tool_stderr, "option %s: %s", orig_opt, reason);
  2804. else
  2805. helpf(tool_stderr, "%s", reason);
  2806. }
  2807. curlx_unicodefree(orig_opt);
  2808. return result;
  2809. }