summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2022-11-05 00:10:24 +0100
committerDaniel Stenberg <daniel@haxx.se>2022-11-08 14:37:34 +0100
commitb6e1afd069f0a621b21bf27a461dc5297ce30031 (patch)
tree0c236a83c352d0506b640ed71313d3b66054ad4a /src
parent43232b59920558f4003accbb31cff5d9a9269497 (diff)
downloadcurl-b6e1afd069f0a621b21bf27a461dc5297ce30031.tar.gz
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
Diffstat (limited to 'src')
-rw-r--r--src/tool_cfgable.c1
-rw-r--r--src/tool_cfgable.h1
-rw-r--r--src/tool_getparam.c36
-rw-r--r--src/tool_listhelp.c3
-rw-r--r--src/tool_operate.c6
5 files changed, 43 insertions, 4 deletions
diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c
index eccb3bcb5..8d347fb54 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 232c26f65..d8347de84 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 5d021441a..7a9d597a4 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 6a2d10fb6..a0100e8cf 100644
--- a/src/tool_listhelp.c
+++ b/src/tool_listhelp.c
@@ -756,6 +756,9 @@ const struct helptxt helptext[] = {
{" --url <url>",
"URL to work with",
CURLHELP_CURL},
+ {" --url-query <data>",
+ "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 c8509531c..8ec2da679 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;