| /*************************************************************************** |
| * _ _ ____ _ |
| * Project ___| | | | _ \| | |
| * / __| | | | |_) | | |
| * | (__| |_| | _ <| |___ |
| * \___|\___/|_| \_\_____| |
| * |
| * Copyright (C) 1998 - 2020, 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 |
| * are also available at https://curl.haxx.se/docs/copyright.html. |
| * |
| * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
| * copies of the Software, and permit persons to whom the Software is |
| * furnished to do so, under the terms of the COPYING file. |
| * |
| * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| * KIND, either express or implied. |
| * |
| ***************************************************************************/ |
| #include "tool_setup.h" |
| |
| #define ENABLE_CURLX_PRINTF |
| |
| /* use our own printf() functions */ |
| #include "curlx.h" |
| #include "tool_cfgable.h" |
| #include "tool_writeout_json.h" |
| #include "tool_writeout.h" |
| |
| |
| static const char *http_version[] = { |
| "0", /* CURL_HTTP_VERSION_NONE */ |
| "1", /* CURL_HTTP_VERSION_1_0 */ |
| "1.1", /* CURL_HTTP_VERSION_1_1 */ |
| "2", /* CURL_HTTP_VERSION_2 */ |
| "3" /* CURL_HTTP_VERSION_3 */ |
| }; |
| |
| static void jsonEscape(FILE *stream, const char *in) |
| { |
| const char *i = in; |
| const char *in_end = in + strlen(in); |
| |
| for(; i < in_end; i++) { |
| switch(*i) { |
| case '\\': |
| fputs("\\\\", stream); |
| break; |
| case '\"': |
| fputs("\\\"", stream); |
| break; |
| case '\b': |
| fputs("\\b", stream); |
| break; |
| case '\f': |
| fputs("\\f", stream); |
| break; |
| case '\n': |
| fputs("\\n", stream); |
| break; |
| case '\r': |
| fputs("\\r", stream); |
| break; |
| case '\t': |
| fputs("\\t", stream); |
| break; |
| default: |
| if (*i < 32) { |
| fprintf(stream, "u%04x", *i); |
| } |
| else { |
| fputc(*i, stream); |
| } |
| break; |
| }; |
| } |
| } |
| |
| static int writeTime(FILE *str, CURL *curl, const char *key, CURLINFO ci) |
| { |
| curl_off_t val = 0; |
| if(CURLE_OK == curl_easy_getinfo(curl, ci, &val)) { |
| curl_off_t s = val / 1000000l; |
| curl_off_t ms = val % 1000000l; |
| fprintf(str, "\"%s\":%" CURL_FORMAT_CURL_OFF_T |
| ".%06" CURL_FORMAT_CURL_OFF_T, key, s, ms); |
| return 1; |
| } |
| return 0; |
| } |
| |
| static int writeString(FILE *str, CURL *curl, const char *key, CURLINFO ci) |
| { |
| char *valp = NULL; |
| if((CURLE_OK == curl_easy_getinfo(curl, ci, &valp)) && valp) { |
| fprintf(str, "\"%s\":\"", key); |
| jsonEscape(str, valp); |
| fprintf(str, "\""); |
| return 1; |
| } |
| return 0; |
| } |
| |
| static int writeLong(FILE *str, CURL *curl, const char *key, CURLINFO ci) |
| { |
| long val = 0; |
| if(CURLE_OK == curl_easy_getinfo(curl, ci, &val)) { |
| fprintf(str, "\"%s\":%ld", key, val); |
| return 1; |
| } |
| return 0; |
| } |
| |
| static int writeOffset(FILE *str, CURL *curl, const char *key, CURLINFO ci) |
| { |
| curl_off_t val = 0; |
| if(CURLE_OK == curl_easy_getinfo(curl, ci, &val)) { |
| fprintf(str, "\"%s\":%" CURL_FORMAT_CURL_OFF_T, key, val); |
| return 1; |
| } |
| return 0; |
| } |
| |
| static int writeFilename(FILE *str, const char *key, const char *filename) |
| { |
| if(filename) { |
| fprintf(str, "\"%s\":\"", key); |
| jsonEscape(str, filename); |
| fprintf(str, "\""); |
| } |
| else { |
| fprintf(str, "\"%s\":null", key); |
| } |
| return 1; |
| } |
| |
| static int writeVersion(FILE *str, CURL *curl, const char *key, CURLINFO ci) |
| { |
| long version = 0; |
| if(CURLE_OK == curl_easy_getinfo(curl, ci, &version) && |
| (version >= 0) && |
| (version < (long)(sizeof(http_version)/sizeof(char *)))) { |
| fprintf(str, "\"%s\":\"%s\"", key, http_version[version]); |
| return 1; |
| } |
| return 0; |
| } |
| |
| void ourWriteOutJSON(const struct writeoutvar mappings[], CURL *curl, |
| struct OutStruct *outs, FILE *stream) |
| { |
| int i; |
| |
| fputs("{", stream); |
| for(i = 0; mappings[i].name != NULL; i++) { |
| const char *name = mappings[i].name; |
| CURLINFO cinfo = mappings[i].cinfo; |
| int ok = 0; |
| |
| if(mappings[i].is_ctrl == 1) { |
| continue; |
| } |
| |
| switch(mappings[i].jsontype) { |
| case JSON_STRING: |
| ok = writeString(stream, curl, name, cinfo); |
| break; |
| case JSON_LONG: |
| ok = writeLong(stream, curl, name, cinfo); |
| break; |
| case JSON_OFFSET: |
| ok = writeOffset(stream, curl, name, cinfo); |
| break; |
| case JSON_TIME: |
| ok = writeTime(stream, curl, name, cinfo); |
| break; |
| case JSON_FILENAME: |
| ok = writeFilename(stream, name, outs->filename); |
| break; |
| case JSON_VERSION: |
| ok = writeVersion(stream, curl, name, cinfo); |
| break; |
| default: |
| break; |
| } |
| |
| if(ok) { |
| fputs(",", stream); |
| } |
| } |
| |
| fprintf(stream, "\"curl_version\":\"%s\"}", curl_version()); |
| } |