From: Daniel Stenberg Date: Fri, 4 Nov 2022 23:10:24 +0000 (+0100) Subject: curl: add --url-query X-Git-Tag: curl-7_87_0~188 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b6e1afd069f0a621b21bf27a461dc5297ce30031;p=thirdparty%2Fcurl.git curl: add --url-query This option adds a piece of data, usually a name + value pair, to the end of the URL query part. The syntax is identical to that used for --data-urlencode with one extension: If the argument starts with a '+' (plus), the rest of the string is provided as-is unencoded. This allows users to "build" query parts with options and URL encoding even when not doing GET requests, which the already provided option -G (--get) is limited to. This idea was born in a Twitter thread. Closes #9691 --- diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc index 350fa9fa7c..4f83bdc960 100644 --- a/docs/cmdline-opts/Makefile.inc +++ b/docs/cmdline-opts/Makefile.inc @@ -265,6 +265,7 @@ DPAGES = \ unix-socket.d \ upload-file.d \ url.d \ + url-query.d \ use-ascii.d \ user-agent.d \ user.d \ diff --git a/docs/cmdline-opts/url-query.d b/docs/cmdline-opts/url-query.d new file mode 100644 index 0000000000..c74b4fb393 --- /dev/null +++ b/docs/cmdline-opts/url-query.d @@ -0,0 +1,25 @@ +c: Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. +SPDX-License-Identifier: curl +Long: url-query +Arg: +Help: Add a URL query part +Protocols: all +See-also: data-urlencode get +Added: 7.87.0 +Category: http post upload +Example: --url-query name=val $URL +Example: --url-query =encodethis http://example.net/foo +Example: --url-query name@file $URL +Example: --url-query @fileonly $URL +Example: --url-query "+name=%20foo" $URL +Multi: append +--- +This option adds a piece of data, usually a name + value pair, to the end of +the URL query part. The syntax is identical to that used for --data-urlencode +with one extension: + +If the argument starts with a '+' (plus), the rest of the string is provided +as-is unencoded. + +The query part of a URL is the one following the question mark on the right +end. diff --git a/docs/options-in-versions b/docs/options-in-versions index a6c75cfd09..8e64f2f3fe 100644 --- a/docs/options-in-versions +++ b/docs/options-in-versions @@ -251,6 +251,7 @@ --unix-socket 7.40.0 --upload-file (-T) 4.0 --url 7.5 +--url-query 7.87.0 --use-ascii (-B) 5.0 --user (-u) 4.0 --user-agent (-A) 4.5.1 diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c index eccb3bcb59..8d347fb54b 100644 --- a/src/tool_cfgable.c +++ b/src/tool_cfgable.c @@ -58,6 +58,7 @@ static void free_config_fields(struct OperationConfig *config) curl_slist_free_all(config->cookiefiles); Curl_safefree(config->postfields); + Curl_safefree(config->query); Curl_safefree(config->referer); Curl_safefree(config->headerfile); diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index 232c26f654..d8347de84b 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -70,6 +70,7 @@ struct OperationConfig { char *postfields; curl_off_t postfieldsize; char *referer; + char *query; long timeout_ms; long connecttimeout_ms; long maxredirs; diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 5d021441ae..7a9d597a4c 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -41,6 +41,7 @@ #include "tool_paramhlp.h" #include "tool_parsecfg.h" #include "tool_main.h" +#include "dynbuf.h" #include "memdebug.h" /* keep this as LAST include */ @@ -233,6 +234,7 @@ static const struct LongShort aliases[]= { {"db", "data-binary", ARG_STRING}, {"de", "data-urlencode", ARG_STRING}, {"df", "json", ARG_STRING}, + {"dg", "url-query", ARG_STRING}, {"D", "dump-header", ARG_FILENAME}, {"e", "referer", ARG_STRING}, {"E", "cert", ARG_FILENAME}, @@ -1567,7 +1569,39 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ size_t size = 0; bool raw_mode = (subletter == 'r'); - if(subletter == 'e') { /* --data-urlencode */ + if(subletter == 'g') { /* --url-query */ +#define MAX_QUERY_LEN 100000 /* larger is not likely to ever work */ + char *query; + struct curlx_dynbuf dyn; + curlx_dyn_init(&dyn, MAX_QUERY_LEN); + + if(*nextarg == '+') { + /* use without encoding */ + query = strdup(&nextarg[1]); + if(!query) + return PARAM_NO_MEM; + } + else { + err = data_urlencode(global, nextarg, &query, &size); + if(err) + return err; + } + + if(config->query) { + CURLcode result = + curlx_dyn_addf(&dyn, "%s&%s", config->query, query); + free(query); + if(result) + return PARAM_NO_MEM; + free(config->query); + config->query = curlx_dyn_ptr(&dyn); + } + else + config->query = query; + + break; /* this is not a POST argument at all */ + } + else if(subletter == 'e') { /* --data-urlencode */ err = data_urlencode(global, nextarg, &postdata, &size); if(err) return err; diff --git a/src/tool_listhelp.c b/src/tool_listhelp.c index 6a2d10fb69..a0100e8cf2 100644 --- a/src/tool_listhelp.c +++ b/src/tool_listhelp.c @@ -756,6 +756,9 @@ const struct helptxt helptext[] = { {" --url ", "URL to work with", CURLHELP_CURL}, + {" --url-query ", + "Add a URL query part", + CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD}, {"-B, --use-ascii", "Use ASCII/text transfer", CURLHELP_MISC}, diff --git a/src/tool_operate.c b/src/tool_operate.c index c8509531c3..8ec2da6796 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -1189,14 +1189,14 @@ static CURLcode single_transfer(struct GlobalConfig *global, global->isatty = orig_isatty; } - if(httpgetfields) { + if(httpgetfields || config->query) { + char *q = httpgetfields ? httpgetfields : config->query; CURLU *uh = curl_url(); if(uh) { char *updated; if(curl_url_set(uh, CURLUPART_URL, per->this_url, CURLU_GUESS_SCHEME) || - curl_url_set(uh, CURLUPART_QUERY, httpgetfields, - CURLU_APPENDQUERY) || + curl_url_set(uh, CURLUPART_QUERY, q, CURLU_APPENDQUERY) || curl_url_get(uh, CURLUPART_URL, &updated, CURLU_GUESS_SCHEME)) { curl_url_cleanup(uh); result = CURLE_OUT_OF_MEMORY;