blob: 5326d6d4bf06b3b81ede8eeb84129449353086ff [file] [log] [blame]
xf.li6c8fc1e2023-08-12 00:11:09 -07001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2022, 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#include "test.h"
25
26#include "memdebug.h"
27
28static char data[]=
29 "dummy\n";
30
31struct WriteThis {
32 char *readptr;
33 curl_off_t sizeleft;
34};
35
36static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
37{
38#ifdef LIB644
39 static int count = 0;
40 (void)ptr;
41 (void)size;
42 (void)nmemb;
43 (void)userp;
44 switch(count++) {
45 case 0: /* Return a single byte. */
46 *ptr = '\n';
47 return 1;
48 case 1: /* Request abort. */
49 return CURL_READFUNC_ABORT;
50 }
51 printf("Wrongly called >2 times\n");
52 exit(1); /* trigger major failure */
53#else
54
55 struct WriteThis *pooh = (struct WriteThis *)userp;
56 int eof = !*pooh->readptr;
57
58 if(size*nmemb < 1)
59 return 0;
60
61#ifndef LIB645
62 eof = pooh->sizeleft <= 0;
63 if(!eof)
64 pooh->sizeleft--;
65#endif
66
67 if(!eof) {
68 *ptr = *pooh->readptr; /* copy one single byte */
69 pooh->readptr++; /* advance pointer */
70 return 1; /* we return 1 byte at a time! */
71 }
72
73 return 0; /* no more data left to deliver */
74#endif
75}
76
77static int once(char *URL, bool oldstyle)
78{
79 CURL *curl;
80 CURLcode res = CURLE_OK;
81
82 curl_mime *mime = NULL;
83 curl_mimepart *part = NULL;
84 struct WriteThis pooh;
85 struct WriteThis pooh2;
86 curl_off_t datasize = -1;
87
88 pooh.readptr = data;
89#ifndef LIB645
90 datasize = (curl_off_t)strlen(data);
91#endif
92 pooh.sizeleft = datasize;
93
94 curl = curl_easy_init();
95 if(!curl) {
96 fprintf(stderr, "curl_easy_init() failed\n");
97 curl_global_cleanup();
98 return TEST_ERR_MAJOR_BAD;
99 }
100
101 mime = curl_mime_init(curl);
102 if(!mime) {
103 fprintf(stderr, "curl_mime_init() failed\n");
104 curl_easy_cleanup(curl);
105 curl_global_cleanup();
106 return TEST_ERR_MAJOR_BAD;
107 }
108
109 part = curl_mime_addpart(mime);
110 if(!part) {
111 fprintf(stderr, "curl_mime_addpart(1) failed\n");
112 curl_mime_free(mime);
113 curl_easy_cleanup(curl);
114 curl_global_cleanup();
115 return TEST_ERR_MAJOR_BAD;
116 }
117
118 /* Fill in the file upload part */
119 if(oldstyle) {
120 res = curl_mime_name(part, "sendfile");
121 if(!res)
122 res = curl_mime_data_cb(part, datasize, read_callback,
123 NULL, NULL, &pooh);
124 if(!res)
125 res = curl_mime_filename(part, "postit2.c");
126 }
127 else {
128 /* new style */
129 res = curl_mime_name(part, "sendfile alternative");
130 if(!res)
131 res = curl_mime_data_cb(part, datasize, read_callback,
132 NULL, NULL, &pooh);
133 if(!res)
134 res = curl_mime_filename(part, "file name 2");
135 }
136
137 if(res)
138 printf("curl_mime_xxx(1) = %s\n", curl_easy_strerror(res));
139
140 /* Now add the same data with another name and make it not look like
141 a file upload but still using the callback */
142
143 pooh2.readptr = data;
144#ifndef LIB645
145 datasize = (curl_off_t)strlen(data);
146#endif
147 pooh2.sizeleft = datasize;
148
149 part = curl_mime_addpart(mime);
150 if(!part) {
151 fprintf(stderr, "curl_mime_addpart(2) failed\n");
152 curl_mime_free(mime);
153 curl_easy_cleanup(curl);
154 curl_global_cleanup();
155 return TEST_ERR_MAJOR_BAD;
156 }
157 /* Fill in the file upload part */
158 res = curl_mime_name(part, "callbackdata");
159 if(!res)
160 res = curl_mime_data_cb(part, datasize, read_callback,
161 NULL, NULL, &pooh2);
162
163 if(res)
164 printf("curl_mime_xxx(2) = %s\n", curl_easy_strerror(res));
165
166 part = curl_mime_addpart(mime);
167 if(!part) {
168 fprintf(stderr, "curl_mime_addpart(3) failed\n");
169 curl_mime_free(mime);
170 curl_easy_cleanup(curl);
171 curl_global_cleanup();
172 return TEST_ERR_MAJOR_BAD;
173 }
174
175 /* Fill in the filename field */
176 res = curl_mime_name(part, "filename");
177 if(!res)
178 res = curl_mime_data(part, "postit2.c",
179 CURL_ZERO_TERMINATED);
180
181 if(res)
182 printf("curl_mime_xxx(3) = %s\n", curl_easy_strerror(res));
183
184 /* Fill in a submit field too */
185 part = curl_mime_addpart(mime);
186 if(!part) {
187 fprintf(stderr, "curl_mime_addpart(4) failed\n");
188 curl_mime_free(mime);
189 curl_easy_cleanup(curl);
190 curl_global_cleanup();
191 return TEST_ERR_MAJOR_BAD;
192 }
193 res = curl_mime_name(part, "submit");
194 if(!res)
195 res = curl_mime_data(part, "send",
196 CURL_ZERO_TERMINATED);
197
198 if(res)
199 printf("curl_mime_xxx(4) = %s\n", curl_easy_strerror(res));
200
201 part = curl_mime_addpart(mime);
202 if(!part) {
203 fprintf(stderr, "curl_mime_addpart(5) failed\n");
204 curl_mime_free(mime);
205 curl_easy_cleanup(curl);
206 curl_global_cleanup();
207 return TEST_ERR_MAJOR_BAD;
208 }
209 res = curl_mime_name(part, "somename");
210 if(!res)
211 res = curl_mime_filename(part, "somefile.txt");
212 if(!res)
213 res = curl_mime_data(part, "blah blah", 9);
214
215 if(res)
216 printf("curl_mime_xxx(5) = %s\n", curl_easy_strerror(res));
217
218 /* First set the URL that is about to receive our POST. */
219 test_setopt(curl, CURLOPT_URL, URL);
220
221 /* send a multi-part mimepost */
222 test_setopt(curl, CURLOPT_MIMEPOST, mime);
223
224 /* get verbose debug output please */
225 test_setopt(curl, CURLOPT_VERBOSE, 1L);
226
227 /* include headers in the output */
228 test_setopt(curl, CURLOPT_HEADER, 1L);
229
230 /* Perform the request, res will get the return code */
231 res = curl_easy_perform(curl);
232
233test_cleanup:
234
235 /* always cleanup */
236 curl_easy_cleanup(curl);
237
238 /* now cleanup the mimepost structure */
239 curl_mime_free(mime);
240
241 return res;
242}
243
244static int cyclic_add(void)
245{
246 CURL *easy = curl_easy_init();
247 curl_mime *mime = curl_mime_init(easy);
248 curl_mimepart *part = curl_mime_addpart(mime);
249 CURLcode a1 = curl_mime_subparts(part, mime);
250
251 if(a1 == CURLE_BAD_FUNCTION_ARGUMENT) {
252 curl_mime *submime = curl_mime_init(easy);
253 curl_mimepart *subpart = curl_mime_addpart(submime);
254
255 curl_mime_subparts(part, submime);
256 a1 = curl_mime_subparts(subpart, mime);
257 }
258
259 curl_mime_free(mime);
260 curl_easy_cleanup(easy);
261 if(a1 != CURLE_BAD_FUNCTION_ARGUMENT)
262 /* that should have failed */
263 return 1;
264
265 return 0;
266}
267
268int test(char *URL)
269{
270 int res;
271
272 if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
273 fprintf(stderr, "curl_global_init() failed\n");
274 return TEST_ERR_MAJOR_BAD;
275 }
276
277 res = once(URL, TRUE); /* old */
278 if(!res)
279 res = once(URL, FALSE); /* new */
280
281 if(!res)
282 res = cyclic_add();
283
284 curl_global_cleanup();
285
286 return res;
287}