From a6e8ead533efca3d0066c1b5150ef4f421584be0 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 22 Feb 2025 10:49:19 +0100 Subject: [PATCH] var: add a '64dec' function that can base64 decode a string Verified in test 455 and 487. If the provided string cannot be base64-decoded, it will instead use "[64dec-fail]" (without the quotes). Documented Ref: #16288 Closes #16330 --- docs/cmdline-opts/_VARIABLES.md | 8 ++--- docs/cmdline-opts/variable.md | 23 ++++++++++++--- src/var.c | 23 +++++++++++++++ tests/data/Makefile.am | 2 +- tests/data/test455 | 4 +-- tests/data/test487 | 52 +++++++++++++++++++++++++++++++++ 6 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 tests/data/test487 diff --git a/docs/cmdline-opts/_VARIABLES.md b/docs/cmdline-opts/_VARIABLES.md index e46b6755310c..62b56ca38cb8 100644 --- a/docs/cmdline-opts/_VARIABLES.md +++ b/docs/cmdline-opts/_VARIABLES.md @@ -27,10 +27,10 @@ set: When expanding variables, curl supports a set of functions that can make the variable contents more convenient to use. It can trim leading and trailing white space with `trim`, it can output the contents as a JSON quoted string -with `json`, URL encode the string with `url` or base64 encode it with `b64`. -To apply functions to a variable expansion, add them colon separated to the -right side of the variable. Variable content holding null bytes that are not -encoded when expanded cause error. +with `json`, URL encode the string with `url`, base64 encode it with `b64` and +base64 decode it with `64dec`. To apply functions to a variable expansion, add +them colon separated to the right side of the variable. Variable content +holding null bytes that are not encoded when expanded cause error. Example: get the contents of a file called $HOME/.secret into a variable called "fix". Make sure that the content is trimmed and percent-encoded when diff --git a/docs/cmdline-opts/variable.md b/docs/cmdline-opts/variable.md index 1a0e70e2090c..13b8d5c5d77d 100644 --- a/docs/cmdline-opts/variable.md +++ b/docs/cmdline-opts/variable.md @@ -66,30 +66,45 @@ error. Available functions: -## trim +## `trim` + removes all leading and trailing white space. Example: curl --expand-url https://example.com/{{var:trim}} -## json +## `json` + outputs the content using JSON string quoting rules. Example: curl --expand-data {{data:json}} https://example.com -## url +## `url` + shows the content URL (percent) encoded. Example: curl --expand-url https://example.com/{{path:url}} -## b64 +## `b64` + expands the variable base64 encoded Example: curl --expand-url https://example.com/{{var:b64}} + +## `64dec` + +decodes a base64 encoded character sequence. If the sequence is not possible +to decode, it instead outputs `[64dec-fail]` + +Example: + + curl --expand-url https://example.com/{{var:64dec}} + +(Added in 8.13.0) diff --git a/src/var.c b/src/var.c index f4b221e74a1a..5ac75068911d 100644 --- a/src/var.c +++ b/src/var.c @@ -91,6 +91,8 @@ static const struct tool_var *varcontent(struct GlobalConfig *global, #define FUNC_URL_LEN (sizeof(FUNC_URL) - 1) #define FUNC_B64 "b64" #define FUNC_B64_LEN (sizeof(FUNC_B64) - 1) +#define FUNC_64DEC "64dec" /* base64 decode */ +#define FUNC_64DEC_LEN (sizeof(FUNC_64DEC) - 1) static ParameterError varfunc(struct GlobalConfig *global, char *c, /* content */ @@ -179,6 +181,27 @@ static ParameterError varfunc(struct GlobalConfig *global, break; } } + else if(FUNCMATCH(f, FUNC_64DEC, FUNC_64DEC_LEN)) { + f += FUNC_64DEC_LEN; + curlx_dyn_reset(out); + if(clen) { + unsigned char *enc; + size_t elen; + CURLcode result = curlx_base64_decode(c, &enc, &elen); + /* put it in the output */ + if(result) { + if(curlx_dyn_add(out, "[64dec-fail]")) + err = PARAM_NO_MEM; + } + else { + if(curlx_dyn_addn(out, enc, elen)) + err = PARAM_NO_MEM; + curl_free(enc); + } + if(err) + break; + } + } else { /* unsupported function */ errorf(global, "unknown variable function in '%.*s'", diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 01fbe9b23e35..6ce2879e9acc 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -78,7 +78,7 @@ test444 test445 test446 test447 test448 test449 test450 test451 test452 \ test453 test454 test455 test456 test457 test458 test459 test460 test461 \ test462 test463 test467 test468 test469 test470 test471 test472 test473 \ test474 test475 test476 test477 test478 test479 test480 test481 test482 \ -test483 test484 test485 test486 \ +test483 test484 test485 test486 test487 \ test490 test491 test492 test493 test494 test495 test496 test497 test498 \ test499 test500 test501 test502 test503 test504 test505 test506 test507 \ test508 test509 test510 test511 test512 test513 test514 test515 test516 \ diff --git a/tests/data/test455 b/tests/data/test455 index ffe6bd14c14d..7e468e75243b 100644 --- a/tests/data/test455 +++ b/tests/data/test455 @@ -34,7 +34,7 @@ http Variable using base64 ---variable moby="Call me Ishmael" --expand-url "http://%HOSTIP:%HTTPPORT/{{moby:b64}}/%TESTNUMBER" +--variable moby="Call me Ishmael" --variable what=%b64[white-whale]b64% --expand-url "http://%HOSTIP:%HTTPPORT/{{moby:b64}}/{{what:64dec}}/%TESTNUMBER" @@ -42,7 +42,7 @@ Variable using base64 # Verify data after the test has been "shot" -GET /%b64[Call me Ishmael]b64%/%TESTNUMBER HTTP/1.1 +GET /%b64[Call me Ishmael]b64%/white-whale/%TESTNUMBER HTTP/1.1 Host: %HOSTIP:%HTTPPORT User-Agent: curl/%VERSION Accept: */* diff --git a/tests/data/test487 b/tests/data/test487 new file mode 100644 index 000000000000..3ac508b2e54f --- /dev/null +++ b/tests/data/test487 @@ -0,0 +1,52 @@ + + + +variables + + + +# +# Server-side + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT +ETag: "21025-dc7-39462498" +Accept-Ranges: bytes +Content-Length: 6 +Connection: close +Content-Type: text/html +Funny-head: yesyes + +-foo- + + + +# +# Client-side + + +http + + +Variable using 64dec with bad base64 + + +--variable what=not-base64-data --expand-url "http://%HOSTIP:%HTTPPORT/{{what:64dec}}/%TESTNUMBER" -g + + + +# +# Verify data after the test has been "shot" + + +GET /[64dec-fail]/%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: curl/%VERSION +Accept: */* + + + +