1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at http://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22#include "tool_setup.h" 23 24#define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */ 25#include <curl/mprintf.h> 26 27#include "tool_cfgable.h" 28#include "tool_writeout.h" 29 30#include "memdebug.h" /* keep this as LAST include */ 31 32typedef enum { 33 VAR_NONE, /* must be the first */ 34 VAR_TOTAL_TIME, 35 VAR_NAMELOOKUP_TIME, 36 VAR_CONNECT_TIME, 37 VAR_APPCONNECT_TIME, 38 VAR_PRETRANSFER_TIME, 39 VAR_STARTTRANSFER_TIME, 40 VAR_SIZE_DOWNLOAD, 41 VAR_SIZE_UPLOAD, 42 VAR_SPEED_DOWNLOAD, 43 VAR_SPEED_UPLOAD, 44 VAR_HTTP_CODE, 45 VAR_HTTP_CODE_PROXY, 46 VAR_HEADER_SIZE, 47 VAR_REQUEST_SIZE, 48 VAR_EFFECTIVE_URL, 49 VAR_CONTENT_TYPE, 50 VAR_NUM_CONNECTS, 51 VAR_REDIRECT_TIME, 52 VAR_REDIRECT_COUNT, 53 VAR_FTP_ENTRY_PATH, 54 VAR_REDIRECT_URL, 55 VAR_SSL_VERIFY_RESULT, 56 VAR_EFFECTIVE_FILENAME, 57 VAR_PRIMARY_IP, 58 VAR_PRIMARY_PORT, 59 VAR_LOCAL_IP, 60 VAR_LOCAL_PORT, 61 VAR_NUM_OF_VARS /* must be the last */ 62} replaceid; 63 64struct variable { 65 const char *name; 66 replaceid id; 67}; 68 69 70static const struct variable replacements[]={ 71 {"url_effective", VAR_EFFECTIVE_URL}, 72 {"http_code", VAR_HTTP_CODE}, 73 {"response_code", VAR_HTTP_CODE}, 74 {"http_connect", VAR_HTTP_CODE_PROXY}, 75 {"time_total", VAR_TOTAL_TIME}, 76 {"time_namelookup", VAR_NAMELOOKUP_TIME}, 77 {"time_connect", VAR_CONNECT_TIME}, 78 {"time_appconnect", VAR_APPCONNECT_TIME}, 79 {"time_pretransfer", VAR_PRETRANSFER_TIME}, 80 {"time_starttransfer", VAR_STARTTRANSFER_TIME}, 81 {"size_header", VAR_HEADER_SIZE}, 82 {"size_request", VAR_REQUEST_SIZE}, 83 {"size_download", VAR_SIZE_DOWNLOAD}, 84 {"size_upload", VAR_SIZE_UPLOAD}, 85 {"speed_download", VAR_SPEED_DOWNLOAD}, 86 {"speed_upload", VAR_SPEED_UPLOAD}, 87 {"content_type", VAR_CONTENT_TYPE}, 88 {"num_connects", VAR_NUM_CONNECTS}, 89 {"time_redirect", VAR_REDIRECT_TIME}, 90 {"num_redirects", VAR_REDIRECT_COUNT}, 91 {"ftp_entry_path", VAR_FTP_ENTRY_PATH}, 92 {"redirect_url", VAR_REDIRECT_URL}, 93 {"ssl_verify_result", VAR_SSL_VERIFY_RESULT}, 94 {"filename_effective", VAR_EFFECTIVE_FILENAME}, 95 {"remote_ip", VAR_PRIMARY_IP}, 96 {"remote_port", VAR_PRIMARY_PORT}, 97 {"local_ip", VAR_LOCAL_IP}, 98 {"local_port", VAR_LOCAL_PORT}, 99 {NULL, VAR_NONE} 100}; 101 102void ourWriteOut(CURL *curl, struct OutStruct *outs, const char *writeinfo) 103{ 104 FILE *stream = stdout; 105 const char *ptr = writeinfo; 106 char *stringp; 107 long longinfo; 108 double doubleinfo; 109 110 while(ptr && *ptr) { 111 if('%' == *ptr) { 112 if('%' == ptr[1]) { 113 /* an escaped %-letter */ 114 fputc('%', stream); 115 ptr += 2; 116 } 117 else { 118 /* this is meant as a variable to output */ 119 char *end; 120 char keepit; 121 int i; 122 if(('{' == ptr[1]) && ((end = strchr(ptr, '}')) != NULL)) { 123 bool match = FALSE; 124 ptr += 2; /* pass the % and the { */ 125 keepit = *end; 126 *end = 0; /* zero terminate */ 127 for(i = 0; replacements[i].name; i++) { 128 if(curl_strequal(ptr, replacements[i].name)) { 129 match = TRUE; 130 switch(replacements[i].id) { 131 case VAR_EFFECTIVE_URL: 132 if((CURLE_OK == 133 curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &stringp)) 134 && stringp) 135 fputs(stringp, stream); 136 break; 137 case VAR_HTTP_CODE: 138 if(CURLE_OK == 139 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &longinfo)) 140 fprintf(stream, "%03ld", longinfo); 141 break; 142 case VAR_HTTP_CODE_PROXY: 143 if(CURLE_OK == 144 curl_easy_getinfo(curl, CURLINFO_HTTP_CONNECTCODE, 145 &longinfo)) 146 fprintf(stream, "%03ld", longinfo); 147 break; 148 case VAR_HEADER_SIZE: 149 if(CURLE_OK == 150 curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &longinfo)) 151 fprintf(stream, "%ld", longinfo); 152 break; 153 case VAR_REQUEST_SIZE: 154 if(CURLE_OK == 155 curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &longinfo)) 156 fprintf(stream, "%ld", longinfo); 157 break; 158 case VAR_NUM_CONNECTS: 159 if(CURLE_OK == 160 curl_easy_getinfo(curl, CURLINFO_NUM_CONNECTS, &longinfo)) 161 fprintf(stream, "%ld", longinfo); 162 break; 163 case VAR_REDIRECT_COUNT: 164 if(CURLE_OK == 165 curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &longinfo)) 166 fprintf(stream, "%ld", longinfo); 167 break; 168 case VAR_REDIRECT_TIME: 169 if(CURLE_OK == 170 curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME, 171 &doubleinfo)) 172 fprintf(stream, "%.3f", doubleinfo); 173 break; 174 case VAR_TOTAL_TIME: 175 if(CURLE_OK == 176 curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &doubleinfo)) 177 fprintf(stream, "%.3f", doubleinfo); 178 break; 179 case VAR_NAMELOOKUP_TIME: 180 if(CURLE_OK == 181 curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME, 182 &doubleinfo)) 183 fprintf(stream, "%.3f", doubleinfo); 184 break; 185 case VAR_CONNECT_TIME: 186 if(CURLE_OK == 187 curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &doubleinfo)) 188 fprintf(stream, "%.3f", doubleinfo); 189 break; 190 case VAR_APPCONNECT_TIME: 191 if(CURLE_OK == 192 curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, 193 &doubleinfo)) 194 fprintf(stream, "%.3f", doubleinfo); 195 break; 196 case VAR_PRETRANSFER_TIME: 197 if(CURLE_OK == 198 curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, 199 &doubleinfo)) 200 fprintf(stream, "%.3f", doubleinfo); 201 break; 202 case VAR_STARTTRANSFER_TIME: 203 if(CURLE_OK == 204 curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, 205 &doubleinfo)) 206 fprintf(stream, "%.3f", doubleinfo); 207 break; 208 case VAR_SIZE_UPLOAD: 209 if(CURLE_OK == 210 curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &doubleinfo)) 211 fprintf(stream, "%.0f", doubleinfo); 212 break; 213 case VAR_SIZE_DOWNLOAD: 214 if(CURLE_OK == 215 curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, 216 &doubleinfo)) 217 fprintf(stream, "%.0f", doubleinfo); 218 break; 219 case VAR_SPEED_DOWNLOAD: 220 if(CURLE_OK == 221 curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, 222 &doubleinfo)) 223 fprintf(stream, "%.3f", doubleinfo); 224 break; 225 case VAR_SPEED_UPLOAD: 226 if(CURLE_OK == 227 curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &doubleinfo)) 228 fprintf(stream, "%.3f", doubleinfo); 229 break; 230 case VAR_CONTENT_TYPE: 231 if((CURLE_OK == 232 curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &stringp)) 233 && stringp) 234 fputs(stringp, stream); 235 break; 236 case VAR_FTP_ENTRY_PATH: 237 if((CURLE_OK == 238 curl_easy_getinfo(curl, CURLINFO_FTP_ENTRY_PATH, &stringp)) 239 && stringp) 240 fputs(stringp, stream); 241 break; 242 case VAR_REDIRECT_URL: 243 if((CURLE_OK == 244 curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &stringp)) 245 && stringp) 246 fputs(stringp, stream); 247 break; 248 case VAR_SSL_VERIFY_RESULT: 249 if(CURLE_OK == 250 curl_easy_getinfo(curl, CURLINFO_SSL_VERIFYRESULT, 251 &longinfo)) 252 fprintf(stream, "%ld", longinfo); 253 break; 254 case VAR_EFFECTIVE_FILENAME: 255 if(outs->filename) 256 fprintf(stream, "%s", outs->filename); 257 break; 258 case VAR_PRIMARY_IP: 259 if(CURLE_OK == 260 curl_easy_getinfo(curl, CURLINFO_PRIMARY_IP, 261 &stringp)) 262 fprintf(stream, "%s", stringp); 263 break; 264 case VAR_PRIMARY_PORT: 265 if(CURLE_OK == 266 curl_easy_getinfo(curl, CURLINFO_PRIMARY_PORT, 267 &longinfo)) 268 fprintf(stream, "%ld", longinfo); 269 break; 270 case VAR_LOCAL_IP: 271 if(CURLE_OK == 272 curl_easy_getinfo(curl, CURLINFO_LOCAL_IP, 273 &stringp)) 274 fprintf(stream, "%s", stringp); 275 break; 276 case VAR_LOCAL_PORT: 277 if(CURLE_OK == 278 curl_easy_getinfo(curl, CURLINFO_LOCAL_PORT, 279 &longinfo)) 280 fprintf(stream, "%ld", longinfo); 281 break; 282 default: 283 break; 284 } 285 break; 286 } 287 } 288 if(!match) { 289 fprintf(stderr, "curl: unknown --write-out variable: '%s'\n", ptr); 290 } 291 ptr = end + 1; /* pass the end */ 292 *end = keepit; 293 } 294 else { 295 /* illegal syntax, then just output the characters that are used */ 296 fputc('%', stream); 297 fputc(ptr[1], stream); 298 ptr += 2; 299 } 300 } 301 } 302 else if('\\' == *ptr) { 303 switch(ptr[1]) { 304 case 'r': 305 fputc('\r', stream); 306 break; 307 case 'n': 308 fputc('\n', stream); 309 break; 310 case 't': 311 fputc('\t', stream); 312 break; 313 default: 314 /* unknown, just output this */ 315 fputc(*ptr, stream); 316 fputc(ptr[1], stream); 317 break; 318 } 319 ptr += 2; 320 } 321 else { 322 fputc(*ptr, stream); 323 ptr++; 324 } 325 } 326 327} 328