tool_getparam: initial --json support

Adds these test cases:

 383 - simple single command line option
 384 - reading it from stdin
 385 - getting two --json options on command line
 386 - --next works after --json

Closes #8314
This commit is contained in:
Daniel Stenberg 2022-01-21 09:38:44 +01:00
parent 1ce1f0b5a0
commit 32160cae84
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
12 changed files with 343 additions and 12 deletions

View file

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -189,6 +189,7 @@ struct OperationConfig {
bool proxydigest;
bool proxybasic;
bool proxyanyauth;
bool jsoned; /* added json content-type */
char *writeout; /* %-styled format string to output */
struct curl_slist *quote;
struct curl_slist *postquote;

View file

@ -230,6 +230,7 @@ static const struct LongShort aliases[]= {
{"da", "data-ascii", ARG_STRING},
{"db", "data-binary", ARG_STRING},
{"de", "data-urlencode", ARG_STRING},
{"df", "json", ARG_STRING},
{"D", "dump-header", ARG_FILENAME},
{"e", "referer", ARG_STRING},
{"E", "cert", ARG_FILENAME},
@ -1386,7 +1387,7 @@ 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 == 'e') { /* --data-urlencode */
/* [name]=[content], we encode the content part only
* [name]@[file name]
*
@ -1489,7 +1490,8 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
"an empty POST.\n", nextarg);
}
if(subletter == 'b')
if((subletter == 'b') || /* --data-binary */
(subletter == 'f') /* --json */)
/* forced binary */
err = file2memory(&postdata, &size, file);
else {
@ -1516,6 +1518,8 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
if(postdata)
size = strlen(postdata);
}
if(subletter == 'f')
config->jsoned = TRUE;
#ifdef CURL_DOES_CONVERSIONS
if(subletter != 'b') {
@ -1540,13 +1544,21 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
return PARAM_NO_MEM;
}
memcpy(config->postfields, oldpost, (size_t)oldlen);
/* use byte value 0x26 for '&' to accommodate non-ASCII platforms */
config->postfields[oldlen] = '\x26';
memcpy(&config->postfields[oldlen + 1], postdata, size);
config->postfields[oldlen + 1 + size] = '\0';
if(subletter != 'f') {
/* skip this treatment for --json */
/* use byte value 0x26 for '&' to accommodate non-ASCII platforms */
config->postfields[oldlen] = '\x26';
memcpy(&config->postfields[oldlen + 1], postdata, size);
config->postfields[oldlen + 1 + size] = '\0';
config->postfieldsize += size + 1;
}
else {
memcpy(&config->postfields[oldlen], postdata, size);
config->postfields[oldlen + size] = '\0';
config->postfieldsize += size;
}
Curl_safefree(oldpost);
Curl_safefree(postdata);
config->postfieldsize += size + 1;
}
else {
config->postfields = postdata;
@ -2367,6 +2379,7 @@ ParameterError parse_args(struct GlobalConfig *global, int argc,
: NULL;
result = getparameter(orig_opt, nextarg, &passarg, global, config);
curlx_unicodefree(nextarg);
config = global->last;
if(result == PARAM_NEXT_OPERATION) {

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel.se>, et al.
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -298,6 +298,9 @@ const struct helptxt helptext[] = {
{"-6, --ipv6",
"Resolve names to IPv6 addresses",
CURLHELP_CONNECTION | CURLHELP_DNS},
{" --json <data>",
"HTTP POST JSON",
CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD},
{"-j, --junk-session-cookies",
"Ignore session cookies read from file",
CURLHELP_HTTP},

View file

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -548,11 +548,45 @@ static char *my_useragent(void)
return strdup(CURL_NAME "/" CURL_VERSION);
}
#define isheadersep(x) ((((x)==':') || ((x)==';')))
/*
* inlist() returns true if the given 'checkfor' header is present in the
* header list.
*/
static bool inlist(const struct curl_slist *head,
const char *checkfor)
{
size_t thislen = strlen(checkfor);
DEBUGASSERT(thislen);
DEBUGASSERT(checkfor[thislen-1] != ':');
for(; head; head = head->next) {
if(curl_strnequal(head->data, checkfor, thislen) &&
isheadersep(head->data[thislen]) )
return TRUE;
}
return FALSE;
}
CURLcode get_args(struct OperationConfig *config, const size_t i)
{
CURLcode result = CURLE_OK;
bool last = (config->next ? FALSE : TRUE);
if(config->jsoned) {
ParameterError err = PARAM_OK;
/* --json also implies json Content-Type: and Accept: headers - if
they are not set with -H */
if(!inlist(config->headers, "Content-Type"))
err = add2list(&config->headers, "Content-Type: application/json");
if(!err && !inlist(config->headers, "Accept"))
err = add2list(&config->headers, "Accept: application/json");
if(err)
return CURLE_OUT_OF_MEMORY;
}
/* Check we have a password for the given host user */
if(config->userpwd && !config->oauth_bearer) {
result = checkpasswd("host", i, last, &config->userpwd);