blob: f91241052675944ec6b68fef4c56d7fd432fb0d4 [file] [log] [blame]
Kristian Monsen5ab50182010-05-14 18:53:44 +01001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
Elliott Hughescac39802018-04-27 16:19:43 -07008 * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
Kristian Monsen5ab50182010-05-14 18:53:44 +01009 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
Alex Deymod15eaac2016-06-28 14:49:26 -070012 * are also available at https://curl.haxx.se/docs/copyright.html.
Kristian Monsen5ab50182010-05-14 18:53:44 +010013 *
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 ***************************************************************************/
22
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070023#include "curl_setup.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010024
Kristian Monsen5ab50182010-05-14 18:53:44 +010025#include <curl/curl.h>
26
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070027#ifndef CURL_DISABLE_HTTP
Kristian Monsen5ab50182010-05-14 18:53:44 +010028
Kristian Monsen5ab50182010-05-14 18:53:44 +010029#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
30#include <libgen.h>
31#endif
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070032
Alex Deymoe3149cc2016-10-05 11:18:42 -070033#include "urldata.h" /* for struct Curl_easy */
Kristian Monsen5ab50182010-05-14 18:53:44 +010034#include "formdata.h"
Alex Deymo486467e2017-12-19 19:04:07 +010035#include "mime.h"
36#include "non-ascii.h"
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070037#include "vtls/vtls.h"
Elliott Hughescee03382017-06-23 12:17:18 -070038#include "strcase.h"
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070039#include "sendf.h"
40#include "strdup.h"
Elliott Hughescee03382017-06-23 12:17:18 -070041#include "rand.h"
Alex Deymod15eaac2016-06-28 14:49:26 -070042/* The last 3 #include files should be in this order */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070043#include "curl_printf.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010044#include "curl_memory.h"
Kristian Monsen5ab50182010-05-14 18:53:44 +010045#include "memdebug.h"
46
Kristian Monsen5ab50182010-05-14 18:53:44 +010047
48/* What kind of Content-Type to use on un-specified files with unrecognized
49 extensions. */
50#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
51
Alex Deymod15eaac2016-06-28 14:49:26 -070052#define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
53#define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
54#define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
55#define HTTPPOST_READFILE CURL_HTTPPOST_READFILE
56#define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER
57#define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK
58#define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER
59
Kristian Monsen5ab50182010-05-14 18:53:44 +010060/***************************************************************************
61 *
62 * AddHttpPost()
63 *
64 * Adds a HttpPost structure to the list, if parent_post is given becomes
65 * a subpost of parent_post instead of a direct list element.
66 *
67 * Returns newly allocated HttpPost on success and NULL if malloc failed.
68 *
69 ***************************************************************************/
70static struct curl_httppost *
71AddHttpPost(char *name, size_t namelength,
Alex Deymod15eaac2016-06-28 14:49:26 -070072 char *value, curl_off_t contentslength,
Kristian Monsen5ab50182010-05-14 18:53:44 +010073 char *buffer, size_t bufferlength,
74 char *contenttype,
75 long flags,
Elliott Hughescee03382017-06-23 12:17:18 -070076 struct curl_slist *contentHeader,
Kristian Monsen5ab50182010-05-14 18:53:44 +010077 char *showfilename, char *userp,
78 struct curl_httppost *parent_post,
79 struct curl_httppost **httppost,
80 struct curl_httppost **last_post)
81{
82 struct curl_httppost *post;
83 post = calloc(1, sizeof(struct curl_httppost));
84 if(post) {
85 post->name = name;
86 post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
87 post->contents = value;
Alex Deymod15eaac2016-06-28 14:49:26 -070088 post->contentlen = contentslength;
Kristian Monsen5ab50182010-05-14 18:53:44 +010089 post->buffer = buffer;
90 post->bufferlength = (long)bufferlength;
91 post->contenttype = contenttype;
92 post->contentheader = contentHeader;
93 post->showfilename = showfilename;
Elliott Hughes82be86d2017-09-20 17:00:17 -070094 post->userp = userp;
Alex Deymod15eaac2016-06-28 14:49:26 -070095 post->flags = flags | CURL_HTTPPOST_LARGE;
Kristian Monsen5ab50182010-05-14 18:53:44 +010096 }
97 else
98 return NULL;
99
100 if(parent_post) {
101 /* now, point our 'more' to the original 'more' */
102 post->more = parent_post->more;
103
104 /* then move the original 'more' to point to ourselves */
105 parent_post->more = post;
106 }
107 else {
108 /* make the previous point to this */
109 if(*last_post)
110 (*last_post)->next = post;
111 else
112 (*httppost) = post;
113
114 (*last_post) = post;
115 }
116 return post;
117}
118
119/***************************************************************************
120 *
121 * AddFormInfo()
122 *
123 * Adds a FormInfo structure to the list presented by parent_form_info.
124 *
125 * Returns newly allocated FormInfo on success and NULL if malloc failed/
126 * parent_form_info is NULL.
127 *
128 ***************************************************************************/
129static FormInfo * AddFormInfo(char *value,
130 char *contenttype,
131 FormInfo *parent_form_info)
132{
133 FormInfo *form_info;
134 form_info = calloc(1, sizeof(struct FormInfo));
135 if(form_info) {
136 if(value)
137 form_info->value = value;
138 if(contenttype)
139 form_info->contenttype = contenttype;
140 form_info->flags = HTTPPOST_FILENAME;
141 }
142 else
143 return NULL;
144
145 if(parent_form_info) {
146 /* now, point our 'more' to the original 'more' */
147 form_info->more = parent_form_info->more;
148
149 /* then move the original 'more' to point to ourselves */
150 parent_form_info->more = form_info;
151 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100152
153 return form_info;
154}
155
156/***************************************************************************
157 *
Kristian Monsen5ab50182010-05-14 18:53:44 +0100158 * FormAdd()
159 *
160 * Stores a formpost parameter and builds the appropriate linked list.
161 *
162 * Has two principal functionalities: using files and byte arrays as
163 * post parts. Byte arrays are either copied or just the pointer is stored
164 * (as the user requests) while for files only the filename and not the
165 * content is stored.
166 *
167 * While you may have only one byte array for each name, multiple filenames
168 * are allowed (and because of this feature CURLFORM_END is needed after
169 * using CURLFORM_FILE).
170 *
171 * Examples:
172 *
173 * Simple name/value pair with copied contents:
174 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
175 * CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
176 *
177 * name/value pair where only the content pointer is remembered:
178 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
179 * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END);
180 * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
181 *
182 * storing a filename (CONTENTTYPE is optional!):
183 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
184 * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text",
185 * CURLFORM_END);
186 *
187 * storing multiple filenames:
188 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
189 * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
190 *
191 * Returns:
192 * CURL_FORMADD_OK on success
193 * CURL_FORMADD_MEMORY if the FormInfo allocation fails
194 * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
195 * CURL_FORMADD_NULL if a null pointer was given for a char
196 * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
197 * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700198 * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100199 * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated
200 * CURL_FORMADD_MEMORY if some allocation for string copying failed.
201 * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
202 *
203 ***************************************************************************/
204
205static
206CURLFORMcode FormAdd(struct curl_httppost **httppost,
207 struct curl_httppost **last_post,
208 va_list params)
209{
210 FormInfo *first_form, *current_form, *form = NULL;
211 CURLFORMcode return_value = CURL_FORMADD_OK;
212 const char *prevtype = NULL;
213 struct curl_httppost *post = NULL;
214 CURLformoption option;
215 struct curl_forms *forms = NULL;
Alex Deymo486467e2017-12-19 19:04:07 +0100216 char *array_value = NULL; /* value read from an array */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100217
218 /* This is a state variable, that if TRUE means that we're parsing an
219 array that we got passed to us. If FALSE we're parsing the input
220 va_list arguments. */
221 bool array_state = FALSE;
222
223 /*
224 * We need to allocate the first struct to fill in.
225 */
226 first_form = calloc(1, sizeof(struct FormInfo));
227 if(!first_form)
228 return CURL_FORMADD_MEMORY;
229
230 current_form = first_form;
231
232 /*
233 * Loop through all the options set. Break if we have an error to report.
234 */
235 while(return_value == CURL_FORMADD_OK) {
236
237 /* first see if we have more parts of the array param */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700238 if(array_state && forms) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100239 /* get the upcoming option from the given array */
240 option = forms->option;
241 array_value = (char *)forms->value;
242
243 forms++; /* advance this to next entry */
244 if(CURLFORM_END == option) {
245 /* end of array state */
246 array_state = FALSE;
247 continue;
248 }
249 }
250 else {
251 /* This is not array-state, get next option */
252 option = va_arg(params, CURLformoption);
253 if(CURLFORM_END == option)
254 break;
255 }
256
Elliott Hughes82be86d2017-09-20 17:00:17 -0700257 switch(option) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100258 case CURLFORM_ARRAY:
259 if(array_state)
260 /* we don't support an array from within an array */
261 return_value = CURL_FORMADD_ILLEGAL_ARRAY;
262 else {
263 forms = va_arg(params, struct curl_forms *);
264 if(forms)
265 array_state = TRUE;
266 else
267 return_value = CURL_FORMADD_NULL;
268 }
269 break;
270
271 /*
272 * Set the Name property.
273 */
274 case CURLFORM_PTRNAME:
275#ifdef CURL_DOES_CONVERSIONS
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700276 /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy
277 * the data in all cases so that we'll have safe memory for the eventual
278 * conversion.
279 */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100280#else
281 current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
282#endif
Elliott Hughes82be86d2017-09-20 17:00:17 -0700283 /* FALLTHROUGH */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100284 case CURLFORM_COPYNAME:
285 if(current_form->name)
286 return_value = CURL_FORMADD_OPTION_TWICE;
287 else {
288 char *name = array_state?
289 array_value:va_arg(params, char *);
290 if(name)
291 current_form->name = name; /* store for the moment */
292 else
293 return_value = CURL_FORMADD_NULL;
294 }
295 break;
296 case CURLFORM_NAMELENGTH:
297 if(current_form->namelength)
298 return_value = CURL_FORMADD_OPTION_TWICE;
299 else
300 current_form->namelength =
301 array_state?(size_t)array_value:(size_t)va_arg(params, long);
302 break;
303
304 /*
305 * Set the contents property.
306 */
307 case CURLFORM_PTRCONTENTS:
308 current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
309 case CURLFORM_COPYCONTENTS:
310 if(current_form->value)
311 return_value = CURL_FORMADD_OPTION_TWICE;
312 else {
313 char *value =
314 array_state?array_value:va_arg(params, char *);
315 if(value)
316 current_form->value = value; /* store for the moment */
317 else
318 return_value = CURL_FORMADD_NULL;
319 }
320 break;
321 case CURLFORM_CONTENTSLENGTH:
Alex Deymod15eaac2016-06-28 14:49:26 -0700322 current_form->contentslength =
323 array_state?(size_t)array_value:(size_t)va_arg(params, long);
324 break;
325
326 case CURLFORM_CONTENTLEN:
327 current_form->flags |= CURL_HTTPPOST_LARGE;
328 current_form->contentslength =
329 array_state?(curl_off_t)(size_t)array_value:va_arg(params, curl_off_t);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100330 break;
331
332 /* Get contents from a given file name */
333 case CURLFORM_FILECONTENT:
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700334 if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
Kristian Monsen5ab50182010-05-14 18:53:44 +0100335 return_value = CURL_FORMADD_OPTION_TWICE;
336 else {
337 const char *filename = array_state?
338 array_value:va_arg(params, char *);
339 if(filename) {
340 current_form->value = strdup(filename);
341 if(!current_form->value)
342 return_value = CURL_FORMADD_MEMORY;
343 else {
344 current_form->flags |= HTTPPOST_READFILE;
345 current_form->value_alloc = TRUE;
346 }
347 }
348 else
349 return_value = CURL_FORMADD_NULL;
350 }
351 break;
352
353 /* We upload a file */
354 case CURLFORM_FILE:
355 {
356 const char *filename = array_state?array_value:
357 va_arg(params, char *);
358
359 if(current_form->value) {
360 if(current_form->flags & HTTPPOST_FILENAME) {
361 if(filename) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700362 char *fname = strdup(filename);
363 if(!fname)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100364 return_value = CURL_FORMADD_MEMORY;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700365 else {
366 form = AddFormInfo(fname, NULL, current_form);
367 if(!form) {
368 free(fname);
369 return_value = CURL_FORMADD_MEMORY;
370 }
371 else {
372 form->value_alloc = TRUE;
373 current_form = form;
374 form = NULL;
375 }
376 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100377 }
378 else
379 return_value = CURL_FORMADD_NULL;
380 }
381 else
382 return_value = CURL_FORMADD_OPTION_TWICE;
383 }
384 else {
385 if(filename) {
386 current_form->value = strdup(filename);
387 if(!current_form->value)
388 return_value = CURL_FORMADD_MEMORY;
389 else {
390 current_form->flags |= HTTPPOST_FILENAME;
391 current_form->value_alloc = TRUE;
392 }
393 }
394 else
395 return_value = CURL_FORMADD_NULL;
396 }
397 break;
398 }
399
Kristian Monsen5ab50182010-05-14 18:53:44 +0100400 case CURLFORM_BUFFERPTR:
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700401 current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100402 if(current_form->buffer)
403 return_value = CURL_FORMADD_OPTION_TWICE;
404 else {
405 char *buffer =
406 array_state?array_value:va_arg(params, char *);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700407 if(buffer) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100408 current_form->buffer = buffer; /* store for the moment */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700409 current_form->value = buffer; /* make it non-NULL to be accepted
410 as fine */
411 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100412 else
413 return_value = CURL_FORMADD_NULL;
414 }
415 break;
416
417 case CURLFORM_BUFFERLENGTH:
418 if(current_form->bufferlength)
419 return_value = CURL_FORMADD_OPTION_TWICE;
420 else
421 current_form->bufferlength =
422 array_state?(size_t)array_value:(size_t)va_arg(params, long);
423 break;
424
425 case CURLFORM_STREAM:
426 current_form->flags |= HTTPPOST_CALLBACK;
427 if(current_form->userp)
428 return_value = CURL_FORMADD_OPTION_TWICE;
429 else {
430 char *userp =
431 array_state?array_value:va_arg(params, char *);
432 if(userp) {
433 current_form->userp = userp;
434 current_form->value = userp; /* this isn't strictly true but we
435 derive a value from this later on
436 and we need this non-NULL to be
437 accepted as a fine form part */
438 }
439 else
440 return_value = CURL_FORMADD_NULL;
441 }
442 break;
443
444 case CURLFORM_CONTENTTYPE:
445 {
446 const char *contenttype =
447 array_state?array_value:va_arg(params, char *);
448 if(current_form->contenttype) {
449 if(current_form->flags & HTTPPOST_FILENAME) {
450 if(contenttype) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700451 char *type = strdup(contenttype);
452 if(!type)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100453 return_value = CURL_FORMADD_MEMORY;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700454 else {
455 form = AddFormInfo(NULL, type, current_form);
456 if(!form) {
457 free(type);
458 return_value = CURL_FORMADD_MEMORY;
459 }
460 else {
461 form->contenttype_alloc = TRUE;
462 current_form = form;
463 form = NULL;
464 }
465 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100466 }
467 else
468 return_value = CURL_FORMADD_NULL;
469 }
470 else
471 return_value = CURL_FORMADD_OPTION_TWICE;
472 }
473 else {
474 if(contenttype) {
475 current_form->contenttype = strdup(contenttype);
476 if(!current_form->contenttype)
477 return_value = CURL_FORMADD_MEMORY;
478 else
479 current_form->contenttype_alloc = TRUE;
480 }
481 else
482 return_value = CURL_FORMADD_NULL;
483 }
484 break;
485 }
486 case CURLFORM_CONTENTHEADER:
487 {
488 /* this "cast increases required alignment of target type" but
489 we consider it OK anyway */
Elliott Hughescee03382017-06-23 12:17:18 -0700490 struct curl_slist *list = array_state?
491 (struct curl_slist *)(void *)array_value:
492 va_arg(params, struct curl_slist *);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100493
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700494 if(current_form->contentheader)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100495 return_value = CURL_FORMADD_OPTION_TWICE;
496 else
497 current_form->contentheader = list;
498
499 break;
500 }
501 case CURLFORM_FILENAME:
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700502 case CURLFORM_BUFFER:
Kristian Monsen5ab50182010-05-14 18:53:44 +0100503 {
504 const char *filename = array_state?array_value:
505 va_arg(params, char *);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700506 if(current_form->showfilename)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100507 return_value = CURL_FORMADD_OPTION_TWICE;
508 else {
509 current_form->showfilename = strdup(filename);
510 if(!current_form->showfilename)
511 return_value = CURL_FORMADD_MEMORY;
512 else
513 current_form->showfilename_alloc = TRUE;
514 }
515 break;
516 }
517 default:
518 return_value = CURL_FORMADD_UNKNOWN_OPTION;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700519 break;
520 }
521 }
522
523 if(CURL_FORMADD_OK != return_value) {
524 /* On error, free allocated fields for all nodes of the FormInfo linked
525 list without deallocating nodes. List nodes are deallocated later on */
526 FormInfo *ptr;
527 for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
528 if(ptr->name_alloc) {
529 Curl_safefree(ptr->name);
530 ptr->name_alloc = FALSE;
531 }
532 if(ptr->value_alloc) {
533 Curl_safefree(ptr->value);
534 ptr->value_alloc = FALSE;
535 }
536 if(ptr->contenttype_alloc) {
537 Curl_safefree(ptr->contenttype);
538 ptr->contenttype_alloc = FALSE;
539 }
540 if(ptr->showfilename_alloc) {
541 Curl_safefree(ptr->showfilename);
542 ptr->showfilename_alloc = FALSE;
543 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100544 }
545 }
546
547 if(CURL_FORMADD_OK == return_value) {
548 /* go through the list, check for completeness and if everything is
549 * alright add the HttpPost item otherwise set return_value accordingly */
550
551 post = NULL;
552 for(form = first_form;
553 form != NULL;
554 form = form->more) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700555 if(((!form->name || !form->value) && !post) ||
556 ( (form->contentslength) &&
557 (form->flags & HTTPPOST_FILENAME) ) ||
558 ( (form->flags & HTTPPOST_FILENAME) &&
559 (form->flags & HTTPPOST_PTRCONTENTS) ) ||
Kristian Monsen5ab50182010-05-14 18:53:44 +0100560
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700561 ( (!form->buffer) &&
562 (form->flags & HTTPPOST_BUFFER) &&
563 (form->flags & HTTPPOST_PTRBUFFER) ) ||
Kristian Monsen5ab50182010-05-14 18:53:44 +0100564
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700565 ( (form->flags & HTTPPOST_READFILE) &&
566 (form->flags & HTTPPOST_PTRCONTENTS) )
Kristian Monsen5ab50182010-05-14 18:53:44 +0100567 ) {
568 return_value = CURL_FORMADD_INCOMPLETE;
569 break;
570 }
Elliott Hughes82be86d2017-09-20 17:00:17 -0700571 if(((form->flags & HTTPPOST_FILENAME) ||
572 (form->flags & HTTPPOST_BUFFER)) &&
573 !form->contenttype) {
574 char *f = form->flags & HTTPPOST_BUFFER?
575 form->showfilename : form->value;
Elliott Hughescac39802018-04-27 16:19:43 -0700576 char const *type;
577 type = Curl_mime_contenttype(f);
578 if(!type)
579 type = prevtype;
580 if(!type)
581 type = FILE_CONTENTTYPE_DEFAULT;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700582
Elliott Hughes82be86d2017-09-20 17:00:17 -0700583 /* our contenttype is missing */
Elliott Hughescac39802018-04-27 16:19:43 -0700584 form->contenttype = strdup(type);
Elliott Hughes82be86d2017-09-20 17:00:17 -0700585 if(!form->contenttype) {
Kristian Monsen5ab50182010-05-14 18:53:44 +0100586 return_value = CURL_FORMADD_MEMORY;
587 break;
588 }
Elliott Hughes82be86d2017-09-20 17:00:17 -0700589 form->contenttype_alloc = TRUE;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100590 }
Alex Deymo486467e2017-12-19 19:04:07 +0100591 if(form->name && form->namelength) {
592 /* Name should not contain nul bytes. */
593 size_t i;
594 for(i = 0; i < form->namelength; i++)
595 if(!form->name[i]) {
596 return_value = CURL_FORMADD_NULL;
597 break;
598 }
599 if(return_value != CURL_FORMADD_OK)
600 break;
601 }
Elliott Hughes82be86d2017-09-20 17:00:17 -0700602 if(!(form->flags & HTTPPOST_PTRNAME) &&
603 (form == first_form) ) {
604 /* Note that there's small risk that form->name is NULL here if the
605 app passed in a bad combo, so we better check for that first. */
606 if(form->name) {
Alex Deymo486467e2017-12-19 19:04:07 +0100607 /* copy name (without strdup; possibly not nul-terminated) */
Elliott Hughes82be86d2017-09-20 17:00:17 -0700608 form->name = Curl_memdup(form->name, form->namelength?
609 form->namelength:
Alex Deymo486467e2017-12-19 19:04:07 +0100610 strlen(form->name) + 1);
Elliott Hughes82be86d2017-09-20 17:00:17 -0700611 }
612 if(!form->name) {
613 return_value = CURL_FORMADD_MEMORY;
614 break;
615 }
616 form->name_alloc = TRUE;
617 }
618 if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
619 HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
620 HTTPPOST_CALLBACK)) && form->value) {
621 /* copy value (without strdup; possibly contains null characters) */
622 size_t clen = (size_t) form->contentslength;
623 if(!clen)
Alex Deymo486467e2017-12-19 19:04:07 +0100624 clen = strlen(form->value) + 1;
Elliott Hughes82be86d2017-09-20 17:00:17 -0700625
626 form->value = Curl_memdup(form->value, clen);
627
628 if(!form->value) {
629 return_value = CURL_FORMADD_MEMORY;
630 break;
631 }
632 form->value_alloc = TRUE;
633 }
634 post = AddHttpPost(form->name, form->namelength,
635 form->value, form->contentslength,
636 form->buffer, form->bufferlength,
637 form->contenttype, form->flags,
638 form->contentheader, form->showfilename,
639 form->userp,
640 post, httppost,
641 last_post);
642
643 if(!post) {
644 return_value = CURL_FORMADD_MEMORY;
645 break;
646 }
647
648 if(form->contenttype)
649 prevtype = form->contenttype;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100650 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700651 if(CURL_FORMADD_OK != return_value) {
652 /* On error, free allocated fields for nodes of the FormInfo linked
653 list which are not already owned by the httppost linked list
654 without deallocating nodes. List nodes are deallocated later on */
655 FormInfo *ptr;
656 for(ptr = form; ptr != NULL; ptr = ptr->more) {
657 if(ptr->name_alloc) {
658 Curl_safefree(ptr->name);
659 ptr->name_alloc = FALSE;
660 }
661 if(ptr->value_alloc) {
662 Curl_safefree(ptr->value);
663 ptr->value_alloc = FALSE;
664 }
665 if(ptr->contenttype_alloc) {
666 Curl_safefree(ptr->contenttype);
667 ptr->contenttype_alloc = FALSE;
668 }
669 if(ptr->showfilename_alloc) {
670 Curl_safefree(ptr->showfilename);
671 ptr->showfilename_alloc = FALSE;
672 }
673 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100674 }
675 }
676
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700677 /* Always deallocate FormInfo linked list nodes without touching node
678 fields given that these have either been deallocated or are owned
679 now by the httppost linked list */
680 while(first_form) {
681 FormInfo *ptr = first_form->more;
682 free(first_form);
683 first_form = ptr;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100684 }
685
686 return return_value;
687}
688
689/*
690 * curl_formadd() is a public API to add a section to the multipart formpost.
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700691 *
692 * @unittest: 1308
Kristian Monsen5ab50182010-05-14 18:53:44 +0100693 */
694
695CURLFORMcode curl_formadd(struct curl_httppost **httppost,
696 struct curl_httppost **last_post,
697 ...)
698{
699 va_list arg;
700 CURLFORMcode result;
701 va_start(arg, last_post);
702 result = FormAdd(httppost, last_post, arg);
703 va_end(arg);
704 return result;
705}
706
Kristian Monsen5ab50182010-05-14 18:53:44 +0100707/*
708 * curl_formget()
709 * Serialize a curl_httppost struct.
710 * Returns 0 on success.
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700711 *
712 * @unittest: 1308
Kristian Monsen5ab50182010-05-14 18:53:44 +0100713 */
714int curl_formget(struct curl_httppost *form, void *arg,
715 curl_formget_callback append)
716{
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700717 CURLcode result;
Alex Deymo486467e2017-12-19 19:04:07 +0100718 curl_mimepart toppart;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100719
Alex Deymo486467e2017-12-19 19:04:07 +0100720 Curl_mime_initpart(&toppart, NULL); /* default form is empty */
721 result = Curl_getformdata(NULL, &toppart, form, NULL);
722 if(!result)
723 result = Curl_mime_prepare_headers(&toppart, "multipart/form-data",
724 NULL, MIMESTRATEGY_FORM);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100725
Alex Deymo486467e2017-12-19 19:04:07 +0100726 while(!result) {
727 char buffer[8192];
728 size_t nread = Curl_mime_read(buffer, 1, sizeof buffer, &toppart);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100729
Alex Deymo486467e2017-12-19 19:04:07 +0100730 if(!nread)
731 break;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100732
Alex Deymo486467e2017-12-19 19:04:07 +0100733 switch(nread) {
734 default:
735 if(append(arg, buffer, nread) != nread)
736 result = CURLE_READ_ERROR;
737 break;
738 case CURL_READFUNC_ABORT:
739 case CURL_READFUNC_PAUSE:
740 break;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100741 }
742 }
Alex Deymo486467e2017-12-19 19:04:07 +0100743
744 Curl_mime_cleanpart(&toppart);
745 return (int) result;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100746}
747
748/*
749 * curl_formfree() is an external function to free up a whole form post
750 * chain
751 */
752void curl_formfree(struct curl_httppost *form)
753{
754 struct curl_httppost *next;
755
756 if(!form)
757 /* no form to free, just get out of this */
758 return;
759
760 do {
Alex Deymo486467e2017-12-19 19:04:07 +0100761 next = form->next; /* the following form line */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100762
763 /* recurse to sub-contents */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700764 curl_formfree(form->more);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100765
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700766 if(!(form->flags & HTTPPOST_PTRNAME))
Kristian Monsen5ab50182010-05-14 18:53:44 +0100767 free(form->name); /* free the name */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700768 if(!(form->flags &
769 (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK))
770 )
Kristian Monsen5ab50182010-05-14 18:53:44 +0100771 free(form->contents); /* free the contents */
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700772 free(form->contenttype); /* free the content type */
773 free(form->showfilename); /* free the faked file name */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100774 free(form); /* free the struct */
Elliott Hughes82be86d2017-09-20 17:00:17 -0700775 form = next;
776 } while(form); /* continue */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100777}
778
Kristian Monsen5ab50182010-05-14 18:53:44 +0100779
Alex Deymo486467e2017-12-19 19:04:07 +0100780/* Set mime part name, taking care of non nul-terminated name string. */
781static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100782{
Alex Deymo486467e2017-12-19 19:04:07 +0100783 char *zname;
784 CURLcode res;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100785
Alex Deymo486467e2017-12-19 19:04:07 +0100786 if(!name || !len)
787 return curl_mime_name(part, name);
788 zname = malloc(len + 1);
789 if(!zname)
790 return CURLE_OUT_OF_MEMORY;
791 memcpy(zname, name, len);
792 zname[len] = '\0';
793 res = curl_mime_name(part, zname);
794 free(zname);
795 return res;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700796}
797
Kristian Monsen5ab50182010-05-14 18:53:44 +0100798/*
Alex Deymo486467e2017-12-19 19:04:07 +0100799 * Curl_getformdata() converts a linked list of "meta data" into a mime
800 * structure. The input list is in 'post', while the output is stored in
801 * mime part at '*finalform'.
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700802 *
803 * This function will not do a failf() for the potential memory failures but
804 * should for all other errors it spots. Just note that this function MAY get
805 * a NULL pointer in the 'data' argument.
Kristian Monsen5ab50182010-05-14 18:53:44 +0100806 */
807
Alex Deymoe3149cc2016-10-05 11:18:42 -0700808CURLcode Curl_getformdata(struct Curl_easy *data,
Alex Deymo486467e2017-12-19 19:04:07 +0100809 curl_mimepart *finalform,
Kristian Monsen5ab50182010-05-14 18:53:44 +0100810 struct curl_httppost *post,
Alex Deymo486467e2017-12-19 19:04:07 +0100811 curl_read_callback fread_func)
Kristian Monsen5ab50182010-05-14 18:53:44 +0100812{
Kristian Monsen5ab50182010-05-14 18:53:44 +0100813 CURLcode result = CURLE_OK;
Alex Deymo486467e2017-12-19 19:04:07 +0100814 curl_mime *form = NULL;
815 curl_mime *multipart;
816 curl_mimepart *part;
817 struct curl_httppost *file;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100818
Alex Deymo486467e2017-12-19 19:04:07 +0100819 Curl_mime_cleanpart(finalform); /* default form is empty */
Kristian Monsen5ab50182010-05-14 18:53:44 +0100820
821 if(!post)
822 return result; /* no input => no output! */
823
Alex Deymo486467e2017-12-19 19:04:07 +0100824 form = curl_mime_init(data);
825 if(!form)
826 result = CURLE_OUT_OF_MEMORY;
Kristian Monsen5ab50182010-05-14 18:53:44 +0100827
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700828 if(!result)
Alex Deymo486467e2017-12-19 19:04:07 +0100829 result = curl_mime_subparts(finalform, form);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700830
Alex Deymo486467e2017-12-19 19:04:07 +0100831 /* Process each top part. */
832 for(; !result && post; post = post->next) {
833 /* If we have more than a file here, create a mime subpart and fill it. */
834 multipart = form;
835 if(post->more) {
836 part = curl_mime_addpart(form);
837 if(!part)
838 result = CURLE_OUT_OF_MEMORY;
839 if(!result)
840 result = setname(part, post->name, post->namelength);
841 if(!result) {
842 multipart = curl_mime_init(data);
843 if(!multipart)
844 result = CURLE_OUT_OF_MEMORY;
845 }
846 if(!result)
847 result = curl_mime_subparts(part, multipart);
848 }
849
850 /* Generate all the part contents. */
851 for(file = post; !result && file; file = file->more) {
852 /* Create the part. */
853 part = curl_mime_addpart(multipart);
854 if(!part)
855 result = CURLE_OUT_OF_MEMORY;
856
857 /* Set the headers. */
858 if(!result)
859 result = curl_mime_headers(part, file->contentheader, 0);
860
861 /* Set the content type. */
862 if(!result && file->contenttype)
863 result = curl_mime_type(part, file->contenttype);
864
865 /* Set field name. */
866 if(!result && !post->more)
867 result = setname(part, post->name, post->namelength);
868
869 /* Process contents. */
870 if(!result) {
871 curl_off_t clen = post->contentslength;
872
873 if(post->flags & CURL_HTTPPOST_LARGE)
874 clen = post->contentlen;
875 if(!clen)
876 clen = -1;
877
878 if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) {
879 if(!strcmp(file->contents, "-")) {
880 /* There are a few cases where the code below won't work; in
881 particular, freopen(stdin) by the caller is not guaranteed
882 to result as expected. This feature has been kept for backward
883 compatibility: use of "-" pseudo file name should be avoided. */
884 result = curl_mime_data_cb(part, (curl_off_t) -1,
885 (curl_read_callback) fread,
886 (curl_seek_callback) fseek,
887 NULL, (void *) stdin);
888 }
889 else
890 result = curl_mime_filedata(part, file->contents);
891 if(!result && (post->flags & HTTPPOST_READFILE))
892 result = curl_mime_filename(part, NULL);
893 }
894 else if(post->flags & HTTPPOST_BUFFER)
895 result = curl_mime_data(part, post->buffer,
896 post->bufferlength? post->bufferlength: -1);
897 else if(post->flags & HTTPPOST_CALLBACK)
898 /* the contents should be read with the callback and the size is set
899 with the contentslength */
900 result = curl_mime_data_cb(part, clen,
901 fread_func, NULL, NULL, post->userp);
902 else {
903 result = curl_mime_data(part, post->contents, (ssize_t) clen);
904#ifdef CURL_DOES_CONVERSIONS
905 /* Convert textual contents now. */
906 if(!result && data && part->datasize)
907 result = Curl_convert_to_network(data, part->data, part->datasize);
908#endif
909 }
910 }
911
912 /* Set fake file name. */
913 if(!result && post->showfilename)
914 if(post->more || (post->flags & (HTTPPOST_FILENAME | HTTPPOST_BUFFER |
915 HTTPPOST_CALLBACK)))
916 result = curl_mime_filename(part, post->showfilename);
917 }
Kristian Monsen5ab50182010-05-14 18:53:44 +0100918 }
919
Alex Deymo486467e2017-12-19 19:04:07 +0100920 if(result)
921 Curl_mime_cleanpart(finalform);
Kristian Monsen5ab50182010-05-14 18:53:44 +0100922
923 return result;
924}
925
Kristian Monsen5ab50182010-05-14 18:53:44 +0100926#else /* CURL_DISABLE_HTTP */
927CURLFORMcode curl_formadd(struct curl_httppost **httppost,
928 struct curl_httppost **last_post,
929 ...)
930{
931 (void)httppost;
932 (void)last_post;
933 return CURL_FORMADD_DISABLED;
934}
935
936int curl_formget(struct curl_httppost *form, void *arg,
937 curl_formget_callback append)
938{
939 (void) form;
940 (void) arg;
941 (void) append;
942 return CURL_FORMADD_DISABLED;
943}
944
945void curl_formfree(struct curl_httppost *form)
946{
947 (void)form;
948 /* does nothing HTTP is disabled */
949}
950
Kristian Monsen5ab50182010-05-14 18:53:44 +0100951
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700952#endif /* !defined(CURL_DISABLE_HTTP) */