1e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/*************************************************************************** 2e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * _ _ ____ _ 3e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Project ___| | | | _ \| | 4e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * / __| | | | |_) | | 5e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * | (__| |_| | _ <| |___ 6e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * \___|\___/|_| \_\_____| 7e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 8e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. 9e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 10e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This software is licensed as described in the file COPYING, which 11e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * you should have received as part of this distribution. The terms 12d15eaac64ca1a7244824d660ea84e8815a23d058Alex Deymo * are also available at https://curl.haxx.se/docs/copyright.html. 13e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 14e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * copies of the Software, and permit persons to whom the Software is 16e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * furnished to do so, under the terms of the COPYING file. 17e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 18e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * KIND, either express or implied. 20e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 21e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ***************************************************************************/ 22e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "tool_setup.h" 23e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 24e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#define ENABLE_CURLX_PRINTF 25e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* use our own printf() functions */ 26e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "curlx.h" 27e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 28e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "tool_cfgable.h" 29e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "tool_msgs.h" 30e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "tool_cb_dbg.h" 31e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "tool_util.h" 32e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 33e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "memdebug.h" /* keep this as LAST include */ 34e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 35e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic void dump(const char *timebuf, const char *text, 36e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET FILE *stream, const unsigned char *ptr, size_t size, 37e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET trace tracetype, curl_infotype infotype); 38e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 39e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* 40e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET** callback for CURLOPT_DEBUGFUNCTION 41e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET*/ 42e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 43e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETint tool_debug_cb(CURL *handle, curl_infotype type, 44e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET unsigned char *data, size_t size, 45e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET void *userdata) 46e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 47e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct OperationConfig *operation = userdata; 48e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct GlobalConfig *config = operation->global; 49e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET FILE *output = config->errors; 50e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET const char *text; 51e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct timeval tv; 52e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct tm *now; 53e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET char timebuf[20]; 54e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET time_t secs; 55e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET static time_t epoch_offset; 56e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET static int known_offset; 57e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 58e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)handle; /* not used */ 59e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 60e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(config->tracetime) { 61e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET tv = tvnow(); 62e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!known_offset) { 63e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET epoch_offset = time(NULL) - tv.tv_sec; 64e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET known_offset = 1; 65e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 66e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET secs = epoch_offset + tv.tv_sec; 67e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET now = localtime(&secs); /* not thread safe but we don't care */ 68e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld ", 69e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec); 70e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 71e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else 72e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET timebuf[0] = 0; 73e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 74e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!config->trace_stream) { 75e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* open for append */ 76e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(curlx_strequal("-", config->trace_dump)) 77e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET config->trace_stream = stdout; 78e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else if(curlx_strequal("%", config->trace_dump)) 79e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Ok, this is somewhat hackish but we do it undocumented for now */ 80e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET config->trace_stream = config->errors; /* aka stderr */ 81e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else { 82e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET config->trace_stream = fopen(config->trace_dump, FOPEN_WRITETEXT); 83e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET config->trace_fopened = TRUE; 84e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 85e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 86e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 87e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(config->trace_stream) 88e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET output = config->trace_stream; 89e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 90e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!output) { 91e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET warnf(config, "Failed to create/open output"); 92e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return 0; 93e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 94e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 95e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(config->tracetype == TRACE_PLAIN) { 96e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* 97e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This is the trace look that is similar to what libcurl makes on its 98e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * own. 99e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 100e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET static const char * const s_infotype[] = { 101e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET "*", "<", ">", "{", "}", "{", "}" 102e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET }; 103e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET size_t i; 104e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET size_t st = 0; 105e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET static bool newl = FALSE; 106e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET static bool traced_data = FALSE; 107e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 108e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET switch(type) { 109e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURLINFO_HEADER_OUT: 110e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(size > 0) { 111e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET for(i = 0; i < size - 1; i++) { 112e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(data[i] == '\n') { /* LF */ 113e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!newl) { 114e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fprintf(output, "%s%s ", timebuf, s_infotype[type]); 115e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 116e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)fwrite(data + st, i - st + 1, 1, output); 117e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET st = i + 1; 118e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET newl = FALSE; 119e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 120e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 121e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!newl) 122e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fprintf(output, "%s%s ", timebuf, s_infotype[type]); 123e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)fwrite(data + st, i - st + 1, 1, output); 124e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 125e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE; 126e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET traced_data = FALSE; 127e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 128e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURLINFO_TEXT: 129e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURLINFO_HEADER_IN: 130e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!newl) 131e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fprintf(output, "%s%s ", timebuf, s_infotype[type]); 132e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)fwrite(data, size, 1, output); 133e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE; 134e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET traced_data = FALSE; 135e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 136e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURLINFO_DATA_OUT: 137e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURLINFO_DATA_IN: 138e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURLINFO_SSL_DATA_IN: 139e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURLINFO_SSL_DATA_OUT: 140e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!traced_data) { 141e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* if the data is output to a tty and we're sending this debug trace 142e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET to stderr or stdout, we don't display the alert about the data not 143e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET being shown as the data _is_ shown then just not via this 144e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET function */ 145e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!config->isatty || ((output != stderr) && (output != stdout))) { 146e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!newl) 147e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fprintf(output, "%s%s ", timebuf, s_infotype[type]); 148e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fprintf(output, "[%zd bytes data]\n", size); 149e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET newl = FALSE; 150e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET traced_data = TRUE; 151e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 152e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 153e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 154e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET default: /* nada */ 155e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET newl = FALSE; 156e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET traced_data = FALSE; 157e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 158e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 159e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 160e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return 0; 161e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 162e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 163e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef CURL_DOES_CONVERSIONS 164e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Special processing is needed for CURLINFO_HEADER_OUT blocks 165e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * if they contain both headers and data (separated by CRLFCRLF). 166e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * We dump the header text and then switch type to CURLINFO_DATA_OUT. 167e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 168e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if((type == CURLINFO_HEADER_OUT) && (size > 4)) { 169e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET size_t i; 170e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET for(i = 0; i < size - 4; i++) { 171e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(memcmp(&data[i], "\r\n\r\n", 4) == 0) { 172e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* dump everything through the CRLFCRLF as a sent header */ 173e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET text = "=> Send header"; 174e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET dump(timebuf, text, output, data, i + 4, config->tracetype, type); 175e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET data += i + 3; 176e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET size -= i + 4; 177e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET type = CURLINFO_DATA_OUT; 178e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET data += 1; 179e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 180e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 181e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 182e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 183e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif /* CURL_DOES_CONVERSIONS */ 184e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 185e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET switch (type) { 186e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURLINFO_TEXT: 187e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fprintf(output, "%s== Info: %s", timebuf, data); 188e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET default: /* in case a new one is introduced to shock us */ 189e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return 0; 190e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 191e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURLINFO_HEADER_OUT: 192e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET text = "=> Send header"; 193e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 194e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURLINFO_DATA_OUT: 195e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET text = "=> Send data"; 196e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 197e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURLINFO_HEADER_IN: 198e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET text = "<= Recv header"; 199e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 200e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURLINFO_DATA_IN: 201e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET text = "<= Recv data"; 202e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 203e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURLINFO_SSL_DATA_IN: 204e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET text = "<= Recv SSL data"; 205e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 206e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case CURLINFO_SSL_DATA_OUT: 207e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET text = "=> Send SSL data"; 208e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 209e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 210e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 211e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET dump(timebuf, text, output, data, size, config->tracetype, type); 212e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return 0; 213e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 214e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 215e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic void dump(const char *timebuf, const char *text, 216e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET FILE *stream, const unsigned char *ptr, size_t size, 217e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET trace tracetype, curl_infotype infotype) 218e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 219e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET size_t i; 220e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET size_t c; 221e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 222e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET unsigned int width = 0x10; 223e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 224e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(tracetype == TRACE_ASCII) 225e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* without the hex output, we can fit more on screen */ 226e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET width = 0x40; 227e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 228e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fprintf(stream, "%s%s, %zd bytes (0x%zx)\n", timebuf, text, size, size); 229e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 230e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET for(i = 0; i < size; i += width) { 231e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 232e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fprintf(stream, "%04zx: ", i); 233e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 234e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(tracetype == TRACE_BIN) { 235e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* hex not disabled, show it */ 236e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET for(c = 0; c < width; c++) 237e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(i+c < size) 238e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fprintf(stream, "%02x ", ptr[i+c]); 239e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else 240e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fputs(" ", stream); 241e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 242e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 243e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET for(c = 0; (c < width) && (i+c < size); c++) { 244e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* check for 0D0A; if found, skip past and start a new line of output */ 245e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if((tracetype == TRACE_ASCII) && 246e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (i+c+1 < size) && (ptr[i+c] == 0x0D) && (ptr[i+c+1] == 0x0A)) { 247e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET i += (c+2-width); 248e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 249e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 250e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef CURL_DOES_CONVERSIONS 251e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* repeat the 0D0A check above but use the host encoding for CRLF */ 252e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if((tracetype == TRACE_ASCII) && 253e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (i+c+1 < size) && (ptr[i+c] == '\r') && (ptr[i+c+1] == '\n')) { 254e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET i += (c+2-width); 255e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 256e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 257e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* convert to host encoding and print this character */ 258e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fprintf(stream, "%c", convert_char(infotype, ptr[i+c])); 259e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#else 260e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (void)infotype; 261e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fprintf(stream, "%c", ((ptr[i+c] >= 0x20) && (ptr[i+c] < 0x80)) ? 262e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ptr[i+c] : UNPRINTABLE_CHAR); 263e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif /* CURL_DOES_CONVERSIONS */ 264e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* check again for 0D0A, to avoid an extra \n if it's at width */ 265e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if((tracetype == TRACE_ASCII) && 266e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (i+c+2 < size) && (ptr[i+c+1] == 0x0D) && (ptr[i+c+2] == 0x0A)) { 267e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET i += (c+3-width); 268e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 269e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 270e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 271e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fputc('\n', stream); /* newline */ 272e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 273e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fflush(stream); 274e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 275e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 276