xref: /third_party/curl/tests/libtest/lib552.c (revision 13498266)
1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 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 https://curl.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 * SPDX-License-Identifier: curl
22 *
23 ***************************************************************************/
24/* argv1 = URL
25 * argv2 = proxy with embedded user+password
26 */
27
28#include "test.h"
29
30#include "warnless.h"
31#include "memdebug.h"
32
33struct data {
34  char trace_ascii; /* 1 or 0 */
35};
36
37static
38void dump(const char *text,
39          FILE *stream, unsigned char *ptr, size_t size,
40          char nohex)
41{
42  size_t i;
43  size_t c;
44
45  unsigned int width = 0x10;
46
47  if(nohex)
48    /* without the hex output, we can fit more on screen */
49    width = 0x40;
50
51  fprintf(stream, "%s, %zu bytes (0x%zx)\n", text, size, size);
52
53  for(i = 0; i<size; i += width) {
54
55    fprintf(stream, "%04zx: ", i);
56
57    if(!nohex) {
58      /* hex not disabled, show it */
59      for(c = 0; c < width; c++)
60        if(i + c < size)
61          fprintf(stream, "%02x ", ptr[i + c]);
62        else
63          fputs("   ", stream);
64    }
65
66    for(c = 0; (c < width) && (i + c < size); c++) {
67      /* check for 0D0A; if found, skip past and start a new line of output */
68      if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
69         ptr[i + c + 1] == 0x0A) {
70        i += (c + 2 - width);
71        break;
72      }
73      fprintf(stream, "%c",
74              (ptr[i + c] >= 0x20) && (ptr[i + c]<0x80)? ptr[i + c] : '.');
75      /* check again for 0D0A, to avoid an extra \n if it's at width */
76      if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
77         ptr[i + c + 2] == 0x0A) {
78        i += (c + 3 - width);
79        break;
80      }
81    }
82    fputc('\n', stream); /* newline */
83  }
84  fflush(stream);
85}
86
87static
88int my_trace(CURL *handle, curl_infotype type,
89             char *data, size_t size,
90             void *userp)
91{
92  struct data *config = (struct data *)userp;
93  const char *text;
94  (void)handle; /* prevent compiler warning */
95
96  switch(type) {
97  case CURLINFO_TEXT:
98    fprintf(stderr, "== Info: %s", (char *)data);
99    return 0;
100  case CURLINFO_HEADER_OUT:
101    text = "=> Send header";
102    break;
103  case CURLINFO_DATA_OUT:
104    text = "=> Send data";
105    break;
106  case CURLINFO_SSL_DATA_OUT:
107    text = "=> Send SSL data";
108    break;
109  case CURLINFO_HEADER_IN:
110    text = "<= Recv header";
111    break;
112  case CURLINFO_DATA_IN:
113    text = "<= Recv data";
114    break;
115  case CURLINFO_SSL_DATA_IN:
116    text = "<= Recv SSL data";
117    break;
118  default: /* in case a new one is introduced to shock us */
119    return 0;
120  }
121
122  dump(text, stderr, (unsigned char *)data, size, config->trace_ascii);
123  return 0;
124}
125
126
127static size_t current_offset = 0;
128static char databuf[70000]; /* MUST be more than 64k OR
129                               MAX_INITIAL_POST_SIZE */
130
131static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
132{
133  size_t  amount = nmemb * size; /* Total bytes curl wants */
134  size_t  available = sizeof(databuf) - current_offset; /* What we have to
135                                                           give */
136  size_t  given = amount < available ? amount : available; /* What is given */
137  (void)stream;
138  memcpy(ptr, databuf + current_offset, given);
139  current_offset += given;
140  return given;
141}
142
143
144static size_t write_callback(void *ptr, size_t size, size_t nmemb,
145                             void *stream)
146{
147  int amount = curlx_uztosi(size * nmemb);
148  printf("%.*s", amount, (char *)ptr);
149  (void)stream;
150  return size * nmemb;
151}
152
153
154static curlioerr ioctl_callback(CURL *handle, int cmd, void *clientp)
155{
156  (void)clientp;
157  if(cmd == CURLIOCMD_RESTARTREAD) {
158    printf("APPLICATION received a CURLIOCMD_RESTARTREAD request\n");
159    printf("APPLICATION ** REWINDING! **\n");
160    current_offset = 0;
161    return CURLIOE_OK;
162  }
163  (void)handle;
164  return CURLIOE_UNKNOWNCMD;
165}
166
167
168
169int test(char *URL)
170{
171  CURL *curl;
172  CURLcode res = CURLE_OK;
173  struct data config;
174  size_t i;
175  static const char fill[] = "test data";
176
177  config.trace_ascii = 1; /* enable ascii tracing */
178
179  global_init(CURL_GLOBAL_ALL);
180  easy_init(curl);
181
182  test_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
183  test_setopt(curl, CURLOPT_DEBUGDATA, &config);
184  /* the DEBUGFUNCTION has no effect until we enable VERBOSE */
185  test_setopt(curl, CURLOPT_VERBOSE, 1L);
186
187  /* setup repeated data string */
188  for(i = 0; i < sizeof(databuf); ++i)
189    databuf[i] = fill[i % sizeof(fill)];
190
191  /* Post */
192  test_setopt(curl, CURLOPT_POST, 1L);
193
194  /* Setup read callback */
195  test_setopt(curl, CURLOPT_POSTFIELDSIZE, (long) sizeof(databuf));
196  test_setopt(curl, CURLOPT_READFUNCTION, read_callback);
197
198  /* Write callback */
199  test_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
200
201  /* Ioctl function */
202  CURL_IGNORE_DEPRECATION(
203    test_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_callback);
204  )
205
206  test_setopt(curl, CURLOPT_PROXY, libtest_arg2);
207
208  test_setopt(curl, CURLOPT_URL, URL);
209
210  /* Accept any auth. But for this bug configure proxy with DIGEST, basic
211     might work too, not NTLM */
212  test_setopt(curl, CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY);
213
214  res = curl_easy_perform(curl);
215
216test_cleanup:
217
218  curl_easy_cleanup(curl);
219  curl_global_cleanup();
220  return (int)res;
221}
222