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