diff --git a/src/tool_writeout.c b/src/tool_writeout.c index 6ff45b9be295d7..6879a98c264d7b 100644 --- a/src/tool_writeout.c +++ b/src/tool_writeout.c @@ -57,14 +57,17 @@ static const char *http_version[] = { with exceptions special cased in the respective function. For example, http_version uses CURLINFO_HTTP_VERSION which returns the version as a long, however it is output as a string and therefore is handled in writeString. + Yes: "http_version": "1.1" No: "http_version": 1.1 + + Variable names should be in alphabetical order. */ static const struct writeoutvar variables[] = { {"content_type", VAR_CONTENT_TYPE, 0, CURLINFO_CONTENT_TYPE, writeString}, - {"filename_effective", VAR_EFFECTIVE_FILENAME, 0, 0, writeString}, - {"exitcode", VAR_EXITCODE, 0, 0, writeLong}, {"errormsg", VAR_ERRORMSG, 0, 0, writeString}, + {"exitcode", VAR_EXITCODE, 0, 0, writeLong}, + {"filename_effective", VAR_EFFECTIVE_FILENAME, 0, 0, writeString}, {"ftp_entry_path", VAR_FTP_ENTRY_PATH, 0, CURLINFO_FTP_ENTRY_PATH, writeString}, {"http_code", VAR_HTTP_CODE, 0, CURLINFO_RESPONSE_CODE, writeLong}, @@ -111,7 +114,7 @@ static const struct writeoutvar variables[] = { {"time_total", VAR_TOTAL_TIME, 0, CURLINFO_TOTAL_TIME_T, writeTime}, {"url", VAR_INPUT_URL, 0, 0, writeString}, {"url_effective", VAR_EFFECTIVE_URL, 0, CURLINFO_EFFECTIVE_URL, writeString}, - {"urlnum", VAR_URLNUM, 0, 0, writeOffset}, + {"urlnum", VAR_URLNUM, 0, 0, writeLong}, {NULL, VAR_NONE, 1, 0, NULL} }; @@ -120,23 +123,37 @@ static int writeTime(FILE *stream, const struct writeoutvar *wovar, struct per_transfer *per, CURLcode per_result, bool use_json) { + bool valid = false; curl_off_t us = 0; + (void)per; (void)per_result; - DEBUGASSERT(wovar->writefunc == writeTime); - if(use_json) - fprintf(stream, "\"%s\":", wovar->name); - if(!curl_easy_getinfo(per->curl, wovar->ci, &us)) { + DEBUGASSERT(wovar->is_ctrl == 0 && wovar->writefunc == writeTime); + + if(wovar->ci) { + if(!curl_easy_getinfo(per->curl, wovar->ci, &us)) + valid = true; + } + else { + DEBUGASSERT(0); + } + + if(valid) { curl_off_t secs = us / 1000000; us %= 1000000; + + if(use_json) + fprintf(stream, "\"%s\":", wovar->name); + fprintf(stream, "%" CURL_FORMAT_CURL_OFF_TU ".%06" CURL_FORMAT_CURL_OFF_TU, secs, us); } else { if(use_json) - fprintf(stream, "null"); + fprintf(stream, "\"%s\":null", wovar->name); } - return 1; + + return 1; /* return 1 if anything was written */ } /* write functions must return 1 if anything was written */ @@ -144,19 +161,25 @@ static int writeString(FILE *stream, const struct writeoutvar *wovar, struct per_transfer *per, CURLcode per_result, bool use_json) { + bool valid = false; const char *strinfo = NULL; - DEBUGASSERT(wovar->writefunc == writeString); - if(wovar->ci == CURLINFO_HTTP_VERSION) { - long version = 0; - if(!curl_easy_getinfo(per->curl, CURLINFO_HTTP_VERSION, &version) && - (version >= 0) && - (version < (long)(sizeof(http_version)/sizeof(http_version[0])))) { - strinfo = http_version[version]; + + DEBUGASSERT(wovar->is_ctrl == 0 && wovar->writefunc == writeString); + + if(wovar->ci) { + if(wovar->ci == CURLINFO_HTTP_VERSION) { + long version = 0; + if(!curl_easy_getinfo(per->curl, CURLINFO_HTTP_VERSION, &version) && + (version >= 0) && + (version < (long)(sizeof(http_version)/sizeof(http_version[0])))) { + strinfo = http_version[version]; + valid = true; + } + } + else { + if(!curl_easy_getinfo(per->curl, wovar->ci, &strinfo) && strinfo) + valid = true; } - } - else if(wovar->ci) { - if(curl_easy_getinfo(per->curl, wovar->ci, &strinfo)) - strinfo = NULL; } else { switch(wovar->id) { @@ -164,31 +187,38 @@ static int writeString(FILE *stream, const struct writeoutvar *wovar, if(per_result) { strinfo = per->errorbuffer[0] ? per->errorbuffer : curl_easy_strerror(per_result); + valid = true; } break; case VAR_EFFECTIVE_FILENAME: strinfo = per->outs.filename; + valid = true; break; case VAR_INPUT_URL: strinfo = per->this_url; + valid = true; break; default: - return 0; + DEBUGASSERT(0); + break; } } - if(use_json) { - fprintf(stream, "\"%s\":", wovar->name); - if(strinfo) { - fprintf(stream, "\""); + + if(valid) { + if(use_json) { + fprintf(stream, "\"%s\":\"", wovar->name); jsonWriteString(stream, strinfo); - fprintf(stream, "\""); + fputs("\"", stream); } else - fprintf(stream, "null"); + fputs(strinfo, stream); + } + else { + if(use_json) + fprintf(stream, "\"%s\":null", wovar->name); } - else - fputs(strinfo, stream); - return 1; + + return 1; /* return 1 if anything was written */ } /* write functions must return 1 if anything was written */ @@ -196,53 +226,85 @@ static int writeLong(FILE *stream, const struct writeoutvar *wovar, struct per_transfer *per, CURLcode per_result, bool use_json) { + bool valid = false; long longinfo = 0; - DEBUGASSERT(wovar->writefunc == writeLong); + + DEBUGASSERT(wovar->is_ctrl == 0 && wovar->writefunc == writeLong); + if(wovar->ci) { - curl_easy_getinfo(per->curl, wovar->ci, &longinfo); + if(!curl_easy_getinfo(per->curl, wovar->ci, &longinfo)) + valid = true; } else { switch(wovar->id) { case VAR_NUM_HEADERS: longinfo = per->num_headers; + valid = true; break; case VAR_EXITCODE: longinfo = per_result; + valid = true; break; case VAR_URLNUM: - if(per->urlnum > LONG_MAX) - return 0; - longinfo = (long)per->urlnum; + if(per->urlnum <= LONG_MAX) { + longinfo = (long)per->urlnum; + valid = true; + } + break; default: - return 0; + DEBUGASSERT(0); + break; } } - if(use_json) - fprintf(stream, "\"%s\":", wovar->name); - - if(wovar->id == VAR_HTTP_CODE || wovar->id == VAR_HTTP_CODE_PROXY) - fprintf(stream, "%03ld", longinfo); - else - fprintf(stream, "%ld", longinfo); - return 1; + + if(valid) { + if(use_json) + fprintf(stream, "\"%s\":", wovar->name); + + if(wovar->id == VAR_HTTP_CODE || wovar->id == VAR_HTTP_CODE_PROXY) + fprintf(stream, "%03ld", longinfo); + else + fprintf(stream, "%ld", longinfo); + } + else { + if(use_json) + fprintf(stream, "\"%s\":null", wovar->name); + } + + return 1; /* return 1 if anything was written */ } -/* write functions must return 1 if anything was written */ static int writeOffset(FILE *stream, const struct writeoutvar *wovar, struct per_transfer *per, CURLcode per_result, bool use_json) { + bool valid = false; curl_off_t offinfo = 0; + (void)per; (void)per_result; - DEBUGASSERT(wovar->writefunc == writeOffset); - if(wovar->ci && !curl_easy_getinfo(per->curl, wovar->ci, &offinfo)) { + DEBUGASSERT(wovar->is_ctrl == 0 && wovar->writefunc == writeOffset); + + if(wovar->ci) { + if(!curl_easy_getinfo(per->curl, wovar->ci, &offinfo)) + valid = true; + } + else { + DEBUGASSERT(0); + } + + if(valid) { if(use_json) fprintf(stream, "\"%s\":", wovar->name); + fprintf(stream, "%" CURL_FORMAT_CURL_OFF_T, offinfo); - return 1; } - return 0; + else { + if(use_json) + fprintf(stream, "\"%s\":null", wovar->name); + } + + return 1; /* return 1 if anything was written */ } void ourWriteOut(const char *writeinfo, struct per_transfer *per, @@ -293,8 +355,8 @@ void ourWriteOut(const char *writeinfo, struct per_transfer *per, ourWriteOutJSON(stream, variables, per, per_result); break; default: - variables[i].writefunc(stream, &variables[i], per, per_result, - false); + (void)variables[i].writefunc(stream, &variables[i], + per, per_result, false); break; } break; diff --git a/src/tool_writeout_json.c b/src/tool_writeout_json.c index b4e53d9bc2305a..f8f38146ee94b6 100644 --- a/src/tool_writeout_json.c +++ b/src/tool_writeout_json.c @@ -76,19 +76,16 @@ void ourWriteOutJSON(FILE *stream, const struct writeoutvar mappings[], int i; fputs("{", stream); - for(i = 0; mappings[i].name != NULL; i++) { - int ok = 0; - if(mappings[i].is_ctrl == 1) + for(i = 0; mappings[i].name != NULL; i++) { + if(mappings[i].is_ctrl) continue; - - ok = mappings[i].writefunc(stream, &mappings[i], per, per_result, true); - - if(ok) { + if(mappings[i].writefunc(stream, &mappings[i], per, per_result, true)) fputs(",", stream); - } } + /* The variables are sorted in alphabetical order but as a special case + curl_version (which is not actually a --write-out variable) is last. */ fprintf(stream, "\"curl_version\":\""); jsonWriteString(stream, curl_version()); fprintf(stream, "\"}");