From a12ed0fa7bca1806ad7664d45f2b4e5ce92e1d94 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 27 Aug 2024 10:35:52 +0200 Subject: [PATCH] trurl: allow "control bytes" in JSON output For example when doing trurl 'http://example.org/%18' --json Adapted and extended test cases to verify. Fixes #262 Reported-by: Emanuele Torre --- tests.json | 64 +++++++++++++++++++++++++++++++++++++----------------- trurl.c | 32 +++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 22 deletions(-) diff --git a/tests.json b/tests.json index 4e2c8e98..0ca0552b 100644 --- a/tests.json +++ b/tests.json @@ -2644,27 +2644,51 @@ "returncode": 0 } }, - { - "input": { - "arguments": [ - "http://example.org/%18", - "--json" - ] - }, - "expected": { - "stdout":[ - { - "url": "http://example.org/%18", - "parts": { - "scheme": "http", - "host": "example.org" + { + "input": { + "arguments": [ + "http://example.org/%18", + "--json" + ] + }, + "expected": { + "stdout":[ + { + "url": "http://example.org/%18", + "parts": { + "scheme": "http", + "host": "example.org", + "path": "/\u0018" + } } - } - ], - "stderr": "trurl note: URL decode error, most likely because of rubbish in the input (path)\n", - "returncode": 0 - } - }, + ], + "stderr": "", + "returncode": 0 + } + }, + { + "input": { + "arguments": [ + "http://example.org/%18", + "--json", + "--urlencode" + ] + }, + "expected": { + "stdout":[ + { + "url": "http://example.org/%18", + "parts": { + "scheme": "http", + "host": "example.org", + "path": "/%18" + } + } + ], + "stderr": "", + "returncode": 0 + } + }, { "input": { "arguments": [ diff --git a/trurl.c b/trurl.c index f907baed..0fe44444 100644 --- a/trurl.c +++ b/trurl.c @@ -1120,14 +1120,42 @@ static void json(struct option *o, CURLU *uh) bool params_errors = false; for(i = 0; variables[i].name; i++) { char *part; - rc = geturlpart(o, 0, uh, variables[i].part, &part); + /* ask for the URL encoded version so that weird control characters do not + cause problems. URL decode it when push to json. */ + rc = geturlpart(o, VARMODIFIER_URLENCODED, uh, variables[i].part, &part); if(!rc) { + int olen; + char *dec = NULL; + + if(!o->urlencode) { + if(variables[i].part == CURLUPART_QUERY) { + /* query parts have '+' for space */ + char *n; + char *p = part; + do { + n = strchr(p, '+'); + if(n) { + *n = ' '; + p = n + 1; + } + } while(n); + } + + dec = curl_easy_unescape(NULL, part, 0, &olen); + if(!dec) + errorf(o, ERROR_MEM, "out of memory"); + } + if(!first) fputs(",\n", stdout); first = false; printf(" \"%s\": ", variables[i].name); - jsonString(stdout, part, strlen(part), false); + if(dec) + jsonString(stdout, dec, (size_t)olen, false); + else + jsonString(stdout, part, strlen(part), false); curl_free(part); + curl_free(dec); } else if(is_valid_trurl_error(rc)) { trurl_warnf(o, "%s (%s)", curl_url_strerror(rc), variables[i].name);