xref: /aosp_15_r20/external/curl/src/tool_writeout.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker  *                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker  *  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker  *                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker  *                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker  *                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker  *
8*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker  *
10*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker  *
14*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker  *
18*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker  *
21*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker  *
23*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker #include "tool_setup.h"
25*6236dae4SAndroid Build Coastguard Worker 
26*6236dae4SAndroid Build Coastguard Worker #include "curlx.h"
27*6236dae4SAndroid Build Coastguard Worker #include "tool_cfgable.h"
28*6236dae4SAndroid Build Coastguard Worker #include "tool_writeout.h"
29*6236dae4SAndroid Build Coastguard Worker #include "tool_writeout_json.h"
30*6236dae4SAndroid Build Coastguard Worker #include "dynbuf.h"
31*6236dae4SAndroid Build Coastguard Worker 
32*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h" /* keep this as LAST include */
33*6236dae4SAndroid Build Coastguard Worker 
34*6236dae4SAndroid Build Coastguard Worker static int writeTime(FILE *stream, const struct writeoutvar *wovar,
35*6236dae4SAndroid Build Coastguard Worker                      struct per_transfer *per, CURLcode per_result,
36*6236dae4SAndroid Build Coastguard Worker                      bool use_json);
37*6236dae4SAndroid Build Coastguard Worker 
38*6236dae4SAndroid Build Coastguard Worker static int writeString(FILE *stream, const struct writeoutvar *wovar,
39*6236dae4SAndroid Build Coastguard Worker                        struct per_transfer *per, CURLcode per_result,
40*6236dae4SAndroid Build Coastguard Worker                        bool use_json);
41*6236dae4SAndroid Build Coastguard Worker 
42*6236dae4SAndroid Build Coastguard Worker static int writeLong(FILE *stream, const struct writeoutvar *wovar,
43*6236dae4SAndroid Build Coastguard Worker                      struct per_transfer *per, CURLcode per_result,
44*6236dae4SAndroid Build Coastguard Worker                      bool use_json);
45*6236dae4SAndroid Build Coastguard Worker 
46*6236dae4SAndroid Build Coastguard Worker static int writeOffset(FILE *stream, const struct writeoutvar *wovar,
47*6236dae4SAndroid Build Coastguard Worker                        struct per_transfer *per, CURLcode per_result,
48*6236dae4SAndroid Build Coastguard Worker                        bool use_json);
49*6236dae4SAndroid Build Coastguard Worker 
50*6236dae4SAndroid Build Coastguard Worker struct httpmap {
51*6236dae4SAndroid Build Coastguard Worker   const char *str;
52*6236dae4SAndroid Build Coastguard Worker   int num;
53*6236dae4SAndroid Build Coastguard Worker };
54*6236dae4SAndroid Build Coastguard Worker 
55*6236dae4SAndroid Build Coastguard Worker static const struct httpmap http_version[] = {
56*6236dae4SAndroid Build Coastguard Worker   { "0",   CURL_HTTP_VERSION_NONE},
57*6236dae4SAndroid Build Coastguard Worker   { "1",   CURL_HTTP_VERSION_1_0},
58*6236dae4SAndroid Build Coastguard Worker   { "1.1", CURL_HTTP_VERSION_1_1},
59*6236dae4SAndroid Build Coastguard Worker   { "2",   CURL_HTTP_VERSION_2},
60*6236dae4SAndroid Build Coastguard Worker   { "3",   CURL_HTTP_VERSION_3},
61*6236dae4SAndroid Build Coastguard Worker   { NULL, 0} /* end of list */
62*6236dae4SAndroid Build Coastguard Worker };
63*6236dae4SAndroid Build Coastguard Worker 
64*6236dae4SAndroid Build Coastguard Worker /* The designated write function should be the same as the CURLINFO return type
65*6236dae4SAndroid Build Coastguard Worker    with exceptions special cased in the respective function. For example,
66*6236dae4SAndroid Build Coastguard Worker    http_version uses CURLINFO_HTTP_VERSION which returns the version as a long,
67*6236dae4SAndroid Build Coastguard Worker    however it is output as a string and therefore is handled in writeString.
68*6236dae4SAndroid Build Coastguard Worker 
69*6236dae4SAndroid Build Coastguard Worker    Yes: "http_version": "1.1"
70*6236dae4SAndroid Build Coastguard Worker    No:  "http_version": 1.1
71*6236dae4SAndroid Build Coastguard Worker 
72*6236dae4SAndroid Build Coastguard Worker    Variable names MUST be in alphabetical order.
73*6236dae4SAndroid Build Coastguard Worker    */
74*6236dae4SAndroid Build Coastguard Worker static const struct writeoutvar variables[] = {
75*6236dae4SAndroid Build Coastguard Worker   {"certs", VAR_CERT, CURLINFO_NONE, writeString},
76*6236dae4SAndroid Build Coastguard Worker   {"conn_id", VAR_CONN_ID, CURLINFO_CONN_ID, writeOffset},
77*6236dae4SAndroid Build Coastguard Worker   {"content_type", VAR_CONTENT_TYPE, CURLINFO_CONTENT_TYPE, writeString},
78*6236dae4SAndroid Build Coastguard Worker   {"errormsg", VAR_ERRORMSG, CURLINFO_NONE, writeString},
79*6236dae4SAndroid Build Coastguard Worker   {"exitcode", VAR_EXITCODE, CURLINFO_NONE, writeLong},
80*6236dae4SAndroid Build Coastguard Worker   {"filename_effective", VAR_EFFECTIVE_FILENAME, CURLINFO_NONE, writeString},
81*6236dae4SAndroid Build Coastguard Worker   {"ftp_entry_path", VAR_FTP_ENTRY_PATH, CURLINFO_FTP_ENTRY_PATH, writeString},
82*6236dae4SAndroid Build Coastguard Worker   {"header_json", VAR_HEADER_JSON, CURLINFO_NONE, NULL},
83*6236dae4SAndroid Build Coastguard Worker   {"http_code", VAR_HTTP_CODE, CURLINFO_RESPONSE_CODE, writeLong},
84*6236dae4SAndroid Build Coastguard Worker   {"http_connect", VAR_HTTP_CODE_PROXY, CURLINFO_HTTP_CONNECTCODE, writeLong},
85*6236dae4SAndroid Build Coastguard Worker   {"http_version", VAR_HTTP_VERSION, CURLINFO_HTTP_VERSION, writeString},
86*6236dae4SAndroid Build Coastguard Worker   {"json", VAR_JSON, CURLINFO_NONE, NULL},
87*6236dae4SAndroid Build Coastguard Worker   {"local_ip", VAR_LOCAL_IP, CURLINFO_LOCAL_IP, writeString},
88*6236dae4SAndroid Build Coastguard Worker   {"local_port", VAR_LOCAL_PORT, CURLINFO_LOCAL_PORT, writeLong},
89*6236dae4SAndroid Build Coastguard Worker   {"method", VAR_EFFECTIVE_METHOD, CURLINFO_EFFECTIVE_METHOD, writeString},
90*6236dae4SAndroid Build Coastguard Worker   {"num_certs", VAR_NUM_CERTS, CURLINFO_NONE, writeLong},
91*6236dae4SAndroid Build Coastguard Worker   {"num_connects", VAR_NUM_CONNECTS, CURLINFO_NUM_CONNECTS, writeLong},
92*6236dae4SAndroid Build Coastguard Worker   {"num_headers", VAR_NUM_HEADERS, CURLINFO_NONE, writeLong},
93*6236dae4SAndroid Build Coastguard Worker   {"num_redirects", VAR_REDIRECT_COUNT, CURLINFO_REDIRECT_COUNT, writeLong},
94*6236dae4SAndroid Build Coastguard Worker   {"num_retries", VAR_NUM_RETRY, CURLINFO_NONE, writeLong},
95*6236dae4SAndroid Build Coastguard Worker   {"onerror", VAR_ONERROR, CURLINFO_NONE, NULL},
96*6236dae4SAndroid Build Coastguard Worker   {"proxy_ssl_verify_result", VAR_PROXY_SSL_VERIFY_RESULT,
97*6236dae4SAndroid Build Coastguard Worker    CURLINFO_PROXY_SSL_VERIFYRESULT, writeLong},
98*6236dae4SAndroid Build Coastguard Worker   {"proxy_used", VAR_PROXY_USED, CURLINFO_USED_PROXY, writeLong},
99*6236dae4SAndroid Build Coastguard Worker   {"redirect_url", VAR_REDIRECT_URL, CURLINFO_REDIRECT_URL, writeString},
100*6236dae4SAndroid Build Coastguard Worker   {"referer", VAR_REFERER, CURLINFO_REFERER, writeString},
101*6236dae4SAndroid Build Coastguard Worker   {"remote_ip", VAR_PRIMARY_IP, CURLINFO_PRIMARY_IP, writeString},
102*6236dae4SAndroid Build Coastguard Worker   {"remote_port", VAR_PRIMARY_PORT, CURLINFO_PRIMARY_PORT, writeLong},
103*6236dae4SAndroid Build Coastguard Worker   {"response_code", VAR_HTTP_CODE, CURLINFO_RESPONSE_CODE, writeLong},
104*6236dae4SAndroid Build Coastguard Worker   {"scheme", VAR_SCHEME, CURLINFO_SCHEME, writeString},
105*6236dae4SAndroid Build Coastguard Worker   {"size_download", VAR_SIZE_DOWNLOAD, CURLINFO_SIZE_DOWNLOAD_T, writeOffset},
106*6236dae4SAndroid Build Coastguard Worker   {"size_header", VAR_HEADER_SIZE, CURLINFO_HEADER_SIZE, writeLong},
107*6236dae4SAndroid Build Coastguard Worker   {"size_request", VAR_REQUEST_SIZE, CURLINFO_REQUEST_SIZE, writeLong},
108*6236dae4SAndroid Build Coastguard Worker   {"size_upload", VAR_SIZE_UPLOAD, CURLINFO_SIZE_UPLOAD_T, writeOffset},
109*6236dae4SAndroid Build Coastguard Worker   {"speed_download", VAR_SPEED_DOWNLOAD, CURLINFO_SPEED_DOWNLOAD_T,
110*6236dae4SAndroid Build Coastguard Worker    writeOffset},
111*6236dae4SAndroid Build Coastguard Worker   {"speed_upload", VAR_SPEED_UPLOAD, CURLINFO_SPEED_UPLOAD_T, writeOffset},
112*6236dae4SAndroid Build Coastguard Worker   {"ssl_verify_result", VAR_SSL_VERIFY_RESULT, CURLINFO_SSL_VERIFYRESULT,
113*6236dae4SAndroid Build Coastguard Worker    writeLong},
114*6236dae4SAndroid Build Coastguard Worker   {"stderr", VAR_STDERR, CURLINFO_NONE, NULL},
115*6236dae4SAndroid Build Coastguard Worker   {"stdout", VAR_STDOUT, CURLINFO_NONE, NULL},
116*6236dae4SAndroid Build Coastguard Worker   {"time_appconnect", VAR_APPCONNECT_TIME, CURLINFO_APPCONNECT_TIME_T,
117*6236dae4SAndroid Build Coastguard Worker    writeTime},
118*6236dae4SAndroid Build Coastguard Worker   {"time_connect", VAR_CONNECT_TIME, CURLINFO_CONNECT_TIME_T, writeTime},
119*6236dae4SAndroid Build Coastguard Worker   {"time_namelookup", VAR_NAMELOOKUP_TIME, CURLINFO_NAMELOOKUP_TIME_T,
120*6236dae4SAndroid Build Coastguard Worker    writeTime},
121*6236dae4SAndroid Build Coastguard Worker   {"time_posttransfer", VAR_POSTTRANSFER_TIME, CURLINFO_POSTTRANSFER_TIME_T,
122*6236dae4SAndroid Build Coastguard Worker    writeTime},
123*6236dae4SAndroid Build Coastguard Worker   {"time_pretransfer", VAR_PRETRANSFER_TIME, CURLINFO_PRETRANSFER_TIME_T,
124*6236dae4SAndroid Build Coastguard Worker    writeTime},
125*6236dae4SAndroid Build Coastguard Worker   {"time_redirect", VAR_REDIRECT_TIME, CURLINFO_REDIRECT_TIME_T, writeTime},
126*6236dae4SAndroid Build Coastguard Worker   {"time_starttransfer", VAR_STARTTRANSFER_TIME, CURLINFO_STARTTRANSFER_TIME_T,
127*6236dae4SAndroid Build Coastguard Worker    writeTime},
128*6236dae4SAndroid Build Coastguard Worker   {"time_total", VAR_TOTAL_TIME, CURLINFO_TOTAL_TIME_T, writeTime},
129*6236dae4SAndroid Build Coastguard Worker   {"url", VAR_INPUT_URL, CURLINFO_NONE, writeString},
130*6236dae4SAndroid Build Coastguard Worker   {"url.fragment", VAR_INPUT_URLFRAGMENT, CURLINFO_NONE, writeString},
131*6236dae4SAndroid Build Coastguard Worker   {"url.host", VAR_INPUT_URLHOST, CURLINFO_NONE, writeString},
132*6236dae4SAndroid Build Coastguard Worker   {"url.options", VAR_INPUT_URLOPTIONS, CURLINFO_NONE, writeString},
133*6236dae4SAndroid Build Coastguard Worker   {"url.password", VAR_INPUT_URLPASSWORD, CURLINFO_NONE, writeString},
134*6236dae4SAndroid Build Coastguard Worker   {"url.path", VAR_INPUT_URLPATH, CURLINFO_NONE, writeString},
135*6236dae4SAndroid Build Coastguard Worker   {"url.port", VAR_INPUT_URLPORT, CURLINFO_NONE, writeString},
136*6236dae4SAndroid Build Coastguard Worker   {"url.query", VAR_INPUT_URLQUERY, CURLINFO_NONE, writeString},
137*6236dae4SAndroid Build Coastguard Worker   {"url.scheme", VAR_INPUT_URLSCHEME, CURLINFO_NONE, writeString},
138*6236dae4SAndroid Build Coastguard Worker   {"url.user", VAR_INPUT_URLUSER, CURLINFO_NONE, writeString},
139*6236dae4SAndroid Build Coastguard Worker   {"url.zoneid", VAR_INPUT_URLZONEID, CURLINFO_NONE, writeString},
140*6236dae4SAndroid Build Coastguard Worker   {"url_effective", VAR_EFFECTIVE_URL, CURLINFO_EFFECTIVE_URL, writeString},
141*6236dae4SAndroid Build Coastguard Worker   {"urle.fragment", VAR_INPUT_URLEFRAGMENT, CURLINFO_NONE, writeString},
142*6236dae4SAndroid Build Coastguard Worker   {"urle.host", VAR_INPUT_URLEHOST, CURLINFO_NONE, writeString},
143*6236dae4SAndroid Build Coastguard Worker   {"urle.options", VAR_INPUT_URLEOPTIONS, CURLINFO_NONE, writeString},
144*6236dae4SAndroid Build Coastguard Worker   {"urle.password", VAR_INPUT_URLEPASSWORD, CURLINFO_NONE, writeString},
145*6236dae4SAndroid Build Coastguard Worker   {"urle.path", VAR_INPUT_URLEPATH, CURLINFO_NONE, writeString},
146*6236dae4SAndroid Build Coastguard Worker   {"urle.port", VAR_INPUT_URLEPORT, CURLINFO_NONE, writeString},
147*6236dae4SAndroid Build Coastguard Worker   {"urle.query", VAR_INPUT_URLEQUERY, CURLINFO_NONE, writeString},
148*6236dae4SAndroid Build Coastguard Worker   {"urle.scheme", VAR_INPUT_URLESCHEME, CURLINFO_NONE, writeString},
149*6236dae4SAndroid Build Coastguard Worker   {"urle.user", VAR_INPUT_URLEUSER, CURLINFO_NONE, writeString},
150*6236dae4SAndroid Build Coastguard Worker   {"urle.zoneid", VAR_INPUT_URLEZONEID, CURLINFO_NONE, writeString},
151*6236dae4SAndroid Build Coastguard Worker   {"urlnum", VAR_URLNUM, CURLINFO_NONE, writeLong},
152*6236dae4SAndroid Build Coastguard Worker   {"xfer_id", VAR_EASY_ID, CURLINFO_XFER_ID, writeOffset}
153*6236dae4SAndroid Build Coastguard Worker };
154*6236dae4SAndroid Build Coastguard Worker 
writeTime(FILE * stream,const struct writeoutvar * wovar,struct per_transfer * per,CURLcode per_result,bool use_json)155*6236dae4SAndroid Build Coastguard Worker static int writeTime(FILE *stream, const struct writeoutvar *wovar,
156*6236dae4SAndroid Build Coastguard Worker                      struct per_transfer *per, CURLcode per_result,
157*6236dae4SAndroid Build Coastguard Worker                      bool use_json)
158*6236dae4SAndroid Build Coastguard Worker {
159*6236dae4SAndroid Build Coastguard Worker   bool valid = false;
160*6236dae4SAndroid Build Coastguard Worker   curl_off_t us = 0;
161*6236dae4SAndroid Build Coastguard Worker 
162*6236dae4SAndroid Build Coastguard Worker   (void)per;
163*6236dae4SAndroid Build Coastguard Worker   (void)per_result;
164*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(wovar->writefunc == writeTime);
165*6236dae4SAndroid Build Coastguard Worker 
166*6236dae4SAndroid Build Coastguard Worker   if(wovar->ci) {
167*6236dae4SAndroid Build Coastguard Worker     if(!curl_easy_getinfo(per->curl, wovar->ci, &us))
168*6236dae4SAndroid Build Coastguard Worker       valid = true;
169*6236dae4SAndroid Build Coastguard Worker   }
170*6236dae4SAndroid Build Coastguard Worker   else {
171*6236dae4SAndroid Build Coastguard Worker     DEBUGASSERT(0);
172*6236dae4SAndroid Build Coastguard Worker   }
173*6236dae4SAndroid Build Coastguard Worker 
174*6236dae4SAndroid Build Coastguard Worker   if(valid) {
175*6236dae4SAndroid Build Coastguard Worker     curl_off_t secs = us / 1000000;
176*6236dae4SAndroid Build Coastguard Worker     us %= 1000000;
177*6236dae4SAndroid Build Coastguard Worker 
178*6236dae4SAndroid Build Coastguard Worker     if(use_json)
179*6236dae4SAndroid Build Coastguard Worker       fprintf(stream, "\"%s\":", wovar->name);
180*6236dae4SAndroid Build Coastguard Worker 
181*6236dae4SAndroid Build Coastguard Worker     fprintf(stream, "%" CURL_FORMAT_CURL_OFF_TU
182*6236dae4SAndroid Build Coastguard Worker             ".%06" CURL_FORMAT_CURL_OFF_TU, secs, us);
183*6236dae4SAndroid Build Coastguard Worker   }
184*6236dae4SAndroid Build Coastguard Worker   else {
185*6236dae4SAndroid Build Coastguard Worker     if(use_json)
186*6236dae4SAndroid Build Coastguard Worker       fprintf(stream, "\"%s\":null", wovar->name);
187*6236dae4SAndroid Build Coastguard Worker   }
188*6236dae4SAndroid Build Coastguard Worker 
189*6236dae4SAndroid Build Coastguard Worker   return 1; /* return 1 if anything was written */
190*6236dae4SAndroid Build Coastguard Worker }
191*6236dae4SAndroid Build Coastguard Worker 
urlpart(struct per_transfer * per,writeoutid vid,const char ** contentp)192*6236dae4SAndroid Build Coastguard Worker static int urlpart(struct per_transfer *per, writeoutid vid,
193*6236dae4SAndroid Build Coastguard Worker                    const char **contentp)
194*6236dae4SAndroid Build Coastguard Worker {
195*6236dae4SAndroid Build Coastguard Worker   CURLU *uh = curl_url();
196*6236dae4SAndroid Build Coastguard Worker   int rc = 0;
197*6236dae4SAndroid Build Coastguard Worker   if(uh) {
198*6236dae4SAndroid Build Coastguard Worker     CURLUPart cpart = CURLUPART_HOST;
199*6236dae4SAndroid Build Coastguard Worker     char *part = NULL;
200*6236dae4SAndroid Build Coastguard Worker     const char *url = NULL;
201*6236dae4SAndroid Build Coastguard Worker 
202*6236dae4SAndroid Build Coastguard Worker     if(vid >= VAR_INPUT_URLESCHEME) {
203*6236dae4SAndroid Build Coastguard Worker       if(curl_easy_getinfo(per->curl, CURLINFO_EFFECTIVE_URL, &url))
204*6236dae4SAndroid Build Coastguard Worker         rc = 5;
205*6236dae4SAndroid Build Coastguard Worker     }
206*6236dae4SAndroid Build Coastguard Worker     else
207*6236dae4SAndroid Build Coastguard Worker       url = per->url;
208*6236dae4SAndroid Build Coastguard Worker 
209*6236dae4SAndroid Build Coastguard Worker     if(!rc) {
210*6236dae4SAndroid Build Coastguard Worker       switch(vid) {
211*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLSCHEME:
212*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLESCHEME:
213*6236dae4SAndroid Build Coastguard Worker         cpart = CURLUPART_SCHEME;
214*6236dae4SAndroid Build Coastguard Worker         break;
215*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLUSER:
216*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLEUSER:
217*6236dae4SAndroid Build Coastguard Worker         cpart = CURLUPART_USER;
218*6236dae4SAndroid Build Coastguard Worker         break;
219*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLPASSWORD:
220*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLEPASSWORD:
221*6236dae4SAndroid Build Coastguard Worker         cpart = CURLUPART_PASSWORD;
222*6236dae4SAndroid Build Coastguard Worker         break;
223*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLOPTIONS:
224*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLEOPTIONS:
225*6236dae4SAndroid Build Coastguard Worker         cpart = CURLUPART_OPTIONS;
226*6236dae4SAndroid Build Coastguard Worker         break;
227*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLHOST:
228*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLEHOST:
229*6236dae4SAndroid Build Coastguard Worker         cpart = CURLUPART_HOST;
230*6236dae4SAndroid Build Coastguard Worker         break;
231*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLPORT:
232*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLEPORT:
233*6236dae4SAndroid Build Coastguard Worker         cpart = CURLUPART_PORT;
234*6236dae4SAndroid Build Coastguard Worker         break;
235*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLPATH:
236*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLEPATH:
237*6236dae4SAndroid Build Coastguard Worker         cpart = CURLUPART_PATH;
238*6236dae4SAndroid Build Coastguard Worker         break;
239*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLQUERY:
240*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLEQUERY:
241*6236dae4SAndroid Build Coastguard Worker         cpart = CURLUPART_QUERY;
242*6236dae4SAndroid Build Coastguard Worker         break;
243*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLFRAGMENT:
244*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLEFRAGMENT:
245*6236dae4SAndroid Build Coastguard Worker         cpart = CURLUPART_FRAGMENT;
246*6236dae4SAndroid Build Coastguard Worker         break;
247*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLZONEID:
248*6236dae4SAndroid Build Coastguard Worker       case VAR_INPUT_URLEZONEID:
249*6236dae4SAndroid Build Coastguard Worker         cpart = CURLUPART_ZONEID;
250*6236dae4SAndroid Build Coastguard Worker         break;
251*6236dae4SAndroid Build Coastguard Worker       default:
252*6236dae4SAndroid Build Coastguard Worker         /* not implemented */
253*6236dae4SAndroid Build Coastguard Worker         rc = 4;
254*6236dae4SAndroid Build Coastguard Worker         break;
255*6236dae4SAndroid Build Coastguard Worker       }
256*6236dae4SAndroid Build Coastguard Worker     }
257*6236dae4SAndroid Build Coastguard Worker     if(!rc && curl_url_set(uh, CURLUPART_URL, url,
258*6236dae4SAndroid Build Coastguard Worker                            CURLU_GUESS_SCHEME|CURLU_NON_SUPPORT_SCHEME))
259*6236dae4SAndroid Build Coastguard Worker       rc = 2;
260*6236dae4SAndroid Build Coastguard Worker 
261*6236dae4SAndroid Build Coastguard Worker     if(!rc && curl_url_get(uh, cpart, &part, CURLU_DEFAULT_PORT))
262*6236dae4SAndroid Build Coastguard Worker       rc = 3;
263*6236dae4SAndroid Build Coastguard Worker 
264*6236dae4SAndroid Build Coastguard Worker     if(!rc && part)
265*6236dae4SAndroid Build Coastguard Worker       *contentp = part;
266*6236dae4SAndroid Build Coastguard Worker     curl_url_cleanup(uh);
267*6236dae4SAndroid Build Coastguard Worker   }
268*6236dae4SAndroid Build Coastguard Worker   else
269*6236dae4SAndroid Build Coastguard Worker     return 1;
270*6236dae4SAndroid Build Coastguard Worker   return rc;
271*6236dae4SAndroid Build Coastguard Worker }
272*6236dae4SAndroid Build Coastguard Worker 
certinfo(struct per_transfer * per)273*6236dae4SAndroid Build Coastguard Worker static void certinfo(struct per_transfer *per)
274*6236dae4SAndroid Build Coastguard Worker {
275*6236dae4SAndroid Build Coastguard Worker   if(!per->certinfo) {
276*6236dae4SAndroid Build Coastguard Worker     struct curl_certinfo *certinfo;
277*6236dae4SAndroid Build Coastguard Worker     CURLcode res = curl_easy_getinfo(per->curl, CURLINFO_CERTINFO, &certinfo);
278*6236dae4SAndroid Build Coastguard Worker     per->certinfo = (!res && certinfo) ? certinfo : NULL;
279*6236dae4SAndroid Build Coastguard Worker   }
280*6236dae4SAndroid Build Coastguard Worker }
281*6236dae4SAndroid Build Coastguard Worker 
writeString(FILE * stream,const struct writeoutvar * wovar,struct per_transfer * per,CURLcode per_result,bool use_json)282*6236dae4SAndroid Build Coastguard Worker static int writeString(FILE *stream, const struct writeoutvar *wovar,
283*6236dae4SAndroid Build Coastguard Worker                        struct per_transfer *per, CURLcode per_result,
284*6236dae4SAndroid Build Coastguard Worker                        bool use_json)
285*6236dae4SAndroid Build Coastguard Worker {
286*6236dae4SAndroid Build Coastguard Worker   bool valid = false;
287*6236dae4SAndroid Build Coastguard Worker   const char *strinfo = NULL;
288*6236dae4SAndroid Build Coastguard Worker   const char *freestr = NULL;
289*6236dae4SAndroid Build Coastguard Worker   struct dynbuf buf;
290*6236dae4SAndroid Build Coastguard Worker   curlx_dyn_init(&buf, 256*1024);
291*6236dae4SAndroid Build Coastguard Worker 
292*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(wovar->writefunc == writeString);
293*6236dae4SAndroid Build Coastguard Worker 
294*6236dae4SAndroid Build Coastguard Worker   if(wovar->ci) {
295*6236dae4SAndroid Build Coastguard Worker     if(wovar->ci == CURLINFO_HTTP_VERSION) {
296*6236dae4SAndroid Build Coastguard Worker       long version = 0;
297*6236dae4SAndroid Build Coastguard Worker       if(!curl_easy_getinfo(per->curl, CURLINFO_HTTP_VERSION, &version)) {
298*6236dae4SAndroid Build Coastguard Worker         const struct httpmap *m = &http_version[0];
299*6236dae4SAndroid Build Coastguard Worker         while(m->str) {
300*6236dae4SAndroid Build Coastguard Worker           if(m->num == version) {
301*6236dae4SAndroid Build Coastguard Worker             strinfo = m->str;
302*6236dae4SAndroid Build Coastguard Worker             valid = true;
303*6236dae4SAndroid Build Coastguard Worker             break;
304*6236dae4SAndroid Build Coastguard Worker           }
305*6236dae4SAndroid Build Coastguard Worker           m++;
306*6236dae4SAndroid Build Coastguard Worker         }
307*6236dae4SAndroid Build Coastguard Worker       }
308*6236dae4SAndroid Build Coastguard Worker     }
309*6236dae4SAndroid Build Coastguard Worker     else {
310*6236dae4SAndroid Build Coastguard Worker       if(!curl_easy_getinfo(per->curl, wovar->ci, &strinfo) && strinfo)
311*6236dae4SAndroid Build Coastguard Worker         valid = true;
312*6236dae4SAndroid Build Coastguard Worker     }
313*6236dae4SAndroid Build Coastguard Worker   }
314*6236dae4SAndroid Build Coastguard Worker   else {
315*6236dae4SAndroid Build Coastguard Worker     switch(wovar->id) {
316*6236dae4SAndroid Build Coastguard Worker     case VAR_CERT:
317*6236dae4SAndroid Build Coastguard Worker       certinfo(per);
318*6236dae4SAndroid Build Coastguard Worker       if(per->certinfo) {
319*6236dae4SAndroid Build Coastguard Worker         int i;
320*6236dae4SAndroid Build Coastguard Worker         bool error = FALSE;
321*6236dae4SAndroid Build Coastguard Worker         for(i = 0; (i < per->certinfo->num_of_certs) && !error; i++) {
322*6236dae4SAndroid Build Coastguard Worker           struct curl_slist *slist;
323*6236dae4SAndroid Build Coastguard Worker 
324*6236dae4SAndroid Build Coastguard Worker           for(slist = per->certinfo->certinfo[i]; slist; slist = slist->next) {
325*6236dae4SAndroid Build Coastguard Worker             size_t len;
326*6236dae4SAndroid Build Coastguard Worker             if(curl_strnequal(slist->data, "cert:", 5)) {
327*6236dae4SAndroid Build Coastguard Worker               if(curlx_dyn_add(&buf, &slist->data[5])) {
328*6236dae4SAndroid Build Coastguard Worker                 error = TRUE;
329*6236dae4SAndroid Build Coastguard Worker                 break;
330*6236dae4SAndroid Build Coastguard Worker               }
331*6236dae4SAndroid Build Coastguard Worker             }
332*6236dae4SAndroid Build Coastguard Worker             else {
333*6236dae4SAndroid Build Coastguard Worker               if(curlx_dyn_add(&buf, slist->data)) {
334*6236dae4SAndroid Build Coastguard Worker                 error = TRUE;
335*6236dae4SAndroid Build Coastguard Worker                 break;
336*6236dae4SAndroid Build Coastguard Worker               }
337*6236dae4SAndroid Build Coastguard Worker             }
338*6236dae4SAndroid Build Coastguard Worker             len = curlx_dyn_len(&buf);
339*6236dae4SAndroid Build Coastguard Worker             if(len) {
340*6236dae4SAndroid Build Coastguard Worker               char *ptr = curlx_dyn_ptr(&buf);
341*6236dae4SAndroid Build Coastguard Worker               if(ptr[len -1] != '\n') {
342*6236dae4SAndroid Build Coastguard Worker                 /* add a newline to make things look better */
343*6236dae4SAndroid Build Coastguard Worker                 if(curlx_dyn_addn(&buf, "\n", 1)) {
344*6236dae4SAndroid Build Coastguard Worker                   error = TRUE;
345*6236dae4SAndroid Build Coastguard Worker                   break;
346*6236dae4SAndroid Build Coastguard Worker                 }
347*6236dae4SAndroid Build Coastguard Worker               }
348*6236dae4SAndroid Build Coastguard Worker             }
349*6236dae4SAndroid Build Coastguard Worker           }
350*6236dae4SAndroid Build Coastguard Worker         }
351*6236dae4SAndroid Build Coastguard Worker         if(!error) {
352*6236dae4SAndroid Build Coastguard Worker           strinfo = curlx_dyn_ptr(&buf);
353*6236dae4SAndroid Build Coastguard Worker           if(!strinfo)
354*6236dae4SAndroid Build Coastguard Worker             /* maybe not a TLS protocol */
355*6236dae4SAndroid Build Coastguard Worker             strinfo = "";
356*6236dae4SAndroid Build Coastguard Worker           valid = true;
357*6236dae4SAndroid Build Coastguard Worker         }
358*6236dae4SAndroid Build Coastguard Worker       }
359*6236dae4SAndroid Build Coastguard Worker       else
360*6236dae4SAndroid Build Coastguard Worker         strinfo = ""; /* no cert info */
361*6236dae4SAndroid Build Coastguard Worker       break;
362*6236dae4SAndroid Build Coastguard Worker     case VAR_ERRORMSG:
363*6236dae4SAndroid Build Coastguard Worker       if(per_result) {
364*6236dae4SAndroid Build Coastguard Worker         strinfo = (per->errorbuffer && per->errorbuffer[0]) ?
365*6236dae4SAndroid Build Coastguard Worker           per->errorbuffer : curl_easy_strerror(per_result);
366*6236dae4SAndroid Build Coastguard Worker         valid = true;
367*6236dae4SAndroid Build Coastguard Worker       }
368*6236dae4SAndroid Build Coastguard Worker       break;
369*6236dae4SAndroid Build Coastguard Worker     case VAR_EFFECTIVE_FILENAME:
370*6236dae4SAndroid Build Coastguard Worker       if(per->outs.filename) {
371*6236dae4SAndroid Build Coastguard Worker         strinfo = per->outs.filename;
372*6236dae4SAndroid Build Coastguard Worker         valid = true;
373*6236dae4SAndroid Build Coastguard Worker       }
374*6236dae4SAndroid Build Coastguard Worker       break;
375*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URL:
376*6236dae4SAndroid Build Coastguard Worker       if(per->url) {
377*6236dae4SAndroid Build Coastguard Worker         strinfo = per->url;
378*6236dae4SAndroid Build Coastguard Worker         valid = true;
379*6236dae4SAndroid Build Coastguard Worker       }
380*6236dae4SAndroid Build Coastguard Worker       break;
381*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLSCHEME:
382*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLUSER:
383*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLPASSWORD:
384*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLOPTIONS:
385*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLHOST:
386*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLPORT:
387*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLPATH:
388*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLQUERY:
389*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLFRAGMENT:
390*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLZONEID:
391*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLESCHEME:
392*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLEUSER:
393*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLEPASSWORD:
394*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLEOPTIONS:
395*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLEHOST:
396*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLEPORT:
397*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLEPATH:
398*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLEQUERY:
399*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLEFRAGMENT:
400*6236dae4SAndroid Build Coastguard Worker     case VAR_INPUT_URLEZONEID:
401*6236dae4SAndroid Build Coastguard Worker       if(per->url) {
402*6236dae4SAndroid Build Coastguard Worker         if(!urlpart(per, wovar->id, &strinfo)) {
403*6236dae4SAndroid Build Coastguard Worker           freestr = strinfo;
404*6236dae4SAndroid Build Coastguard Worker           valid = true;
405*6236dae4SAndroid Build Coastguard Worker         }
406*6236dae4SAndroid Build Coastguard Worker       }
407*6236dae4SAndroid Build Coastguard Worker       break;
408*6236dae4SAndroid Build Coastguard Worker     default:
409*6236dae4SAndroid Build Coastguard Worker       DEBUGASSERT(0);
410*6236dae4SAndroid Build Coastguard Worker       break;
411*6236dae4SAndroid Build Coastguard Worker     }
412*6236dae4SAndroid Build Coastguard Worker   }
413*6236dae4SAndroid Build Coastguard Worker 
414*6236dae4SAndroid Build Coastguard Worker   if(valid) {
415*6236dae4SAndroid Build Coastguard Worker     DEBUGASSERT(strinfo);
416*6236dae4SAndroid Build Coastguard Worker     if(use_json) {
417*6236dae4SAndroid Build Coastguard Worker       fprintf(stream, "\"%s\":", wovar->name);
418*6236dae4SAndroid Build Coastguard Worker       jsonWriteString(stream, strinfo, FALSE);
419*6236dae4SAndroid Build Coastguard Worker     }
420*6236dae4SAndroid Build Coastguard Worker     else
421*6236dae4SAndroid Build Coastguard Worker       fputs(strinfo, stream);
422*6236dae4SAndroid Build Coastguard Worker   }
423*6236dae4SAndroid Build Coastguard Worker   else {
424*6236dae4SAndroid Build Coastguard Worker     if(use_json)
425*6236dae4SAndroid Build Coastguard Worker       fprintf(stream, "\"%s\":null", wovar->name);
426*6236dae4SAndroid Build Coastguard Worker   }
427*6236dae4SAndroid Build Coastguard Worker   curl_free((char *)freestr);
428*6236dae4SAndroid Build Coastguard Worker 
429*6236dae4SAndroid Build Coastguard Worker   curlx_dyn_free(&buf);
430*6236dae4SAndroid Build Coastguard Worker   return 1; /* return 1 if anything was written */
431*6236dae4SAndroid Build Coastguard Worker }
432*6236dae4SAndroid Build Coastguard Worker 
writeLong(FILE * stream,const struct writeoutvar * wovar,struct per_transfer * per,CURLcode per_result,bool use_json)433*6236dae4SAndroid Build Coastguard Worker static int writeLong(FILE *stream, const struct writeoutvar *wovar,
434*6236dae4SAndroid Build Coastguard Worker                      struct per_transfer *per, CURLcode per_result,
435*6236dae4SAndroid Build Coastguard Worker                      bool use_json)
436*6236dae4SAndroid Build Coastguard Worker {
437*6236dae4SAndroid Build Coastguard Worker   bool valid = false;
438*6236dae4SAndroid Build Coastguard Worker   long longinfo = 0;
439*6236dae4SAndroid Build Coastguard Worker 
440*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(wovar->writefunc == writeLong);
441*6236dae4SAndroid Build Coastguard Worker 
442*6236dae4SAndroid Build Coastguard Worker   if(wovar->ci) {
443*6236dae4SAndroid Build Coastguard Worker     if(!curl_easy_getinfo(per->curl, wovar->ci, &longinfo))
444*6236dae4SAndroid Build Coastguard Worker       valid = true;
445*6236dae4SAndroid Build Coastguard Worker   }
446*6236dae4SAndroid Build Coastguard Worker   else {
447*6236dae4SAndroid Build Coastguard Worker     switch(wovar->id) {
448*6236dae4SAndroid Build Coastguard Worker     case VAR_NUM_RETRY:
449*6236dae4SAndroid Build Coastguard Worker       longinfo = per->num_retries;
450*6236dae4SAndroid Build Coastguard Worker       valid = true;
451*6236dae4SAndroid Build Coastguard Worker       break;
452*6236dae4SAndroid Build Coastguard Worker     case VAR_NUM_CERTS:
453*6236dae4SAndroid Build Coastguard Worker       certinfo(per);
454*6236dae4SAndroid Build Coastguard Worker       longinfo = per->certinfo ? per->certinfo->num_of_certs : 0;
455*6236dae4SAndroid Build Coastguard Worker       valid = true;
456*6236dae4SAndroid Build Coastguard Worker       break;
457*6236dae4SAndroid Build Coastguard Worker     case VAR_NUM_HEADERS:
458*6236dae4SAndroid Build Coastguard Worker       longinfo = per->num_headers;
459*6236dae4SAndroid Build Coastguard Worker       valid = true;
460*6236dae4SAndroid Build Coastguard Worker       break;
461*6236dae4SAndroid Build Coastguard Worker     case VAR_EXITCODE:
462*6236dae4SAndroid Build Coastguard Worker       longinfo = (long)per_result;
463*6236dae4SAndroid Build Coastguard Worker       valid = true;
464*6236dae4SAndroid Build Coastguard Worker       break;
465*6236dae4SAndroid Build Coastguard Worker     case VAR_URLNUM:
466*6236dae4SAndroid Build Coastguard Worker       if(per->urlnum <= INT_MAX) {
467*6236dae4SAndroid Build Coastguard Worker         longinfo = (long)per->urlnum;
468*6236dae4SAndroid Build Coastguard Worker         valid = true;
469*6236dae4SAndroid Build Coastguard Worker       }
470*6236dae4SAndroid Build Coastguard Worker       break;
471*6236dae4SAndroid Build Coastguard Worker     default:
472*6236dae4SAndroid Build Coastguard Worker       DEBUGASSERT(0);
473*6236dae4SAndroid Build Coastguard Worker       break;
474*6236dae4SAndroid Build Coastguard Worker     }
475*6236dae4SAndroid Build Coastguard Worker   }
476*6236dae4SAndroid Build Coastguard Worker 
477*6236dae4SAndroid Build Coastguard Worker   if(valid) {
478*6236dae4SAndroid Build Coastguard Worker     if(use_json)
479*6236dae4SAndroid Build Coastguard Worker       fprintf(stream, "\"%s\":%ld", wovar->name, longinfo);
480*6236dae4SAndroid Build Coastguard Worker     else {
481*6236dae4SAndroid Build Coastguard Worker       if(wovar->id == VAR_HTTP_CODE || wovar->id == VAR_HTTP_CODE_PROXY)
482*6236dae4SAndroid Build Coastguard Worker         fprintf(stream, "%03ld", longinfo);
483*6236dae4SAndroid Build Coastguard Worker       else
484*6236dae4SAndroid Build Coastguard Worker         fprintf(stream, "%ld", longinfo);
485*6236dae4SAndroid Build Coastguard Worker     }
486*6236dae4SAndroid Build Coastguard Worker   }
487*6236dae4SAndroid Build Coastguard Worker   else {
488*6236dae4SAndroid Build Coastguard Worker     if(use_json)
489*6236dae4SAndroid Build Coastguard Worker       fprintf(stream, "\"%s\":null", wovar->name);
490*6236dae4SAndroid Build Coastguard Worker   }
491*6236dae4SAndroid Build Coastguard Worker 
492*6236dae4SAndroid Build Coastguard Worker   return 1; /* return 1 if anything was written */
493*6236dae4SAndroid Build Coastguard Worker }
494*6236dae4SAndroid Build Coastguard Worker 
writeOffset(FILE * stream,const struct writeoutvar * wovar,struct per_transfer * per,CURLcode per_result,bool use_json)495*6236dae4SAndroid Build Coastguard Worker static int writeOffset(FILE *stream, const struct writeoutvar *wovar,
496*6236dae4SAndroid Build Coastguard Worker                        struct per_transfer *per, CURLcode per_result,
497*6236dae4SAndroid Build Coastguard Worker                        bool use_json)
498*6236dae4SAndroid Build Coastguard Worker {
499*6236dae4SAndroid Build Coastguard Worker   bool valid = false;
500*6236dae4SAndroid Build Coastguard Worker   curl_off_t offinfo = 0;
501*6236dae4SAndroid Build Coastguard Worker 
502*6236dae4SAndroid Build Coastguard Worker   (void)per;
503*6236dae4SAndroid Build Coastguard Worker   (void)per_result;
504*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(wovar->writefunc == writeOffset);
505*6236dae4SAndroid Build Coastguard Worker 
506*6236dae4SAndroid Build Coastguard Worker   if(wovar->ci) {
507*6236dae4SAndroid Build Coastguard Worker     if(!curl_easy_getinfo(per->curl, wovar->ci, &offinfo))
508*6236dae4SAndroid Build Coastguard Worker       valid = true;
509*6236dae4SAndroid Build Coastguard Worker   }
510*6236dae4SAndroid Build Coastguard Worker   else {
511*6236dae4SAndroid Build Coastguard Worker     DEBUGASSERT(0);
512*6236dae4SAndroid Build Coastguard Worker   }
513*6236dae4SAndroid Build Coastguard Worker 
514*6236dae4SAndroid Build Coastguard Worker   if(valid) {
515*6236dae4SAndroid Build Coastguard Worker     if(use_json)
516*6236dae4SAndroid Build Coastguard Worker       fprintf(stream, "\"%s\":", wovar->name);
517*6236dae4SAndroid Build Coastguard Worker 
518*6236dae4SAndroid Build Coastguard Worker     fprintf(stream, "%" CURL_FORMAT_CURL_OFF_T, offinfo);
519*6236dae4SAndroid Build Coastguard Worker   }
520*6236dae4SAndroid Build Coastguard Worker   else {
521*6236dae4SAndroid Build Coastguard Worker     if(use_json)
522*6236dae4SAndroid Build Coastguard Worker       fprintf(stream, "\"%s\":null", wovar->name);
523*6236dae4SAndroid Build Coastguard Worker   }
524*6236dae4SAndroid Build Coastguard Worker 
525*6236dae4SAndroid Build Coastguard Worker   return 1; /* return 1 if anything was written */
526*6236dae4SAndroid Build Coastguard Worker }
527*6236dae4SAndroid Build Coastguard Worker 
528*6236dae4SAndroid Build Coastguard Worker static int
matchvar(const void * m1,const void * m2)529*6236dae4SAndroid Build Coastguard Worker matchvar(const void *m1, const void *m2)
530*6236dae4SAndroid Build Coastguard Worker {
531*6236dae4SAndroid Build Coastguard Worker   const struct writeoutvar *v1 = m1;
532*6236dae4SAndroid Build Coastguard Worker   const struct writeoutvar *v2 = m2;
533*6236dae4SAndroid Build Coastguard Worker 
534*6236dae4SAndroid Build Coastguard Worker   return strcmp(v1->name, v2->name);
535*6236dae4SAndroid Build Coastguard Worker }
536*6236dae4SAndroid Build Coastguard Worker 
537*6236dae4SAndroid Build Coastguard Worker #define MAX_WRITEOUT_NAME_LENGTH 24
538*6236dae4SAndroid Build Coastguard Worker 
ourWriteOut(struct OperationConfig * config,struct per_transfer * per,CURLcode per_result)539*6236dae4SAndroid Build Coastguard Worker void ourWriteOut(struct OperationConfig *config, struct per_transfer *per,
540*6236dae4SAndroid Build Coastguard Worker                  CURLcode per_result)
541*6236dae4SAndroid Build Coastguard Worker {
542*6236dae4SAndroid Build Coastguard Worker   FILE *stream = stdout;
543*6236dae4SAndroid Build Coastguard Worker   const char *writeinfo = config->writeout;
544*6236dae4SAndroid Build Coastguard Worker   const char *ptr = writeinfo;
545*6236dae4SAndroid Build Coastguard Worker   bool done = FALSE;
546*6236dae4SAndroid Build Coastguard Worker   bool fclose_stream = FALSE;
547*6236dae4SAndroid Build Coastguard Worker   struct dynbuf name;
548*6236dae4SAndroid Build Coastguard Worker 
549*6236dae4SAndroid Build Coastguard Worker   if(!writeinfo)
550*6236dae4SAndroid Build Coastguard Worker     return;
551*6236dae4SAndroid Build Coastguard Worker 
552*6236dae4SAndroid Build Coastguard Worker   curlx_dyn_init(&name, MAX_WRITEOUT_NAME_LENGTH);
553*6236dae4SAndroid Build Coastguard Worker   while(ptr && *ptr && !done) {
554*6236dae4SAndroid Build Coastguard Worker     if('%' == *ptr && ptr[1]) {
555*6236dae4SAndroid Build Coastguard Worker       if('%' == ptr[1]) {
556*6236dae4SAndroid Build Coastguard Worker         /* an escaped %-letter */
557*6236dae4SAndroid Build Coastguard Worker         fputc('%', stream);
558*6236dae4SAndroid Build Coastguard Worker         ptr += 2;
559*6236dae4SAndroid Build Coastguard Worker       }
560*6236dae4SAndroid Build Coastguard Worker       else {
561*6236dae4SAndroid Build Coastguard Worker         /* this is meant as a variable to output */
562*6236dae4SAndroid Build Coastguard Worker         char *end;
563*6236dae4SAndroid Build Coastguard Worker         size_t vlen;
564*6236dae4SAndroid Build Coastguard Worker         if('{' == ptr[1]) {
565*6236dae4SAndroid Build Coastguard Worker           struct writeoutvar *wv = NULL;
566*6236dae4SAndroid Build Coastguard Worker           struct writeoutvar find = { 0 };
567*6236dae4SAndroid Build Coastguard Worker           end = strchr(ptr, '}');
568*6236dae4SAndroid Build Coastguard Worker           ptr += 2; /* pass the % and the { */
569*6236dae4SAndroid Build Coastguard Worker           if(!end) {
570*6236dae4SAndroid Build Coastguard Worker             fputs("%{", stream);
571*6236dae4SAndroid Build Coastguard Worker             continue;
572*6236dae4SAndroid Build Coastguard Worker           }
573*6236dae4SAndroid Build Coastguard Worker           vlen = end - ptr;
574*6236dae4SAndroid Build Coastguard Worker 
575*6236dae4SAndroid Build Coastguard Worker           curlx_dyn_reset(&name);
576*6236dae4SAndroid Build Coastguard Worker           if(!curlx_dyn_addn(&name, ptr, vlen)) {
577*6236dae4SAndroid Build Coastguard Worker             find.name = curlx_dyn_ptr(&name);
578*6236dae4SAndroid Build Coastguard Worker             wv = bsearch(&find,
579*6236dae4SAndroid Build Coastguard Worker                          variables, sizeof(variables)/sizeof(variables[0]),
580*6236dae4SAndroid Build Coastguard Worker                          sizeof(variables[0]), matchvar);
581*6236dae4SAndroid Build Coastguard Worker           }
582*6236dae4SAndroid Build Coastguard Worker           if(wv) {
583*6236dae4SAndroid Build Coastguard Worker             switch(wv->id) {
584*6236dae4SAndroid Build Coastguard Worker             case VAR_ONERROR:
585*6236dae4SAndroid Build Coastguard Worker               if(per_result == CURLE_OK)
586*6236dae4SAndroid Build Coastguard Worker                 /* this is not error so skip the rest */
587*6236dae4SAndroid Build Coastguard Worker                 done = TRUE;
588*6236dae4SAndroid Build Coastguard Worker               break;
589*6236dae4SAndroid Build Coastguard Worker             case VAR_STDOUT:
590*6236dae4SAndroid Build Coastguard Worker               if(fclose_stream)
591*6236dae4SAndroid Build Coastguard Worker                 fclose(stream);
592*6236dae4SAndroid Build Coastguard Worker               fclose_stream = FALSE;
593*6236dae4SAndroid Build Coastguard Worker               stream = stdout;
594*6236dae4SAndroid Build Coastguard Worker               break;
595*6236dae4SAndroid Build Coastguard Worker             case VAR_STDERR:
596*6236dae4SAndroid Build Coastguard Worker               if(fclose_stream)
597*6236dae4SAndroid Build Coastguard Worker                 fclose(stream);
598*6236dae4SAndroid Build Coastguard Worker               fclose_stream = FALSE;
599*6236dae4SAndroid Build Coastguard Worker               stream = tool_stderr;
600*6236dae4SAndroid Build Coastguard Worker               break;
601*6236dae4SAndroid Build Coastguard Worker             case VAR_JSON:
602*6236dae4SAndroid Build Coastguard Worker               ourWriteOutJSON(stream, variables,
603*6236dae4SAndroid Build Coastguard Worker                               sizeof(variables)/sizeof(variables[0]),
604*6236dae4SAndroid Build Coastguard Worker                               per, per_result);
605*6236dae4SAndroid Build Coastguard Worker               break;
606*6236dae4SAndroid Build Coastguard Worker             case VAR_HEADER_JSON:
607*6236dae4SAndroid Build Coastguard Worker               headerJSON(stream, per);
608*6236dae4SAndroid Build Coastguard Worker               break;
609*6236dae4SAndroid Build Coastguard Worker             default:
610*6236dae4SAndroid Build Coastguard Worker               (void)wv->writefunc(stream, wv, per, per_result, false);
611*6236dae4SAndroid Build Coastguard Worker               break;
612*6236dae4SAndroid Build Coastguard Worker             }
613*6236dae4SAndroid Build Coastguard Worker           }
614*6236dae4SAndroid Build Coastguard Worker           else {
615*6236dae4SAndroid Build Coastguard Worker             fprintf(tool_stderr,
616*6236dae4SAndroid Build Coastguard Worker                     "curl: unknown --write-out variable: '%.*s'\n",
617*6236dae4SAndroid Build Coastguard Worker                     (int)vlen, ptr);
618*6236dae4SAndroid Build Coastguard Worker           }
619*6236dae4SAndroid Build Coastguard Worker           ptr = end + 1; /* pass the end */
620*6236dae4SAndroid Build Coastguard Worker         }
621*6236dae4SAndroid Build Coastguard Worker         else if(!strncmp("header{", &ptr[1], 7)) {
622*6236dae4SAndroid Build Coastguard Worker           ptr += 8;
623*6236dae4SAndroid Build Coastguard Worker           end = strchr(ptr, '}');
624*6236dae4SAndroid Build Coastguard Worker           if(end) {
625*6236dae4SAndroid Build Coastguard Worker             char hname[256]; /* holds the longest header field name */
626*6236dae4SAndroid Build Coastguard Worker             struct curl_header *header;
627*6236dae4SAndroid Build Coastguard Worker             vlen = end - ptr;
628*6236dae4SAndroid Build Coastguard Worker             if(vlen < sizeof(hname)) {
629*6236dae4SAndroid Build Coastguard Worker               memcpy(hname, ptr, vlen);
630*6236dae4SAndroid Build Coastguard Worker               hname[vlen] = 0;
631*6236dae4SAndroid Build Coastguard Worker               if(CURLHE_OK == curl_easy_header(per->curl, hname, 0,
632*6236dae4SAndroid Build Coastguard Worker                                                CURLH_HEADER, -1, &header))
633*6236dae4SAndroid Build Coastguard Worker                 fputs(header->value, stream);
634*6236dae4SAndroid Build Coastguard Worker             }
635*6236dae4SAndroid Build Coastguard Worker             ptr = end + 1;
636*6236dae4SAndroid Build Coastguard Worker           }
637*6236dae4SAndroid Build Coastguard Worker           else
638*6236dae4SAndroid Build Coastguard Worker             fputs("%header{", stream);
639*6236dae4SAndroid Build Coastguard Worker         }
640*6236dae4SAndroid Build Coastguard Worker         else if(!strncmp("output{", &ptr[1], 7)) {
641*6236dae4SAndroid Build Coastguard Worker           bool append = FALSE;
642*6236dae4SAndroid Build Coastguard Worker           ptr += 8;
643*6236dae4SAndroid Build Coastguard Worker           if((ptr[0] == '>') && (ptr[1] == '>')) {
644*6236dae4SAndroid Build Coastguard Worker             append = TRUE;
645*6236dae4SAndroid Build Coastguard Worker             ptr += 2;
646*6236dae4SAndroid Build Coastguard Worker           }
647*6236dae4SAndroid Build Coastguard Worker           end = strchr(ptr, '}');
648*6236dae4SAndroid Build Coastguard Worker           if(end) {
649*6236dae4SAndroid Build Coastguard Worker             char fname[512]; /* holds the longest filename */
650*6236dae4SAndroid Build Coastguard Worker             size_t flen = end - ptr;
651*6236dae4SAndroid Build Coastguard Worker             if(flen < sizeof(fname)) {
652*6236dae4SAndroid Build Coastguard Worker               FILE *stream2;
653*6236dae4SAndroid Build Coastguard Worker               memcpy(fname, ptr, flen);
654*6236dae4SAndroid Build Coastguard Worker               fname[flen] = 0;
655*6236dae4SAndroid Build Coastguard Worker               stream2 = fopen(fname, append ? FOPEN_APPENDTEXT :
656*6236dae4SAndroid Build Coastguard Worker                               FOPEN_WRITETEXT);
657*6236dae4SAndroid Build Coastguard Worker               if(stream2) {
658*6236dae4SAndroid Build Coastguard Worker                 /* only change if the open worked */
659*6236dae4SAndroid Build Coastguard Worker                 if(fclose_stream)
660*6236dae4SAndroid Build Coastguard Worker                   fclose(stream);
661*6236dae4SAndroid Build Coastguard Worker                 stream = stream2;
662*6236dae4SAndroid Build Coastguard Worker                 fclose_stream = TRUE;
663*6236dae4SAndroid Build Coastguard Worker               }
664*6236dae4SAndroid Build Coastguard Worker             }
665*6236dae4SAndroid Build Coastguard Worker             ptr = end + 1;
666*6236dae4SAndroid Build Coastguard Worker           }
667*6236dae4SAndroid Build Coastguard Worker           else
668*6236dae4SAndroid Build Coastguard Worker             fputs("%output{", stream);
669*6236dae4SAndroid Build Coastguard Worker         }
670*6236dae4SAndroid Build Coastguard Worker         else {
671*6236dae4SAndroid Build Coastguard Worker           /* illegal syntax, then just output the characters that are used */
672*6236dae4SAndroid Build Coastguard Worker           fputc('%', stream);
673*6236dae4SAndroid Build Coastguard Worker           fputc(ptr[1], stream);
674*6236dae4SAndroid Build Coastguard Worker           ptr += 2;
675*6236dae4SAndroid Build Coastguard Worker         }
676*6236dae4SAndroid Build Coastguard Worker       }
677*6236dae4SAndroid Build Coastguard Worker     }
678*6236dae4SAndroid Build Coastguard Worker     else if('\\' == *ptr && ptr[1]) {
679*6236dae4SAndroid Build Coastguard Worker       switch(ptr[1]) {
680*6236dae4SAndroid Build Coastguard Worker       case 'r':
681*6236dae4SAndroid Build Coastguard Worker         fputc('\r', stream);
682*6236dae4SAndroid Build Coastguard Worker         break;
683*6236dae4SAndroid Build Coastguard Worker       case 'n':
684*6236dae4SAndroid Build Coastguard Worker         fputc('\n', stream);
685*6236dae4SAndroid Build Coastguard Worker         break;
686*6236dae4SAndroid Build Coastguard Worker       case 't':
687*6236dae4SAndroid Build Coastguard Worker         fputc('\t', stream);
688*6236dae4SAndroid Build Coastguard Worker         break;
689*6236dae4SAndroid Build Coastguard Worker       default:
690*6236dae4SAndroid Build Coastguard Worker         /* unknown, just output this */
691*6236dae4SAndroid Build Coastguard Worker         fputc(*ptr, stream);
692*6236dae4SAndroid Build Coastguard Worker         fputc(ptr[1], stream);
693*6236dae4SAndroid Build Coastguard Worker         break;
694*6236dae4SAndroid Build Coastguard Worker       }
695*6236dae4SAndroid Build Coastguard Worker       ptr += 2;
696*6236dae4SAndroid Build Coastguard Worker     }
697*6236dae4SAndroid Build Coastguard Worker     else {
698*6236dae4SAndroid Build Coastguard Worker       fputc(*ptr, stream);
699*6236dae4SAndroid Build Coastguard Worker       ptr++;
700*6236dae4SAndroid Build Coastguard Worker     }
701*6236dae4SAndroid Build Coastguard Worker   }
702*6236dae4SAndroid Build Coastguard Worker   if(fclose_stream)
703*6236dae4SAndroid Build Coastguard Worker     fclose(stream);
704*6236dae4SAndroid Build Coastguard Worker   curlx_dyn_free(&name);
705*6236dae4SAndroid Build Coastguard Worker }
706