| /*************************************************************************** |
| * _ _ ____ _ |
| * Project ___| | | | _ \| | |
| * / __| | | | |_) | | |
| * | (__| |_| | _ <| |___ |
| * \___|\___/|_| \_\_____| |
| * |
| * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. |
| * |
| * This software is licensed as described in the file COPYING, which |
| * you should have received as part of this distribution. The terms |
| * are also available at http://curl.haxx.se/docs/copyright.html. |
| * |
| * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
| * copies of the Software, and permit persons to whom the Software is |
| * furnished to do so, under the terms of the COPYING file. |
| * |
| * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| * KIND, either express or implied. |
| * |
| ***************************************************************************/ |
| #include "setup.h" |
| |
| #include <curl/curl.h> |
| |
| #define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */ |
| #include <curl/mprintf.h> |
| |
| #include "tool_writeout.h" |
| |
| #include "memdebug.h" /* keep this as LAST include */ |
| |
| typedef enum { |
| VAR_NONE, /* must be the first */ |
| VAR_TOTAL_TIME, |
| VAR_NAMELOOKUP_TIME, |
| VAR_CONNECT_TIME, |
| VAR_APPCONNECT_TIME, |
| VAR_PRETRANSFER_TIME, |
| VAR_STARTTRANSFER_TIME, |
| VAR_SIZE_DOWNLOAD, |
| VAR_SIZE_UPLOAD, |
| VAR_SPEED_DOWNLOAD, |
| VAR_SPEED_UPLOAD, |
| VAR_HTTP_CODE, |
| VAR_HTTP_CODE_PROXY, |
| VAR_HEADER_SIZE, |
| VAR_REQUEST_SIZE, |
| VAR_EFFECTIVE_URL, |
| VAR_CONTENT_TYPE, |
| VAR_NUM_CONNECTS, |
| VAR_REDIRECT_TIME, |
| VAR_REDIRECT_COUNT, |
| VAR_FTP_ENTRY_PATH, |
| VAR_REDIRECT_URL, |
| VAR_SSL_VERIFY_RESULT, |
| VAR_NUM_OF_VARS /* must be the last */ |
| } replaceid; |
| |
| struct variable { |
| const char *name; |
| replaceid id; |
| }; |
| |
| |
| static const struct variable replacements[]={ |
| {"url_effective", VAR_EFFECTIVE_URL}, |
| {"http_code", VAR_HTTP_CODE}, |
| {"response_code", VAR_HTTP_CODE}, |
| {"http_connect", VAR_HTTP_CODE_PROXY}, |
| {"time_total", VAR_TOTAL_TIME}, |
| {"time_namelookup", VAR_NAMELOOKUP_TIME}, |
| {"time_connect", VAR_CONNECT_TIME}, |
| {"time_appconnect", VAR_APPCONNECT_TIME}, |
| {"time_pretransfer", VAR_PRETRANSFER_TIME}, |
| {"time_starttransfer", VAR_STARTTRANSFER_TIME}, |
| {"size_header", VAR_HEADER_SIZE}, |
| {"size_request", VAR_REQUEST_SIZE}, |
| {"size_download", VAR_SIZE_DOWNLOAD}, |
| {"size_upload", VAR_SIZE_UPLOAD}, |
| {"speed_download", VAR_SPEED_DOWNLOAD}, |
| {"speed_upload", VAR_SPEED_UPLOAD}, |
| {"content_type", VAR_CONTENT_TYPE}, |
| {"num_connects", VAR_NUM_CONNECTS}, |
| {"time_redirect", VAR_REDIRECT_TIME}, |
| {"num_redirects", VAR_REDIRECT_COUNT}, |
| {"ftp_entry_path", VAR_FTP_ENTRY_PATH}, |
| {"redirect_url", VAR_REDIRECT_URL}, |
| {"ssl_verify_result", VAR_SSL_VERIFY_RESULT}, |
| {NULL, VAR_NONE} |
| }; |
| |
| void ourWriteOut(CURL *curl, const char *writeinfo) |
| { |
| FILE *stream = stdout; |
| const char *ptr = writeinfo; |
| char *stringp; |
| long longinfo; |
| double doubleinfo; |
| |
| while(ptr && *ptr) { |
| if('%' == *ptr) { |
| if('%' == ptr[1]) { |
| /* an escaped %-letter */ |
| fputc('%', stream); |
| ptr += 2; |
| } |
| else { |
| /* this is meant as a variable to output */ |
| char *end; |
| char keepit; |
| int i; |
| if(('{' == ptr[1]) && ((end = strchr(ptr, '}')) != NULL)) { |
| bool match = FALSE; |
| ptr += 2; /* pass the % and the { */ |
| keepit = *end; |
| *end = 0; /* zero terminate */ |
| for(i = 0; replacements[i].name; i++) { |
| if(curl_strequal(ptr, replacements[i].name)) { |
| match = TRUE; |
| switch(replacements[i].id) { |
| case VAR_EFFECTIVE_URL: |
| if((CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &stringp)) |
| && stringp) |
| fputs(stringp, stream); |
| break; |
| case VAR_HTTP_CODE: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &longinfo)) |
| fprintf(stream, "%03ld", longinfo); |
| break; |
| case VAR_HTTP_CODE_PROXY: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_HTTP_CONNECTCODE, |
| &longinfo)) |
| fprintf(stream, "%03ld", longinfo); |
| break; |
| case VAR_HEADER_SIZE: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &longinfo)) |
| fprintf(stream, "%ld", longinfo); |
| break; |
| case VAR_REQUEST_SIZE: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &longinfo)) |
| fprintf(stream, "%ld", longinfo); |
| break; |
| case VAR_NUM_CONNECTS: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_NUM_CONNECTS, &longinfo)) |
| fprintf(stream, "%ld", longinfo); |
| break; |
| case VAR_REDIRECT_COUNT: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &longinfo)) |
| fprintf(stream, "%ld", longinfo); |
| break; |
| case VAR_REDIRECT_TIME: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME, |
| &doubleinfo)) |
| fprintf(stream, "%.3f", doubleinfo); |
| break; |
| case VAR_TOTAL_TIME: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &doubleinfo)) |
| fprintf(stream, "%.3f", doubleinfo); |
| break; |
| case VAR_NAMELOOKUP_TIME: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME, |
| &doubleinfo)) |
| fprintf(stream, "%.3f", doubleinfo); |
| break; |
| case VAR_CONNECT_TIME: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &doubleinfo)) |
| fprintf(stream, "%.3f", doubleinfo); |
| break; |
| case VAR_APPCONNECT_TIME: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, |
| &doubleinfo)) |
| fprintf(stream, "%.3f", doubleinfo); |
| break; |
| case VAR_PRETRANSFER_TIME: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, |
| &doubleinfo)) |
| fprintf(stream, "%.3f", doubleinfo); |
| break; |
| case VAR_STARTTRANSFER_TIME: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, |
| &doubleinfo)) |
| fprintf(stream, "%.3f", doubleinfo); |
| break; |
| case VAR_SIZE_UPLOAD: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &doubleinfo)) |
| fprintf(stream, "%.0f", doubleinfo); |
| break; |
| case VAR_SIZE_DOWNLOAD: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, |
| &doubleinfo)) |
| fprintf(stream, "%.0f", doubleinfo); |
| break; |
| case VAR_SPEED_DOWNLOAD: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, |
| &doubleinfo)) |
| fprintf(stream, "%.3f", doubleinfo); |
| break; |
| case VAR_SPEED_UPLOAD: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &doubleinfo)) |
| fprintf(stream, "%.3f", doubleinfo); |
| break; |
| case VAR_CONTENT_TYPE: |
| if((CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &stringp)) |
| && stringp) |
| fputs(stringp, stream); |
| break; |
| case VAR_FTP_ENTRY_PATH: |
| if((CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_FTP_ENTRY_PATH, &stringp)) |
| && stringp) |
| fputs(stringp, stream); |
| break; |
| case VAR_REDIRECT_URL: |
| if((CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &stringp)) |
| && stringp) |
| fputs(stringp, stream); |
| break; |
| case VAR_SSL_VERIFY_RESULT: |
| if(CURLE_OK == |
| curl_easy_getinfo(curl, CURLINFO_SSL_VERIFYRESULT, |
| &longinfo)) |
| fprintf(stream, "%ld", longinfo); |
| break; |
| default: |
| break; |
| } |
| break; |
| } |
| } |
| if(!match) { |
| fprintf(stderr, "curl: unknown --write-out variable: '%s'\n", ptr); |
| } |
| ptr = end + 1; /* pass the end */ |
| *end = keepit; |
| } |
| else { |
| /* illegal syntax, then just output the characters that are used */ |
| fputc('%', stream); |
| fputc(ptr[1], stream); |
| ptr += 2; |
| } |
| } |
| } |
| else if('\\' == *ptr) { |
| switch(ptr[1]) { |
| case 'r': |
| fputc('\r', stream); |
| break; |
| case 'n': |
| fputc('\n', stream); |
| break; |
| case 't': |
| fputc('\t', stream); |
| break; |
| default: |
| /* unknown, just output this */ |
| fputc(*ptr, stream); |
| fputc(ptr[1], stream); |
| break; |
| } |
| ptr += 2; |
| } |
| else { |
| fputc(*ptr, stream); |
| ptr++; |
| } |
| } |
| |
| } |