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