113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci#include "tool_setup.h" 2513498266Sopenharmony_ci#define ENABLE_CURLX_PRINTF 2613498266Sopenharmony_ci/* use our own printf() functions */ 2713498266Sopenharmony_ci#include "curlx.h" 2813498266Sopenharmony_ci#include "tool_cfgable.h" 2913498266Sopenharmony_ci#include "tool_writeout.h" 3013498266Sopenharmony_ci#include "tool_writeout_json.h" 3113498266Sopenharmony_ci#include "dynbuf.h" 3213498266Sopenharmony_ci 3313498266Sopenharmony_ci#include "memdebug.h" /* keep this as LAST include */ 3413498266Sopenharmony_ci 3513498266Sopenharmony_cistatic int writeTime(FILE *stream, const struct writeoutvar *wovar, 3613498266Sopenharmony_ci struct per_transfer *per, CURLcode per_result, 3713498266Sopenharmony_ci bool use_json); 3813498266Sopenharmony_ci 3913498266Sopenharmony_cistatic int writeString(FILE *stream, const struct writeoutvar *wovar, 4013498266Sopenharmony_ci struct per_transfer *per, CURLcode per_result, 4113498266Sopenharmony_ci bool use_json); 4213498266Sopenharmony_ci 4313498266Sopenharmony_cistatic int writeLong(FILE *stream, const struct writeoutvar *wovar, 4413498266Sopenharmony_ci struct per_transfer *per, CURLcode per_result, 4513498266Sopenharmony_ci bool use_json); 4613498266Sopenharmony_ci 4713498266Sopenharmony_cistatic int writeOffset(FILE *stream, const struct writeoutvar *wovar, 4813498266Sopenharmony_ci struct per_transfer *per, CURLcode per_result, 4913498266Sopenharmony_ci bool use_json); 5013498266Sopenharmony_ci 5113498266Sopenharmony_cistruct httpmap { 5213498266Sopenharmony_ci const char *str; 5313498266Sopenharmony_ci int num; 5413498266Sopenharmony_ci}; 5513498266Sopenharmony_ci 5613498266Sopenharmony_cistatic const struct httpmap http_version[] = { 5713498266Sopenharmony_ci { "0", CURL_HTTP_VERSION_NONE}, 5813498266Sopenharmony_ci { "1", CURL_HTTP_VERSION_1_0}, 5913498266Sopenharmony_ci { "1.1", CURL_HTTP_VERSION_1_1}, 6013498266Sopenharmony_ci { "2", CURL_HTTP_VERSION_2}, 6113498266Sopenharmony_ci { "3", CURL_HTTP_VERSION_3}, 6213498266Sopenharmony_ci { NULL, 0} /* end of list */ 6313498266Sopenharmony_ci}; 6413498266Sopenharmony_ci 6513498266Sopenharmony_ci/* The designated write function should be the same as the CURLINFO return type 6613498266Sopenharmony_ci with exceptions special cased in the respective function. For example, 6713498266Sopenharmony_ci http_version uses CURLINFO_HTTP_VERSION which returns the version as a long, 6813498266Sopenharmony_ci however it is output as a string and therefore is handled in writeString. 6913498266Sopenharmony_ci 7013498266Sopenharmony_ci Yes: "http_version": "1.1" 7113498266Sopenharmony_ci No: "http_version": 1.1 7213498266Sopenharmony_ci 7313498266Sopenharmony_ci Variable names should be in alphabetical order. 7413498266Sopenharmony_ci */ 7513498266Sopenharmony_cistatic const struct writeoutvar variables[] = { 7613498266Sopenharmony_ci {"certs", VAR_CERT, CURLINFO_NONE, writeString}, 7713498266Sopenharmony_ci {"content_type", VAR_CONTENT_TYPE, CURLINFO_CONTENT_TYPE, writeString}, 7813498266Sopenharmony_ci {"conn_id", VAR_CONN_ID, CURLINFO_CONN_ID, writeOffset}, 7913498266Sopenharmony_ci {"errormsg", VAR_ERRORMSG, CURLINFO_NONE, writeString}, 8013498266Sopenharmony_ci {"exitcode", VAR_EXITCODE, CURLINFO_NONE, writeLong}, 8113498266Sopenharmony_ci {"filename_effective", VAR_EFFECTIVE_FILENAME, CURLINFO_NONE, writeString}, 8213498266Sopenharmony_ci {"ftp_entry_path", VAR_FTP_ENTRY_PATH, CURLINFO_FTP_ENTRY_PATH, writeString}, 8313498266Sopenharmony_ci {"header_json", VAR_HEADER_JSON, CURLINFO_NONE, NULL}, 8413498266Sopenharmony_ci {"http_code", VAR_HTTP_CODE, CURLINFO_RESPONSE_CODE, writeLong}, 8513498266Sopenharmony_ci {"http_connect", VAR_HTTP_CODE_PROXY, CURLINFO_HTTP_CONNECTCODE, writeLong}, 8613498266Sopenharmony_ci {"http_version", VAR_HTTP_VERSION, CURLINFO_HTTP_VERSION, writeString}, 8713498266Sopenharmony_ci {"json", VAR_JSON, CURLINFO_NONE, NULL}, 8813498266Sopenharmony_ci {"local_ip", VAR_LOCAL_IP, CURLINFO_LOCAL_IP, writeString}, 8913498266Sopenharmony_ci {"local_port", VAR_LOCAL_PORT, CURLINFO_LOCAL_PORT, writeLong}, 9013498266Sopenharmony_ci {"method", VAR_EFFECTIVE_METHOD, CURLINFO_EFFECTIVE_METHOD, writeString}, 9113498266Sopenharmony_ci {"num_certs", VAR_NUM_CERTS, CURLINFO_NONE, writeLong}, 9213498266Sopenharmony_ci {"num_connects", VAR_NUM_CONNECTS, CURLINFO_NUM_CONNECTS, writeLong}, 9313498266Sopenharmony_ci {"num_headers", VAR_NUM_HEADERS, CURLINFO_NONE, writeLong}, 9413498266Sopenharmony_ci {"num_redirects", VAR_REDIRECT_COUNT, CURLINFO_REDIRECT_COUNT, writeLong}, 9513498266Sopenharmony_ci {"onerror", VAR_ONERROR, CURLINFO_NONE, NULL}, 9613498266Sopenharmony_ci {"proxy_ssl_verify_result", VAR_PROXY_SSL_VERIFY_RESULT, 9713498266Sopenharmony_ci CURLINFO_PROXY_SSL_VERIFYRESULT, writeLong}, 9813498266Sopenharmony_ci {"redirect_url", VAR_REDIRECT_URL, CURLINFO_REDIRECT_URL, writeString}, 9913498266Sopenharmony_ci {"referer", VAR_REFERER, CURLINFO_REFERER, writeString}, 10013498266Sopenharmony_ci {"remote_ip", VAR_PRIMARY_IP, CURLINFO_PRIMARY_IP, writeString}, 10113498266Sopenharmony_ci {"remote_port", VAR_PRIMARY_PORT, CURLINFO_PRIMARY_PORT, writeLong}, 10213498266Sopenharmony_ci {"response_code", VAR_HTTP_CODE, CURLINFO_RESPONSE_CODE, writeLong}, 10313498266Sopenharmony_ci {"scheme", VAR_SCHEME, CURLINFO_SCHEME, writeString}, 10413498266Sopenharmony_ci {"size_download", VAR_SIZE_DOWNLOAD, CURLINFO_SIZE_DOWNLOAD_T, writeOffset}, 10513498266Sopenharmony_ci {"size_header", VAR_HEADER_SIZE, CURLINFO_HEADER_SIZE, writeLong}, 10613498266Sopenharmony_ci {"size_request", VAR_REQUEST_SIZE, CURLINFO_REQUEST_SIZE, writeLong}, 10713498266Sopenharmony_ci {"size_upload", VAR_SIZE_UPLOAD, CURLINFO_SIZE_UPLOAD_T, writeOffset}, 10813498266Sopenharmony_ci {"speed_download", VAR_SPEED_DOWNLOAD, CURLINFO_SPEED_DOWNLOAD_T, 10913498266Sopenharmony_ci writeOffset}, 11013498266Sopenharmony_ci {"speed_upload", VAR_SPEED_UPLOAD, CURLINFO_SPEED_UPLOAD_T, writeOffset}, 11113498266Sopenharmony_ci {"ssl_verify_result", VAR_SSL_VERIFY_RESULT, CURLINFO_SSL_VERIFYRESULT, 11213498266Sopenharmony_ci writeLong}, 11313498266Sopenharmony_ci {"stderr", VAR_STDERR, CURLINFO_NONE, NULL}, 11413498266Sopenharmony_ci {"stdout", VAR_STDOUT, CURLINFO_NONE, NULL}, 11513498266Sopenharmony_ci {"time_appconnect", VAR_APPCONNECT_TIME, CURLINFO_APPCONNECT_TIME_T, 11613498266Sopenharmony_ci writeTime}, 11713498266Sopenharmony_ci {"time_connect", VAR_CONNECT_TIME, CURLINFO_CONNECT_TIME_T, writeTime}, 11813498266Sopenharmony_ci {"time_namelookup", VAR_NAMELOOKUP_TIME, CURLINFO_NAMELOOKUP_TIME_T, 11913498266Sopenharmony_ci writeTime}, 12013498266Sopenharmony_ci {"time_pretransfer", VAR_PRETRANSFER_TIME, CURLINFO_PRETRANSFER_TIME_T, 12113498266Sopenharmony_ci writeTime}, 12213498266Sopenharmony_ci {"time_redirect", VAR_REDIRECT_TIME, CURLINFO_REDIRECT_TIME_T, writeTime}, 12313498266Sopenharmony_ci {"time_starttransfer", VAR_STARTTRANSFER_TIME, CURLINFO_STARTTRANSFER_TIME_T, 12413498266Sopenharmony_ci writeTime}, 12513498266Sopenharmony_ci {"time_total", VAR_TOTAL_TIME, CURLINFO_TOTAL_TIME_T, writeTime}, 12613498266Sopenharmony_ci {"url", VAR_INPUT_URL, CURLINFO_NONE, writeString}, 12713498266Sopenharmony_ci {"url.scheme", VAR_INPUT_URLSCHEME, CURLINFO_NONE, writeString}, 12813498266Sopenharmony_ci {"url.user", VAR_INPUT_URLUSER, CURLINFO_NONE, writeString}, 12913498266Sopenharmony_ci {"url.password", VAR_INPUT_URLPASSWORD, CURLINFO_NONE, writeString}, 13013498266Sopenharmony_ci {"url.options", VAR_INPUT_URLOPTIONS, CURLINFO_NONE, writeString}, 13113498266Sopenharmony_ci {"url.host", VAR_INPUT_URLHOST, CURLINFO_NONE, writeString}, 13213498266Sopenharmony_ci {"url.port", VAR_INPUT_URLPORT, CURLINFO_NONE, writeString}, 13313498266Sopenharmony_ci {"url.path", VAR_INPUT_URLPATH, CURLINFO_NONE, writeString}, 13413498266Sopenharmony_ci {"url.query", VAR_INPUT_URLQUERY, CURLINFO_NONE, writeString}, 13513498266Sopenharmony_ci {"url.fragment", VAR_INPUT_URLFRAGMENT, CURLINFO_NONE, writeString}, 13613498266Sopenharmony_ci {"url.zoneid", VAR_INPUT_URLZONEID, CURLINFO_NONE, writeString}, 13713498266Sopenharmony_ci {"urle.scheme", VAR_INPUT_URLESCHEME, CURLINFO_NONE, writeString}, 13813498266Sopenharmony_ci {"urle.user", VAR_INPUT_URLEUSER, CURLINFO_NONE, writeString}, 13913498266Sopenharmony_ci {"urle.password", VAR_INPUT_URLEPASSWORD, CURLINFO_NONE, writeString}, 14013498266Sopenharmony_ci {"urle.options", VAR_INPUT_URLEOPTIONS, CURLINFO_NONE, writeString}, 14113498266Sopenharmony_ci {"urle.host", VAR_INPUT_URLEHOST, CURLINFO_NONE, writeString}, 14213498266Sopenharmony_ci {"urle.port", VAR_INPUT_URLEPORT, CURLINFO_NONE, writeString}, 14313498266Sopenharmony_ci {"urle.path", VAR_INPUT_URLEPATH, CURLINFO_NONE, writeString}, 14413498266Sopenharmony_ci {"urle.query", VAR_INPUT_URLEQUERY, CURLINFO_NONE, writeString}, 14513498266Sopenharmony_ci {"urle.fragment", VAR_INPUT_URLEFRAGMENT, CURLINFO_NONE, writeString}, 14613498266Sopenharmony_ci {"urle.zoneid", VAR_INPUT_URLEZONEID, CURLINFO_NONE, writeString}, 14713498266Sopenharmony_ci {"url_effective", VAR_EFFECTIVE_URL, CURLINFO_EFFECTIVE_URL, writeString}, 14813498266Sopenharmony_ci {"urlnum", VAR_URLNUM, CURLINFO_NONE, writeLong}, 14913498266Sopenharmony_ci {"xfer_id", VAR_EASY_ID, CURLINFO_XFER_ID, writeOffset}, 15013498266Sopenharmony_ci {NULL, VAR_NONE, CURLINFO_NONE, NULL} 15113498266Sopenharmony_ci}; 15213498266Sopenharmony_ci 15313498266Sopenharmony_cistatic int writeTime(FILE *stream, const struct writeoutvar *wovar, 15413498266Sopenharmony_ci struct per_transfer *per, CURLcode per_result, 15513498266Sopenharmony_ci bool use_json) 15613498266Sopenharmony_ci{ 15713498266Sopenharmony_ci bool valid = false; 15813498266Sopenharmony_ci curl_off_t us = 0; 15913498266Sopenharmony_ci 16013498266Sopenharmony_ci (void)per; 16113498266Sopenharmony_ci (void)per_result; 16213498266Sopenharmony_ci DEBUGASSERT(wovar->writefunc == writeTime); 16313498266Sopenharmony_ci 16413498266Sopenharmony_ci if(wovar->ci) { 16513498266Sopenharmony_ci if(!curl_easy_getinfo(per->curl, wovar->ci, &us)) 16613498266Sopenharmony_ci valid = true; 16713498266Sopenharmony_ci } 16813498266Sopenharmony_ci else { 16913498266Sopenharmony_ci DEBUGASSERT(0); 17013498266Sopenharmony_ci } 17113498266Sopenharmony_ci 17213498266Sopenharmony_ci if(valid) { 17313498266Sopenharmony_ci curl_off_t secs = us / 1000000; 17413498266Sopenharmony_ci us %= 1000000; 17513498266Sopenharmony_ci 17613498266Sopenharmony_ci if(use_json) 17713498266Sopenharmony_ci fprintf(stream, "\"%s\":", wovar->name); 17813498266Sopenharmony_ci 17913498266Sopenharmony_ci fprintf(stream, "%" CURL_FORMAT_CURL_OFF_TU 18013498266Sopenharmony_ci ".%06" CURL_FORMAT_CURL_OFF_TU, secs, us); 18113498266Sopenharmony_ci } 18213498266Sopenharmony_ci else { 18313498266Sopenharmony_ci if(use_json) 18413498266Sopenharmony_ci fprintf(stream, "\"%s\":null", wovar->name); 18513498266Sopenharmony_ci } 18613498266Sopenharmony_ci 18713498266Sopenharmony_ci return 1; /* return 1 if anything was written */ 18813498266Sopenharmony_ci} 18913498266Sopenharmony_ci 19013498266Sopenharmony_cistatic int urlpart(struct per_transfer *per, writeoutid vid, 19113498266Sopenharmony_ci const char **contentp) 19213498266Sopenharmony_ci{ 19313498266Sopenharmony_ci CURLU *uh = curl_url(); 19413498266Sopenharmony_ci int rc = 0; 19513498266Sopenharmony_ci if(uh) { 19613498266Sopenharmony_ci CURLUPart cpart = CURLUPART_HOST; 19713498266Sopenharmony_ci char *part = NULL; 19813498266Sopenharmony_ci const char *url = NULL; 19913498266Sopenharmony_ci 20013498266Sopenharmony_ci if(vid >= VAR_INPUT_URLEHOST) { 20113498266Sopenharmony_ci if(curl_easy_getinfo(per->curl, CURLINFO_EFFECTIVE_URL, &url)) 20213498266Sopenharmony_ci rc = 5; 20313498266Sopenharmony_ci } 20413498266Sopenharmony_ci else 20513498266Sopenharmony_ci url = per->this_url; 20613498266Sopenharmony_ci 20713498266Sopenharmony_ci if(!rc) { 20813498266Sopenharmony_ci switch(vid) { 20913498266Sopenharmony_ci case VAR_INPUT_URLSCHEME: 21013498266Sopenharmony_ci case VAR_INPUT_URLESCHEME: 21113498266Sopenharmony_ci cpart = CURLUPART_SCHEME; 21213498266Sopenharmony_ci break; 21313498266Sopenharmony_ci case VAR_INPUT_URLUSER: 21413498266Sopenharmony_ci case VAR_INPUT_URLEUSER: 21513498266Sopenharmony_ci cpart = CURLUPART_USER; 21613498266Sopenharmony_ci break; 21713498266Sopenharmony_ci case VAR_INPUT_URLPASSWORD: 21813498266Sopenharmony_ci case VAR_INPUT_URLEPASSWORD: 21913498266Sopenharmony_ci cpart = CURLUPART_PASSWORD; 22013498266Sopenharmony_ci break; 22113498266Sopenharmony_ci case VAR_INPUT_URLOPTIONS: 22213498266Sopenharmony_ci case VAR_INPUT_URLEOPTIONS: 22313498266Sopenharmony_ci cpart = CURLUPART_OPTIONS; 22413498266Sopenharmony_ci break; 22513498266Sopenharmony_ci case VAR_INPUT_URLHOST: 22613498266Sopenharmony_ci case VAR_INPUT_URLEHOST: 22713498266Sopenharmony_ci cpart = CURLUPART_HOST; 22813498266Sopenharmony_ci break; 22913498266Sopenharmony_ci case VAR_INPUT_URLPORT: 23013498266Sopenharmony_ci case VAR_INPUT_URLEPORT: 23113498266Sopenharmony_ci cpart = CURLUPART_PORT; 23213498266Sopenharmony_ci break; 23313498266Sopenharmony_ci case VAR_INPUT_URLPATH: 23413498266Sopenharmony_ci case VAR_INPUT_URLEPATH: 23513498266Sopenharmony_ci cpart = CURLUPART_PATH; 23613498266Sopenharmony_ci break; 23713498266Sopenharmony_ci case VAR_INPUT_URLQUERY: 23813498266Sopenharmony_ci case VAR_INPUT_URLEQUERY: 23913498266Sopenharmony_ci cpart = CURLUPART_QUERY; 24013498266Sopenharmony_ci break; 24113498266Sopenharmony_ci case VAR_INPUT_URLFRAGMENT: 24213498266Sopenharmony_ci case VAR_INPUT_URLEFRAGMENT: 24313498266Sopenharmony_ci cpart = CURLUPART_FRAGMENT; 24413498266Sopenharmony_ci break; 24513498266Sopenharmony_ci case VAR_INPUT_URLZONEID: 24613498266Sopenharmony_ci case VAR_INPUT_URLEZONEID: 24713498266Sopenharmony_ci cpart = CURLUPART_ZONEID; 24813498266Sopenharmony_ci break; 24913498266Sopenharmony_ci default: 25013498266Sopenharmony_ci /* not implemented */ 25113498266Sopenharmony_ci rc = 4; 25213498266Sopenharmony_ci break; 25313498266Sopenharmony_ci } 25413498266Sopenharmony_ci } 25513498266Sopenharmony_ci if(!rc && curl_url_set(uh, CURLUPART_URL, url, 25613498266Sopenharmony_ci CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME)) 25713498266Sopenharmony_ci rc = 2; 25813498266Sopenharmony_ci 25913498266Sopenharmony_ci if(!rc && curl_url_get(uh, cpart, &part, CURLU_DEFAULT_PORT)) 26013498266Sopenharmony_ci rc = 3; 26113498266Sopenharmony_ci 26213498266Sopenharmony_ci if(!rc && part) 26313498266Sopenharmony_ci *contentp = part; 26413498266Sopenharmony_ci curl_url_cleanup(uh); 26513498266Sopenharmony_ci } 26613498266Sopenharmony_ci else 26713498266Sopenharmony_ci return 1; 26813498266Sopenharmony_ci return rc; 26913498266Sopenharmony_ci} 27013498266Sopenharmony_ci 27113498266Sopenharmony_cistatic int writeString(FILE *stream, const struct writeoutvar *wovar, 27213498266Sopenharmony_ci struct per_transfer *per, CURLcode per_result, 27313498266Sopenharmony_ci bool use_json) 27413498266Sopenharmony_ci{ 27513498266Sopenharmony_ci bool valid = false; 27613498266Sopenharmony_ci const char *strinfo = NULL; 27713498266Sopenharmony_ci const char *freestr = NULL; 27813498266Sopenharmony_ci struct dynbuf buf; 27913498266Sopenharmony_ci curlx_dyn_init(&buf, 256*1024); 28013498266Sopenharmony_ci 28113498266Sopenharmony_ci DEBUGASSERT(wovar->writefunc == writeString); 28213498266Sopenharmony_ci 28313498266Sopenharmony_ci if(wovar->ci) { 28413498266Sopenharmony_ci if(wovar->ci == CURLINFO_HTTP_VERSION) { 28513498266Sopenharmony_ci long version = 0; 28613498266Sopenharmony_ci if(!curl_easy_getinfo(per->curl, CURLINFO_HTTP_VERSION, &version)) { 28713498266Sopenharmony_ci const struct httpmap *m = &http_version[0]; 28813498266Sopenharmony_ci while(m->str) { 28913498266Sopenharmony_ci if(m->num == version) { 29013498266Sopenharmony_ci strinfo = m->str; 29113498266Sopenharmony_ci valid = true; 29213498266Sopenharmony_ci break; 29313498266Sopenharmony_ci } 29413498266Sopenharmony_ci m++; 29513498266Sopenharmony_ci } 29613498266Sopenharmony_ci } 29713498266Sopenharmony_ci } 29813498266Sopenharmony_ci else { 29913498266Sopenharmony_ci if(!curl_easy_getinfo(per->curl, wovar->ci, &strinfo) && strinfo) 30013498266Sopenharmony_ci valid = true; 30113498266Sopenharmony_ci } 30213498266Sopenharmony_ci } 30313498266Sopenharmony_ci else { 30413498266Sopenharmony_ci switch(wovar->id) { 30513498266Sopenharmony_ci case VAR_CERT: 30613498266Sopenharmony_ci if(per->certinfo) { 30713498266Sopenharmony_ci int i; 30813498266Sopenharmony_ci bool error = FALSE; 30913498266Sopenharmony_ci for(i = 0; (i < per->certinfo->num_of_certs) && !error; i++) { 31013498266Sopenharmony_ci struct curl_slist *slist; 31113498266Sopenharmony_ci 31213498266Sopenharmony_ci for(slist = per->certinfo->certinfo[i]; slist; slist = slist->next) { 31313498266Sopenharmony_ci size_t len; 31413498266Sopenharmony_ci if(curl_strnequal(slist->data, "cert:", 5)) { 31513498266Sopenharmony_ci if(curlx_dyn_add(&buf, &slist->data[5])) { 31613498266Sopenharmony_ci error = TRUE; 31713498266Sopenharmony_ci break; 31813498266Sopenharmony_ci } 31913498266Sopenharmony_ci } 32013498266Sopenharmony_ci else { 32113498266Sopenharmony_ci if(curlx_dyn_add(&buf, slist->data)) { 32213498266Sopenharmony_ci error = TRUE; 32313498266Sopenharmony_ci break; 32413498266Sopenharmony_ci } 32513498266Sopenharmony_ci } 32613498266Sopenharmony_ci len = curlx_dyn_len(&buf); 32713498266Sopenharmony_ci if(len) { 32813498266Sopenharmony_ci char *ptr = curlx_dyn_ptr(&buf); 32913498266Sopenharmony_ci if(ptr[len -1] != '\n') { 33013498266Sopenharmony_ci /* add a newline to make things look better */ 33113498266Sopenharmony_ci if(curlx_dyn_addn(&buf, "\n", 1)) { 33213498266Sopenharmony_ci error = TRUE; 33313498266Sopenharmony_ci break; 33413498266Sopenharmony_ci } 33513498266Sopenharmony_ci } 33613498266Sopenharmony_ci } 33713498266Sopenharmony_ci } 33813498266Sopenharmony_ci } 33913498266Sopenharmony_ci if(!error) { 34013498266Sopenharmony_ci strinfo = curlx_dyn_ptr(&buf); 34113498266Sopenharmony_ci if(!strinfo) 34213498266Sopenharmony_ci /* maybe not a TLS protocol */ 34313498266Sopenharmony_ci strinfo = ""; 34413498266Sopenharmony_ci valid = true; 34513498266Sopenharmony_ci } 34613498266Sopenharmony_ci } 34713498266Sopenharmony_ci else 34813498266Sopenharmony_ci strinfo = ""; /* no cert info */ 34913498266Sopenharmony_ci break; 35013498266Sopenharmony_ci case VAR_ERRORMSG: 35113498266Sopenharmony_ci if(per_result) { 35213498266Sopenharmony_ci strinfo = (per->errorbuffer && per->errorbuffer[0]) ? 35313498266Sopenharmony_ci per->errorbuffer : curl_easy_strerror(per_result); 35413498266Sopenharmony_ci valid = true; 35513498266Sopenharmony_ci } 35613498266Sopenharmony_ci break; 35713498266Sopenharmony_ci case VAR_EFFECTIVE_FILENAME: 35813498266Sopenharmony_ci if(per->outs.filename) { 35913498266Sopenharmony_ci strinfo = per->outs.filename; 36013498266Sopenharmony_ci valid = true; 36113498266Sopenharmony_ci } 36213498266Sopenharmony_ci break; 36313498266Sopenharmony_ci case VAR_INPUT_URL: 36413498266Sopenharmony_ci if(per->this_url) { 36513498266Sopenharmony_ci strinfo = per->this_url; 36613498266Sopenharmony_ci valid = true; 36713498266Sopenharmony_ci } 36813498266Sopenharmony_ci break; 36913498266Sopenharmony_ci case VAR_INPUT_URLSCHEME: 37013498266Sopenharmony_ci case VAR_INPUT_URLUSER: 37113498266Sopenharmony_ci case VAR_INPUT_URLPASSWORD: 37213498266Sopenharmony_ci case VAR_INPUT_URLOPTIONS: 37313498266Sopenharmony_ci case VAR_INPUT_URLHOST: 37413498266Sopenharmony_ci case VAR_INPUT_URLPORT: 37513498266Sopenharmony_ci case VAR_INPUT_URLPATH: 37613498266Sopenharmony_ci case VAR_INPUT_URLQUERY: 37713498266Sopenharmony_ci case VAR_INPUT_URLFRAGMENT: 37813498266Sopenharmony_ci case VAR_INPUT_URLZONEID: 37913498266Sopenharmony_ci case VAR_INPUT_URLESCHEME: 38013498266Sopenharmony_ci case VAR_INPUT_URLEUSER: 38113498266Sopenharmony_ci case VAR_INPUT_URLEPASSWORD: 38213498266Sopenharmony_ci case VAR_INPUT_URLEOPTIONS: 38313498266Sopenharmony_ci case VAR_INPUT_URLEHOST: 38413498266Sopenharmony_ci case VAR_INPUT_URLEPORT: 38513498266Sopenharmony_ci case VAR_INPUT_URLEPATH: 38613498266Sopenharmony_ci case VAR_INPUT_URLEQUERY: 38713498266Sopenharmony_ci case VAR_INPUT_URLEFRAGMENT: 38813498266Sopenharmony_ci case VAR_INPUT_URLEZONEID: 38913498266Sopenharmony_ci if(per->this_url) { 39013498266Sopenharmony_ci if(!urlpart(per, wovar->id, &strinfo)) { 39113498266Sopenharmony_ci freestr = strinfo; 39213498266Sopenharmony_ci valid = true; 39313498266Sopenharmony_ci } 39413498266Sopenharmony_ci } 39513498266Sopenharmony_ci break; 39613498266Sopenharmony_ci default: 39713498266Sopenharmony_ci DEBUGASSERT(0); 39813498266Sopenharmony_ci break; 39913498266Sopenharmony_ci } 40013498266Sopenharmony_ci } 40113498266Sopenharmony_ci 40213498266Sopenharmony_ci if(valid) { 40313498266Sopenharmony_ci DEBUGASSERT(strinfo); 40413498266Sopenharmony_ci if(use_json) { 40513498266Sopenharmony_ci fprintf(stream, "\"%s\":", wovar->name); 40613498266Sopenharmony_ci jsonWriteString(stream, strinfo, FALSE); 40713498266Sopenharmony_ci } 40813498266Sopenharmony_ci else 40913498266Sopenharmony_ci fputs(strinfo, stream); 41013498266Sopenharmony_ci } 41113498266Sopenharmony_ci else { 41213498266Sopenharmony_ci if(use_json) 41313498266Sopenharmony_ci fprintf(stream, "\"%s\":null", wovar->name); 41413498266Sopenharmony_ci } 41513498266Sopenharmony_ci curl_free((char *)freestr); 41613498266Sopenharmony_ci 41713498266Sopenharmony_ci curlx_dyn_free(&buf); 41813498266Sopenharmony_ci return 1; /* return 1 if anything was written */ 41913498266Sopenharmony_ci} 42013498266Sopenharmony_ci 42113498266Sopenharmony_cistatic int writeLong(FILE *stream, const struct writeoutvar *wovar, 42213498266Sopenharmony_ci struct per_transfer *per, CURLcode per_result, 42313498266Sopenharmony_ci bool use_json) 42413498266Sopenharmony_ci{ 42513498266Sopenharmony_ci bool valid = false; 42613498266Sopenharmony_ci long longinfo = 0; 42713498266Sopenharmony_ci 42813498266Sopenharmony_ci DEBUGASSERT(wovar->writefunc == writeLong); 42913498266Sopenharmony_ci 43013498266Sopenharmony_ci if(wovar->ci) { 43113498266Sopenharmony_ci if(!curl_easy_getinfo(per->curl, wovar->ci, &longinfo)) 43213498266Sopenharmony_ci valid = true; 43313498266Sopenharmony_ci } 43413498266Sopenharmony_ci else { 43513498266Sopenharmony_ci switch(wovar->id) { 43613498266Sopenharmony_ci case VAR_NUM_CERTS: 43713498266Sopenharmony_ci longinfo = per->certinfo ? per->certinfo->num_of_certs : 0; 43813498266Sopenharmony_ci valid = true; 43913498266Sopenharmony_ci break; 44013498266Sopenharmony_ci case VAR_NUM_HEADERS: 44113498266Sopenharmony_ci longinfo = per->num_headers; 44213498266Sopenharmony_ci valid = true; 44313498266Sopenharmony_ci break; 44413498266Sopenharmony_ci case VAR_EXITCODE: 44513498266Sopenharmony_ci longinfo = per_result; 44613498266Sopenharmony_ci valid = true; 44713498266Sopenharmony_ci break; 44813498266Sopenharmony_ci case VAR_URLNUM: 44913498266Sopenharmony_ci if(per->urlnum <= INT_MAX) { 45013498266Sopenharmony_ci longinfo = (long)per->urlnum; 45113498266Sopenharmony_ci valid = true; 45213498266Sopenharmony_ci } 45313498266Sopenharmony_ci break; 45413498266Sopenharmony_ci default: 45513498266Sopenharmony_ci DEBUGASSERT(0); 45613498266Sopenharmony_ci break; 45713498266Sopenharmony_ci } 45813498266Sopenharmony_ci } 45913498266Sopenharmony_ci 46013498266Sopenharmony_ci if(valid) { 46113498266Sopenharmony_ci if(use_json) 46213498266Sopenharmony_ci fprintf(stream, "\"%s\":%ld", wovar->name, longinfo); 46313498266Sopenharmony_ci else { 46413498266Sopenharmony_ci if(wovar->id == VAR_HTTP_CODE || wovar->id == VAR_HTTP_CODE_PROXY) 46513498266Sopenharmony_ci fprintf(stream, "%03ld", longinfo); 46613498266Sopenharmony_ci else 46713498266Sopenharmony_ci fprintf(stream, "%ld", longinfo); 46813498266Sopenharmony_ci } 46913498266Sopenharmony_ci } 47013498266Sopenharmony_ci else { 47113498266Sopenharmony_ci if(use_json) 47213498266Sopenharmony_ci fprintf(stream, "\"%s\":null", wovar->name); 47313498266Sopenharmony_ci } 47413498266Sopenharmony_ci 47513498266Sopenharmony_ci return 1; /* return 1 if anything was written */ 47613498266Sopenharmony_ci} 47713498266Sopenharmony_ci 47813498266Sopenharmony_cistatic int writeOffset(FILE *stream, const struct writeoutvar *wovar, 47913498266Sopenharmony_ci struct per_transfer *per, CURLcode per_result, 48013498266Sopenharmony_ci bool use_json) 48113498266Sopenharmony_ci{ 48213498266Sopenharmony_ci bool valid = false; 48313498266Sopenharmony_ci curl_off_t offinfo = 0; 48413498266Sopenharmony_ci 48513498266Sopenharmony_ci (void)per; 48613498266Sopenharmony_ci (void)per_result; 48713498266Sopenharmony_ci DEBUGASSERT(wovar->writefunc == writeOffset); 48813498266Sopenharmony_ci 48913498266Sopenharmony_ci if(wovar->ci) { 49013498266Sopenharmony_ci if(!curl_easy_getinfo(per->curl, wovar->ci, &offinfo)) 49113498266Sopenharmony_ci valid = true; 49213498266Sopenharmony_ci } 49313498266Sopenharmony_ci else { 49413498266Sopenharmony_ci DEBUGASSERT(0); 49513498266Sopenharmony_ci } 49613498266Sopenharmony_ci 49713498266Sopenharmony_ci if(valid) { 49813498266Sopenharmony_ci if(use_json) 49913498266Sopenharmony_ci fprintf(stream, "\"%s\":", wovar->name); 50013498266Sopenharmony_ci 50113498266Sopenharmony_ci fprintf(stream, "%" CURL_FORMAT_CURL_OFF_T, offinfo); 50213498266Sopenharmony_ci } 50313498266Sopenharmony_ci else { 50413498266Sopenharmony_ci if(use_json) 50513498266Sopenharmony_ci fprintf(stream, "\"%s\":null", wovar->name); 50613498266Sopenharmony_ci } 50713498266Sopenharmony_ci 50813498266Sopenharmony_ci return 1; /* return 1 if anything was written */ 50913498266Sopenharmony_ci} 51013498266Sopenharmony_ci 51113498266Sopenharmony_civoid ourWriteOut(struct OperationConfig *config, struct per_transfer *per, 51213498266Sopenharmony_ci CURLcode per_result) 51313498266Sopenharmony_ci{ 51413498266Sopenharmony_ci FILE *stream = stdout; 51513498266Sopenharmony_ci const char *writeinfo = config->writeout; 51613498266Sopenharmony_ci const char *ptr = writeinfo; 51713498266Sopenharmony_ci bool done = FALSE; 51813498266Sopenharmony_ci struct curl_certinfo *certinfo; 51913498266Sopenharmony_ci CURLcode res = curl_easy_getinfo(per->curl, CURLINFO_CERTINFO, &certinfo); 52013498266Sopenharmony_ci bool fclose_stream = FALSE; 52113498266Sopenharmony_ci 52213498266Sopenharmony_ci if(!writeinfo) 52313498266Sopenharmony_ci return; 52413498266Sopenharmony_ci 52513498266Sopenharmony_ci if(!res && certinfo) 52613498266Sopenharmony_ci per->certinfo = certinfo; 52713498266Sopenharmony_ci 52813498266Sopenharmony_ci while(ptr && *ptr && !done) { 52913498266Sopenharmony_ci if('%' == *ptr && ptr[1]) { 53013498266Sopenharmony_ci if('%' == ptr[1]) { 53113498266Sopenharmony_ci /* an escaped %-letter */ 53213498266Sopenharmony_ci fputc('%', stream); 53313498266Sopenharmony_ci ptr += 2; 53413498266Sopenharmony_ci } 53513498266Sopenharmony_ci else { 53613498266Sopenharmony_ci /* this is meant as a variable to output */ 53713498266Sopenharmony_ci char *end; 53813498266Sopenharmony_ci size_t vlen; 53913498266Sopenharmony_ci if('{' == ptr[1]) { 54013498266Sopenharmony_ci int i; 54113498266Sopenharmony_ci bool match = FALSE; 54213498266Sopenharmony_ci end = strchr(ptr, '}'); 54313498266Sopenharmony_ci ptr += 2; /* pass the % and the { */ 54413498266Sopenharmony_ci if(!end) { 54513498266Sopenharmony_ci fputs("%{", stream); 54613498266Sopenharmony_ci continue; 54713498266Sopenharmony_ci } 54813498266Sopenharmony_ci vlen = end - ptr; 54913498266Sopenharmony_ci for(i = 0; variables[i].name; i++) { 55013498266Sopenharmony_ci if((strlen(variables[i].name) == vlen) && 55113498266Sopenharmony_ci curl_strnequal(ptr, variables[i].name, vlen)) { 55213498266Sopenharmony_ci match = TRUE; 55313498266Sopenharmony_ci switch(variables[i].id) { 55413498266Sopenharmony_ci case VAR_ONERROR: 55513498266Sopenharmony_ci if(per_result == CURLE_OK) 55613498266Sopenharmony_ci /* this isn't error so skip the rest */ 55713498266Sopenharmony_ci done = TRUE; 55813498266Sopenharmony_ci break; 55913498266Sopenharmony_ci case VAR_STDOUT: 56013498266Sopenharmony_ci if(fclose_stream) 56113498266Sopenharmony_ci fclose(stream); 56213498266Sopenharmony_ci fclose_stream = FALSE; 56313498266Sopenharmony_ci stream = stdout; 56413498266Sopenharmony_ci break; 56513498266Sopenharmony_ci case VAR_STDERR: 56613498266Sopenharmony_ci if(fclose_stream) 56713498266Sopenharmony_ci fclose(stream); 56813498266Sopenharmony_ci fclose_stream = FALSE; 56913498266Sopenharmony_ci stream = tool_stderr; 57013498266Sopenharmony_ci break; 57113498266Sopenharmony_ci case VAR_JSON: 57213498266Sopenharmony_ci ourWriteOutJSON(stream, variables, per, per_result); 57313498266Sopenharmony_ci break; 57413498266Sopenharmony_ci case VAR_HEADER_JSON: 57513498266Sopenharmony_ci headerJSON(stream, per); 57613498266Sopenharmony_ci break; 57713498266Sopenharmony_ci default: 57813498266Sopenharmony_ci (void)variables[i].writefunc(stream, &variables[i], 57913498266Sopenharmony_ci per, per_result, false); 58013498266Sopenharmony_ci break; 58113498266Sopenharmony_ci } 58213498266Sopenharmony_ci break; 58313498266Sopenharmony_ci } 58413498266Sopenharmony_ci } 58513498266Sopenharmony_ci if(!match) { 58613498266Sopenharmony_ci fprintf(tool_stderr, 58713498266Sopenharmony_ci "curl: unknown --write-out variable: '%.*s'\n", 58813498266Sopenharmony_ci (int)vlen, ptr); 58913498266Sopenharmony_ci } 59013498266Sopenharmony_ci ptr = end + 1; /* pass the end */ 59113498266Sopenharmony_ci } 59213498266Sopenharmony_ci else if(!strncmp("header{", &ptr[1], 7)) { 59313498266Sopenharmony_ci ptr += 8; 59413498266Sopenharmony_ci end = strchr(ptr, '}'); 59513498266Sopenharmony_ci if(end) { 59613498266Sopenharmony_ci char hname[256]; /* holds the longest header field name */ 59713498266Sopenharmony_ci struct curl_header *header; 59813498266Sopenharmony_ci vlen = end - ptr; 59913498266Sopenharmony_ci if(vlen < sizeof(hname)) { 60013498266Sopenharmony_ci memcpy(hname, ptr, vlen); 60113498266Sopenharmony_ci hname[vlen] = 0; 60213498266Sopenharmony_ci if(CURLHE_OK == curl_easy_header(per->curl, hname, 0, 60313498266Sopenharmony_ci CURLH_HEADER, -1, &header)) 60413498266Sopenharmony_ci fputs(header->value, stream); 60513498266Sopenharmony_ci } 60613498266Sopenharmony_ci ptr = end + 1; 60713498266Sopenharmony_ci } 60813498266Sopenharmony_ci else 60913498266Sopenharmony_ci fputs("%header{", stream); 61013498266Sopenharmony_ci } 61113498266Sopenharmony_ci else if(!strncmp("output{", &ptr[1], 7)) { 61213498266Sopenharmony_ci bool append = FALSE; 61313498266Sopenharmony_ci ptr += 8; 61413498266Sopenharmony_ci if((ptr[0] == '>') && (ptr[1] == '>')) { 61513498266Sopenharmony_ci append = TRUE; 61613498266Sopenharmony_ci ptr += 2; 61713498266Sopenharmony_ci } 61813498266Sopenharmony_ci end = strchr(ptr, '}'); 61913498266Sopenharmony_ci if(end) { 62013498266Sopenharmony_ci char fname[512]; /* holds the longest file name */ 62113498266Sopenharmony_ci size_t flen = end - ptr; 62213498266Sopenharmony_ci if(flen < sizeof(fname)) { 62313498266Sopenharmony_ci FILE *stream2; 62413498266Sopenharmony_ci memcpy(fname, ptr, flen); 62513498266Sopenharmony_ci fname[flen] = 0; 62613498266Sopenharmony_ci stream2 = fopen(fname, append? FOPEN_APPENDTEXT : 62713498266Sopenharmony_ci FOPEN_WRITETEXT); 62813498266Sopenharmony_ci if(stream2) { 62913498266Sopenharmony_ci /* only change if the open worked */ 63013498266Sopenharmony_ci if(fclose_stream) 63113498266Sopenharmony_ci fclose(stream); 63213498266Sopenharmony_ci stream = stream2; 63313498266Sopenharmony_ci fclose_stream = TRUE; 63413498266Sopenharmony_ci } 63513498266Sopenharmony_ci } 63613498266Sopenharmony_ci ptr = end + 1; 63713498266Sopenharmony_ci } 63813498266Sopenharmony_ci else 63913498266Sopenharmony_ci fputs("%output{", stream); 64013498266Sopenharmony_ci } 64113498266Sopenharmony_ci else { 64213498266Sopenharmony_ci /* illegal syntax, then just output the characters that are used */ 64313498266Sopenharmony_ci fputc('%', stream); 64413498266Sopenharmony_ci fputc(ptr[1], stream); 64513498266Sopenharmony_ci ptr += 2; 64613498266Sopenharmony_ci } 64713498266Sopenharmony_ci } 64813498266Sopenharmony_ci } 64913498266Sopenharmony_ci else if('\\' == *ptr && ptr[1]) { 65013498266Sopenharmony_ci switch(ptr[1]) { 65113498266Sopenharmony_ci case 'r': 65213498266Sopenharmony_ci fputc('\r', stream); 65313498266Sopenharmony_ci break; 65413498266Sopenharmony_ci case 'n': 65513498266Sopenharmony_ci fputc('\n', stream); 65613498266Sopenharmony_ci break; 65713498266Sopenharmony_ci case 't': 65813498266Sopenharmony_ci fputc('\t', stream); 65913498266Sopenharmony_ci break; 66013498266Sopenharmony_ci default: 66113498266Sopenharmony_ci /* unknown, just output this */ 66213498266Sopenharmony_ci fputc(*ptr, stream); 66313498266Sopenharmony_ci fputc(ptr[1], stream); 66413498266Sopenharmony_ci break; 66513498266Sopenharmony_ci } 66613498266Sopenharmony_ci ptr += 2; 66713498266Sopenharmony_ci } 66813498266Sopenharmony_ci else { 66913498266Sopenharmony_ci fputc(*ptr, stream); 67013498266Sopenharmony_ci ptr++; 67113498266Sopenharmony_ci } 67213498266Sopenharmony_ci } 67313498266Sopenharmony_ci if(fclose_stream) 67413498266Sopenharmony_ci fclose(stream); 67513498266Sopenharmony_ci} 676