00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "tool_setup.h"
00023
00024 #define ENABLE_CURLX_PRINTF
00025
00026 #include "curlx.h"
00027
00028 #include "tool_cfgable.h"
00029 #include "tool_msgs.h"
00030 #include "tool_cb_dbg.h"
00031 #include "tool_util.h"
00032
00033 #include "memdebug.h"
00034
00035 static void dump(const char *timebuf, const char *text,
00036 FILE *stream, const unsigned char *ptr, size_t size,
00037 trace tracetype, curl_infotype infotype);
00038
00039
00040
00041
00042
00043 int tool_debug_cb(CURL *handle, curl_infotype type,
00044 unsigned char *data, size_t size,
00045 void *userdata)
00046 {
00047 struct OperationConfig *operation = userdata;
00048 struct GlobalConfig *config = operation->global;
00049 FILE *output = config->errors;
00050 const char *text;
00051 struct timeval tv;
00052 struct tm *now;
00053 char timebuf[20];
00054 time_t secs;
00055 static time_t epoch_offset;
00056 static int known_offset;
00057
00058 (void)handle;
00059
00060 if(config->tracetime) {
00061 tv = tvnow();
00062 if(!known_offset) {
00063 epoch_offset = time(NULL) - tv.tv_sec;
00064 known_offset = 1;
00065 }
00066 secs = epoch_offset + tv.tv_sec;
00067 now = localtime(&secs);
00068 snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld ",
00069 now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec);
00070 }
00071 else
00072 timebuf[0] = 0;
00073
00074 if(!config->trace_stream) {
00075
00076 if(!strcmp("-", config->trace_dump))
00077 config->trace_stream = stdout;
00078 else if(!strcmp("%", config->trace_dump))
00079
00080 config->trace_stream = config->errors;
00081 else {
00082 config->trace_stream = fopen(config->trace_dump, FOPEN_WRITETEXT);
00083 config->trace_fopened = TRUE;
00084 }
00085 }
00086
00087 if(config->trace_stream)
00088 output = config->trace_stream;
00089
00090 if(!output) {
00091 warnf(config, "Failed to create/open output");
00092 return 0;
00093 }
00094
00095 if(config->tracetype == TRACE_PLAIN) {
00096
00097
00098
00099
00100 static const char * const s_infotype[] = {
00101 "*", "<", ">", "{", "}", "{", "}"
00102 };
00103 size_t i;
00104 size_t st = 0;
00105 static bool newl = FALSE;
00106 static bool traced_data = FALSE;
00107
00108 switch(type) {
00109 case CURLINFO_HEADER_OUT:
00110 if(size > 0) {
00111 for(i = 0; i < size - 1; i++) {
00112 if(data[i] == '\n') {
00113 if(!newl) {
00114 fprintf(output, "%s%s ", timebuf, s_infotype[type]);
00115 }
00116 (void)fwrite(data + st, i - st + 1, 1, output);
00117 st = i + 1;
00118 newl = FALSE;
00119 }
00120 }
00121 if(!newl)
00122 fprintf(output, "%s%s ", timebuf, s_infotype[type]);
00123 (void)fwrite(data + st, i - st + 1, 1, output);
00124 }
00125 newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE;
00126 traced_data = FALSE;
00127 break;
00128 case CURLINFO_TEXT:
00129 case CURLINFO_HEADER_IN:
00130 if(!newl)
00131 fprintf(output, "%s%s ", timebuf, s_infotype[type]);
00132 (void)fwrite(data, size, 1, output);
00133 newl = (size && (data[size - 1] != '\n')) ? TRUE : FALSE;
00134 traced_data = FALSE;
00135 break;
00136 case CURLINFO_DATA_OUT:
00137 case CURLINFO_DATA_IN:
00138 case CURLINFO_SSL_DATA_IN:
00139 case CURLINFO_SSL_DATA_OUT:
00140 if(!traced_data) {
00141
00142
00143
00144
00145 if(!config->isatty || ((output != stderr) && (output != stdout))) {
00146 if(!newl)
00147 fprintf(output, "%s%s ", timebuf, s_infotype[type]);
00148 fprintf(output, "[%zd bytes data]\n", size);
00149 newl = FALSE;
00150 traced_data = TRUE;
00151 }
00152 }
00153 break;
00154 default:
00155 newl = FALSE;
00156 traced_data = FALSE;
00157 break;
00158 }
00159
00160 return 0;
00161 }
00162
00163 #ifdef CURL_DOES_CONVERSIONS
00164
00165
00166
00167
00168 if((type == CURLINFO_HEADER_OUT) && (size > 4)) {
00169 size_t i;
00170 for(i = 0; i < size - 4; i++) {
00171 if(memcmp(&data[i], "\r\n\r\n", 4) == 0) {
00172
00173 text = "=> Send header";
00174 dump(timebuf, text, output, data, i + 4, config->tracetype, type);
00175 data += i + 3;
00176 size -= i + 4;
00177 type = CURLINFO_DATA_OUT;
00178 data += 1;
00179 break;
00180 }
00181 }
00182 }
00183 #endif
00184
00185 switch(type) {
00186 case CURLINFO_TEXT:
00187 fprintf(output, "%s== Info: %s", timebuf, data);
00188 default:
00189 return 0;
00190
00191 case CURLINFO_HEADER_OUT:
00192 text = "=> Send header";
00193 break;
00194 case CURLINFO_DATA_OUT:
00195 text = "=> Send data";
00196 break;
00197 case CURLINFO_HEADER_IN:
00198 text = "<= Recv header";
00199 break;
00200 case CURLINFO_DATA_IN:
00201 text = "<= Recv data";
00202 break;
00203 case CURLINFO_SSL_DATA_IN:
00204 text = "<= Recv SSL data";
00205 break;
00206 case CURLINFO_SSL_DATA_OUT:
00207 text = "=> Send SSL data";
00208 break;
00209 }
00210
00211 dump(timebuf, text, output, data, size, config->tracetype, type);
00212 return 0;
00213 }
00214
00215 static void dump(const char *timebuf, const char *text,
00216 FILE *stream, const unsigned char *ptr, size_t size,
00217 trace tracetype, curl_infotype infotype)
00218 {
00219 size_t i;
00220 size_t c;
00221
00222 unsigned int width = 0x10;
00223
00224 if(tracetype == TRACE_ASCII)
00225
00226 width = 0x40;
00227
00228 fprintf(stream, "%s%s, %zd bytes (0x%zx)\n", timebuf, text, size, size);
00229
00230 for(i = 0; i < size; i += width) {
00231
00232 fprintf(stream, "%04zx: ", i);
00233
00234 if(tracetype == TRACE_BIN) {
00235
00236 for(c = 0; c < width; c++)
00237 if(i+c < size)
00238 fprintf(stream, "%02x ", ptr[i+c]);
00239 else
00240 fputs(" ", stream);
00241 }
00242
00243 for(c = 0; (c < width) && (i+c < size); c++) {
00244
00245 if((tracetype == TRACE_ASCII) &&
00246 (i+c+1 < size) && (ptr[i+c] == 0x0D) && (ptr[i+c+1] == 0x0A)) {
00247 i += (c+2-width);
00248 break;
00249 }
00250 #ifdef CURL_DOES_CONVERSIONS
00251
00252 if((tracetype == TRACE_ASCII) &&
00253 (i+c+1 < size) && (ptr[i+c] == '\r') && (ptr[i+c+1] == '\n')) {
00254 i += (c+2-width);
00255 break;
00256 }
00257
00258 fprintf(stream, "%c", convert_char(infotype, ptr[i+c]));
00259 #else
00260 (void)infotype;
00261 fprintf(stream, "%c", ((ptr[i+c] >= 0x20) && (ptr[i+c] < 0x80)) ?
00262 ptr[i+c] : UNPRINTABLE_CHAR);
00263 #endif
00264
00265 if((tracetype == TRACE_ASCII) &&
00266 (i+c+2 < size) && (ptr[i+c+1] == 0x0D) && (ptr[i+c+2] == 0x0A)) {
00267 i += (c+3-width);
00268 break;
00269 }
00270 }
00271 fputc('\n', stream);
00272 }
00273 fflush(stream);
00274 }
00275