1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2020, 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.haxx.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 ***************************************************************************/
22
23 #include "curl_setup.h"
24
25 #include <curl/curl.h>
26
27 #include "formdata.h"
28 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)
29
30 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
31 #include <libgen.h>
32 #endif
33
34 #include "urldata.h" /* for struct Curl_easy */
35 #include "mime.h"
36 #include "non-ascii.h"
37 #include "vtls/vtls.h"
38 #include "strcase.h"
39 #include "sendf.h"
40 #include "strdup.h"
41 #include "rand.h"
42 #include "warnless.h"
43 /* The last 3 #include files should be in this order */
44 #include "curl_printf.h"
45 #include "curl_memory.h"
46 #include "memdebug.h"
47
48
49 #define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
50 #define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
51 #define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
52 #define HTTPPOST_READFILE CURL_HTTPPOST_READFILE
53 #define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER
54 #define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK
55 #define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER
56
57 /***************************************************************************
58 *
59 * AddHttpPost()
60 *
61 * Adds a HttpPost structure to the list, if parent_post is given becomes
62 * a subpost of parent_post instead of a direct list element.
63 *
64 * Returns newly allocated HttpPost on success and NULL if malloc failed.
65 *
66 ***************************************************************************/
67 static struct curl_httppost *
AddHttpPost(char * name,size_t namelength,char * value,curl_off_t contentslength,char * buffer,size_t bufferlength,char * contenttype,long flags,struct curl_slist * contentHeader,char * showfilename,char * userp,struct curl_httppost * parent_post,struct curl_httppost ** httppost,struct curl_httppost ** last_post)68 AddHttpPost(char *name, size_t namelength,
69 char *value, curl_off_t contentslength,
70 char *buffer, size_t bufferlength,
71 char *contenttype,
72 long flags,
73 struct curl_slist *contentHeader,
74 char *showfilename, char *userp,
75 struct curl_httppost *parent_post,
76 struct curl_httppost **httppost,
77 struct curl_httppost **last_post)
78 {
79 struct curl_httppost *post;
80 post = calloc(1, sizeof(struct curl_httppost));
81 if(post) {
82 post->name = name;
83 post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
84 post->contents = value;
85 post->contentlen = contentslength;
86 post->buffer = buffer;
87 post->bufferlength = (long)bufferlength;
88 post->contenttype = contenttype;
89 post->contentheader = contentHeader;
90 post->showfilename = showfilename;
91 post->userp = userp;
92 post->flags = flags | CURL_HTTPPOST_LARGE;
93 }
94 else
95 return NULL;
96
97 if(parent_post) {
98 /* now, point our 'more' to the original 'more' */
99 post->more = parent_post->more;
100
101 /* then move the original 'more' to point to ourselves */
102 parent_post->more = post;
103 }
104 else {
105 /* make the previous point to this */
106 if(*last_post)
107 (*last_post)->next = post;
108 else
109 (*httppost) = post;
110
111 (*last_post) = post;
112 }
113 return post;
114 }
115
116 /***************************************************************************
117 *
118 * AddFormInfo()
119 *
120 * Adds a FormInfo structure to the list presented by parent_form_info.
121 *
122 * Returns newly allocated FormInfo on success and NULL if malloc failed/
123 * parent_form_info is NULL.
124 *
125 ***************************************************************************/
AddFormInfo(char * value,char * contenttype,struct FormInfo * parent_form_info)126 static struct FormInfo *AddFormInfo(char *value,
127 char *contenttype,
128 struct FormInfo *parent_form_info)
129 {
130 struct FormInfo *form_info;
131 form_info = calloc(1, sizeof(struct FormInfo));
132 if(form_info) {
133 if(value)
134 form_info->value = value;
135 if(contenttype)
136 form_info->contenttype = contenttype;
137 form_info->flags = HTTPPOST_FILENAME;
138 }
139 else
140 return NULL;
141
142 if(parent_form_info) {
143 /* now, point our 'more' to the original 'more' */
144 form_info->more = parent_form_info->more;
145
146 /* then move the original 'more' to point to ourselves */
147 parent_form_info->more = form_info;
148 }
149
150 return form_info;
151 }
152
153 /***************************************************************************
154 *
155 * FormAdd()
156 *
157 * Stores a formpost parameter and builds the appropriate linked list.
158 *
159 * Has two principal functionalities: using files and byte arrays as
160 * post parts. Byte arrays are either copied or just the pointer is stored
161 * (as the user requests) while for files only the filename and not the
162 * content is stored.
163 *
164 * While you may have only one byte array for each name, multiple filenames
165 * are allowed (and because of this feature CURLFORM_END is needed after
166 * using CURLFORM_FILE).
167 *
168 * Examples:
169 *
170 * Simple name/value pair with copied contents:
171 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
172 * CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
173 *
174 * name/value pair where only the content pointer is remembered:
175 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
176 * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END);
177 * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
178 *
179 * storing a filename (CONTENTTYPE is optional!):
180 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
181 * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text",
182 * CURLFORM_END);
183 *
184 * storing multiple filenames:
185 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
186 * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
187 *
188 * Returns:
189 * CURL_FORMADD_OK on success
190 * CURL_FORMADD_MEMORY if the FormInfo allocation fails
191 * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
192 * CURL_FORMADD_NULL if a null pointer was given for a char
193 * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
194 * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
195 * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
196 * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated
197 * CURL_FORMADD_MEMORY if some allocation for string copying failed.
198 * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
199 *
200 ***************************************************************************/
201
202 static
FormAdd(struct curl_httppost ** httppost,struct curl_httppost ** last_post,va_list params)203 CURLFORMcode FormAdd(struct curl_httppost **httppost,
204 struct curl_httppost **last_post,
205 va_list params)
206 {
207 struct FormInfo *first_form, *current_form, *form = NULL;
208 CURLFORMcode return_value = CURL_FORMADD_OK;
209 const char *prevtype = NULL;
210 struct curl_httppost *post = NULL;
211 CURLformoption option;
212 struct curl_forms *forms = NULL;
213 char *array_value = NULL; /* value read from an array */
214
215 /* This is a state variable, that if TRUE means that we're parsing an
216 array that we got passed to us. If FALSE we're parsing the input
217 va_list arguments. */
218 bool array_state = FALSE;
219
220 /*
221 * We need to allocate the first struct to fill in.
222 */
223 first_form = calloc(1, sizeof(struct FormInfo));
224 if(!first_form)
225 return CURL_FORMADD_MEMORY;
226
227 current_form = first_form;
228
229 /*
230 * Loop through all the options set. Break if we have an error to report.
231 */
232 while(return_value == CURL_FORMADD_OK) {
233
234 /* first see if we have more parts of the array param */
235 if(array_state && forms) {
236 /* get the upcoming option from the given array */
237 option = forms->option;
238 array_value = (char *)forms->value;
239
240 forms++; /* advance this to next entry */
241 if(CURLFORM_END == option) {
242 /* end of array state */
243 array_state = FALSE;
244 continue;
245 }
246 }
247 else {
248 /* This is not array-state, get next option */
249 option = va_arg(params, CURLformoption);
250 if(CURLFORM_END == option)
251 break;
252 }
253
254 switch(option) {
255 case CURLFORM_ARRAY:
256 if(array_state)
257 /* we don't support an array from within an array */
258 return_value = CURL_FORMADD_ILLEGAL_ARRAY;
259 else {
260 forms = va_arg(params, struct curl_forms *);
261 if(forms)
262 array_state = TRUE;
263 else
264 return_value = CURL_FORMADD_NULL;
265 }
266 break;
267
268 /*
269 * Set the Name property.
270 */
271 case CURLFORM_PTRNAME:
272 #ifdef CURL_DOES_CONVERSIONS
273 /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy
274 * the data in all cases so that we'll have safe memory for the eventual
275 * conversion.
276 */
277 #else
278 current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
279 #endif
280 /* FALLTHROUGH */
281 case CURLFORM_COPYNAME:
282 if(current_form->name)
283 return_value = CURL_FORMADD_OPTION_TWICE;
284 else {
285 char *name = array_state?
286 array_value:va_arg(params, char *);
287 if(name)
288 current_form->name = name; /* store for the moment */
289 else
290 return_value = CURL_FORMADD_NULL;
291 }
292 break;
293 case CURLFORM_NAMELENGTH:
294 if(current_form->namelength)
295 return_value = CURL_FORMADD_OPTION_TWICE;
296 else
297 current_form->namelength =
298 array_state?(size_t)array_value:(size_t)va_arg(params, long);
299 break;
300
301 /*
302 * Set the contents property.
303 */
304 case CURLFORM_PTRCONTENTS:
305 current_form->flags |= HTTPPOST_PTRCONTENTS;
306 /* FALLTHROUGH */
307 case CURLFORM_COPYCONTENTS:
308 if(current_form->value)
309 return_value = CURL_FORMADD_OPTION_TWICE;
310 else {
311 char *value =
312 array_state?array_value:va_arg(params, char *);
313 if(value)
314 current_form->value = value; /* store for the moment */
315 else
316 return_value = CURL_FORMADD_NULL;
317 }
318 break;
319 case CURLFORM_CONTENTSLENGTH:
320 current_form->contentslength =
321 array_state?(size_t)array_value:(size_t)va_arg(params, long);
322 break;
323
324 case CURLFORM_CONTENTLEN:
325 current_form->flags |= CURL_HTTPPOST_LARGE;
326 current_form->contentslength =
327 array_state?(curl_off_t)(size_t)array_value:va_arg(params, curl_off_t);
328 break;
329
330 /* Get contents from a given file name */
331 case CURLFORM_FILECONTENT:
332 if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
333 return_value = CURL_FORMADD_OPTION_TWICE;
334 else {
335 const char *filename = array_state?
336 array_value:va_arg(params, char *);
337 if(filename) {
338 current_form->value = strdup(filename);
339 if(!current_form->value)
340 return_value = CURL_FORMADD_MEMORY;
341 else {
342 current_form->flags |= HTTPPOST_READFILE;
343 current_form->value_alloc = TRUE;
344 }
345 }
346 else
347 return_value = CURL_FORMADD_NULL;
348 }
349 break;
350
351 /* We upload a file */
352 case CURLFORM_FILE:
353 {
354 const char *filename = array_state?array_value:
355 va_arg(params, char *);
356
357 if(current_form->value) {
358 if(current_form->flags & HTTPPOST_FILENAME) {
359 if(filename) {
360 char *fname = strdup(filename);
361 if(!fname)
362 return_value = CURL_FORMADD_MEMORY;
363 else {
364 form = AddFormInfo(fname, NULL, current_form);
365 if(!form) {
366 free(fname);
367 return_value = CURL_FORMADD_MEMORY;
368 }
369 else {
370 form->value_alloc = TRUE;
371 current_form = form;
372 form = NULL;
373 }
374 }
375 }
376 else
377 return_value = CURL_FORMADD_NULL;
378 }
379 else
380 return_value = CURL_FORMADD_OPTION_TWICE;
381 }
382 else {
383 if(filename) {
384 current_form->value = strdup(filename);
385 if(!current_form->value)
386 return_value = CURL_FORMADD_MEMORY;
387 else {
388 current_form->flags |= HTTPPOST_FILENAME;
389 current_form->value_alloc = TRUE;
390 }
391 }
392 else
393 return_value = CURL_FORMADD_NULL;
394 }
395 break;
396 }
397
398 case CURLFORM_BUFFERPTR:
399 current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
400 if(current_form->buffer)
401 return_value = CURL_FORMADD_OPTION_TWICE;
402 else {
403 char *buffer =
404 array_state?array_value:va_arg(params, char *);
405 if(buffer) {
406 current_form->buffer = buffer; /* store for the moment */
407 current_form->value = buffer; /* make it non-NULL to be accepted
408 as fine */
409 }
410 else
411 return_value = CURL_FORMADD_NULL;
412 }
413 break;
414
415 case CURLFORM_BUFFERLENGTH:
416 if(current_form->bufferlength)
417 return_value = CURL_FORMADD_OPTION_TWICE;
418 else
419 current_form->bufferlength =
420 array_state?(size_t)array_value:(size_t)va_arg(params, long);
421 break;
422
423 case CURLFORM_STREAM:
424 current_form->flags |= HTTPPOST_CALLBACK;
425 if(current_form->userp)
426 return_value = CURL_FORMADD_OPTION_TWICE;
427 else {
428 char *userp =
429 array_state?array_value:va_arg(params, char *);
430 if(userp) {
431 current_form->userp = userp;
432 current_form->value = userp; /* this isn't strictly true but we
433 derive a value from this later on
434 and we need this non-NULL to be
435 accepted as a fine form part */
436 }
437 else
438 return_value = CURL_FORMADD_NULL;
439 }
440 break;
441
442 case CURLFORM_CONTENTTYPE:
443 {
444 const char *contenttype =
445 array_state?array_value:va_arg(params, char *);
446 if(current_form->contenttype) {
447 if(current_form->flags & HTTPPOST_FILENAME) {
448 if(contenttype) {
449 char *type = strdup(contenttype);
450 if(!type)
451 return_value = CURL_FORMADD_MEMORY;
452 else {
453 form = AddFormInfo(NULL, type, current_form);
454 if(!form) {
455 free(type);
456 return_value = CURL_FORMADD_MEMORY;
457 }
458 else {
459 form->contenttype_alloc = TRUE;
460 current_form = form;
461 form = NULL;
462 }
463 }
464 }
465 else
466 return_value = CURL_FORMADD_NULL;
467 }
468 else
469 return_value = CURL_FORMADD_OPTION_TWICE;
470 }
471 else {
472 if(contenttype) {
473 current_form->contenttype = strdup(contenttype);
474 if(!current_form->contenttype)
475 return_value = CURL_FORMADD_MEMORY;
476 else
477 current_form->contenttype_alloc = TRUE;
478 }
479 else
480 return_value = CURL_FORMADD_NULL;
481 }
482 break;
483 }
484 case CURLFORM_CONTENTHEADER:
485 {
486 /* this "cast increases required alignment of target type" but
487 we consider it OK anyway */
488 struct curl_slist *list = array_state?
489 (struct curl_slist *)(void *)array_value:
490 va_arg(params, struct curl_slist *);
491
492 if(current_form->contentheader)
493 return_value = CURL_FORMADD_OPTION_TWICE;
494 else
495 current_form->contentheader = list;
496
497 break;
498 }
499 case CURLFORM_FILENAME:
500 case CURLFORM_BUFFER:
501 {
502 const char *filename = array_state?array_value:
503 va_arg(params, char *);
504 if(current_form->showfilename)
505 return_value = CURL_FORMADD_OPTION_TWICE;
506 else {
507 current_form->showfilename = strdup(filename);
508 if(!current_form->showfilename)
509 return_value = CURL_FORMADD_MEMORY;
510 else
511 current_form->showfilename_alloc = TRUE;
512 }
513 break;
514 }
515 default:
516 return_value = CURL_FORMADD_UNKNOWN_OPTION;
517 break;
518 }
519 }
520
521 if(CURL_FORMADD_OK != return_value) {
522 /* On error, free allocated fields for all nodes of the FormInfo linked
523 list without deallocating nodes. List nodes are deallocated later on */
524 struct FormInfo *ptr;
525 for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
526 if(ptr->name_alloc) {
527 Curl_safefree(ptr->name);
528 ptr->name_alloc = FALSE;
529 }
530 if(ptr->value_alloc) {
531 Curl_safefree(ptr->value);
532 ptr->value_alloc = FALSE;
533 }
534 if(ptr->contenttype_alloc) {
535 Curl_safefree(ptr->contenttype);
536 ptr->contenttype_alloc = FALSE;
537 }
538 if(ptr->showfilename_alloc) {
539 Curl_safefree(ptr->showfilename);
540 ptr->showfilename_alloc = FALSE;
541 }
542 }
543 }
544
545 if(CURL_FORMADD_OK == return_value) {
546 /* go through the list, check for completeness and if everything is
547 * alright add the HttpPost item otherwise set return_value accordingly */
548
549 post = NULL;
550 for(form = first_form;
551 form != NULL;
552 form = form->more) {
553 if(((!form->name || !form->value) && !post) ||
554 ( (form->contentslength) &&
555 (form->flags & HTTPPOST_FILENAME) ) ||
556 ( (form->flags & HTTPPOST_FILENAME) &&
557 (form->flags & HTTPPOST_PTRCONTENTS) ) ||
558
559 ( (!form->buffer) &&
560 (form->flags & HTTPPOST_BUFFER) &&
561 (form->flags & HTTPPOST_PTRBUFFER) ) ||
562
563 ( (form->flags & HTTPPOST_READFILE) &&
564 (form->flags & HTTPPOST_PTRCONTENTS) )
565 ) {
566 return_value = CURL_FORMADD_INCOMPLETE;
567 break;
568 }
569 if(((form->flags & HTTPPOST_FILENAME) ||
570 (form->flags & HTTPPOST_BUFFER)) &&
571 !form->contenttype) {
572 char *f = (form->flags & HTTPPOST_BUFFER)?
573 form->showfilename : form->value;
574 char const *type;
575 type = Curl_mime_contenttype(f);
576 if(!type)
577 type = prevtype;
578 if(!type)
579 type = FILE_CONTENTTYPE_DEFAULT;
580
581 /* our contenttype is missing */
582 form->contenttype = strdup(type);
583 if(!form->contenttype) {
584 return_value = CURL_FORMADD_MEMORY;
585 break;
586 }
587 form->contenttype_alloc = TRUE;
588 }
589 if(form->name && form->namelength) {
590 /* Name should not contain nul bytes. */
591 size_t i;
592 for(i = 0; i < form->namelength; i++)
593 if(!form->name[i]) {
594 return_value = CURL_FORMADD_NULL;
595 break;
596 }
597 if(return_value != CURL_FORMADD_OK)
598 break;
599 }
600 if(!(form->flags & HTTPPOST_PTRNAME) &&
601 (form == first_form) ) {
602 /* Note that there's small risk that form->name is NULL here if the
603 app passed in a bad combo, so we better check for that first. */
604 if(form->name) {
605 /* copy name (without strdup; possibly not null-terminated) */
606 form->name = Curl_memdup(form->name, form->namelength?
607 form->namelength:
608 strlen(form->name) + 1);
609 }
610 if(!form->name) {
611 return_value = CURL_FORMADD_MEMORY;
612 break;
613 }
614 form->name_alloc = TRUE;
615 }
616 if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
617 HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
618 HTTPPOST_CALLBACK)) && form->value) {
619 /* copy value (without strdup; possibly contains null characters) */
620 size_t clen = (size_t) form->contentslength;
621 if(!clen)
622 clen = strlen(form->value) + 1;
623
624 form->value = Curl_memdup(form->value, clen);
625
626 if(!form->value) {
627 return_value = CURL_FORMADD_MEMORY;
628 break;
629 }
630 form->value_alloc = TRUE;
631 }
632 post = AddHttpPost(form->name, form->namelength,
633 form->value, form->contentslength,
634 form->buffer, form->bufferlength,
635 form->contenttype, form->flags,
636 form->contentheader, form->showfilename,
637 form->userp,
638 post, httppost,
639 last_post);
640
641 if(!post) {
642 return_value = CURL_FORMADD_MEMORY;
643 break;
644 }
645
646 if(form->contenttype)
647 prevtype = form->contenttype;
648 }
649 if(CURL_FORMADD_OK != return_value) {
650 /* On error, free allocated fields for nodes of the FormInfo linked
651 list which are not already owned by the httppost linked list
652 without deallocating nodes. List nodes are deallocated later on */
653 struct FormInfo *ptr;
654 for(ptr = form; ptr != NULL; ptr = ptr->more) {
655 if(ptr->name_alloc) {
656 Curl_safefree(ptr->name);
657 ptr->name_alloc = FALSE;
658 }
659 if(ptr->value_alloc) {
660 Curl_safefree(ptr->value);
661 ptr->value_alloc = FALSE;
662 }
663 if(ptr->contenttype_alloc) {
664 Curl_safefree(ptr->contenttype);
665 ptr->contenttype_alloc = FALSE;
666 }
667 if(ptr->showfilename_alloc) {
668 Curl_safefree(ptr->showfilename);
669 ptr->showfilename_alloc = FALSE;
670 }
671 }
672 }
673 }
674
675 /* Always deallocate FormInfo linked list nodes without touching node
676 fields given that these have either been deallocated or are owned
677 now by the httppost linked list */
678 while(first_form) {
679 struct FormInfo *ptr = first_form->more;
680 free(first_form);
681 first_form = ptr;
682 }
683
684 return return_value;
685 }
686
687 /*
688 * curl_formadd() is a public API to add a section to the multipart formpost.
689 *
690 * @unittest: 1308
691 */
692
curl_formadd(struct curl_httppost ** httppost,struct curl_httppost ** last_post,...)693 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
694 struct curl_httppost **last_post,
695 ...)
696 {
697 va_list arg;
698 CURLFORMcode result;
699 va_start(arg, last_post);
700 result = FormAdd(httppost, last_post, arg);
701 va_end(arg);
702 return result;
703 }
704
705 /*
706 * curl_formget()
707 * Serialize a curl_httppost struct.
708 * Returns 0 on success.
709 *
710 * @unittest: 1308
711 */
curl_formget(struct curl_httppost * form,void * arg,curl_formget_callback append)712 int curl_formget(struct curl_httppost *form, void *arg,
713 curl_formget_callback append)
714 {
715 CURLcode result;
716 curl_mimepart toppart;
717
718 Curl_mime_initpart(&toppart, NULL); /* default form is empty */
719 result = Curl_getformdata(NULL, &toppart, form, NULL);
720 if(!result)
721 result = Curl_mime_prepare_headers(&toppart, "multipart/form-data",
722 NULL, MIMESTRATEGY_FORM);
723
724 while(!result) {
725 char buffer[8192];
726 size_t nread = Curl_mime_read(buffer, 1, sizeof(buffer), &toppart);
727
728 if(!nread)
729 break;
730
731 if(nread > sizeof(buffer) || append(arg, buffer, nread) != nread) {
732 result = CURLE_READ_ERROR;
733 if(nread == CURL_READFUNC_ABORT)
734 result = CURLE_ABORTED_BY_CALLBACK;
735 }
736 }
737
738 Curl_mime_cleanpart(&toppart);
739 return (int) result;
740 }
741
742 /*
743 * curl_formfree() is an external function to free up a whole form post
744 * chain
745 */
curl_formfree(struct curl_httppost * form)746 void curl_formfree(struct curl_httppost *form)
747 {
748 struct curl_httppost *next;
749
750 if(!form)
751 /* no form to free, just get out of this */
752 return;
753
754 do {
755 next = form->next; /* the following form line */
756
757 /* recurse to sub-contents */
758 curl_formfree(form->more);
759
760 if(!(form->flags & HTTPPOST_PTRNAME))
761 free(form->name); /* free the name */
762 if(!(form->flags &
763 (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK))
764 )
765 free(form->contents); /* free the contents */
766 free(form->contenttype); /* free the content type */
767 free(form->showfilename); /* free the faked file name */
768 free(form); /* free the struct */
769 form = next;
770 } while(form); /* continue */
771 }
772
773
774 /* Set mime part name, taking care of non null-terminated name string. */
setname(curl_mimepart * part,const char * name,size_t len)775 static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
776 {
777 char *zname;
778 CURLcode res;
779
780 if(!name || !len)
781 return curl_mime_name(part, name);
782 zname = malloc(len + 1);
783 if(!zname)
784 return CURLE_OUT_OF_MEMORY;
785 memcpy(zname, name, len);
786 zname[len] = '\0';
787 res = curl_mime_name(part, zname);
788 free(zname);
789 return res;
790 }
791
792 /*
793 * Curl_getformdata() converts a linked list of "meta data" into a mime
794 * structure. The input list is in 'post', while the output is stored in
795 * mime part at '*finalform'.
796 *
797 * This function will not do a failf() for the potential memory failures but
798 * should for all other errors it spots. Just note that this function MAY get
799 * a NULL pointer in the 'data' argument.
800 */
801
Curl_getformdata(struct Curl_easy * data,curl_mimepart * finalform,struct curl_httppost * post,curl_read_callback fread_func)802 CURLcode Curl_getformdata(struct Curl_easy *data,
803 curl_mimepart *finalform,
804 struct curl_httppost *post,
805 curl_read_callback fread_func)
806 {
807 CURLcode result = CURLE_OK;
808 curl_mime *form = NULL;
809 curl_mimepart *part;
810 struct curl_httppost *file;
811
812 Curl_mime_cleanpart(finalform); /* default form is empty */
813
814 if(!post)
815 return result; /* no input => no output! */
816
817 form = curl_mime_init(data);
818 if(!form)
819 result = CURLE_OUT_OF_MEMORY;
820
821 if(!result)
822 result = curl_mime_subparts(finalform, form);
823
824 /* Process each top part. */
825 for(; !result && post; post = post->next) {
826 /* If we have more than a file here, create a mime subpart and fill it. */
827 curl_mime *multipart = form;
828 if(post->more) {
829 part = curl_mime_addpart(form);
830 if(!part)
831 result = CURLE_OUT_OF_MEMORY;
832 if(!result)
833 result = setname(part, post->name, post->namelength);
834 if(!result) {
835 multipart = curl_mime_init(data);
836 if(!multipart)
837 result = CURLE_OUT_OF_MEMORY;
838 }
839 if(!result)
840 result = curl_mime_subparts(part, multipart);
841 }
842
843 /* Generate all the part contents. */
844 for(file = post; !result && file; file = file->more) {
845 /* Create the part. */
846 part = curl_mime_addpart(multipart);
847 if(!part)
848 result = CURLE_OUT_OF_MEMORY;
849
850 /* Set the headers. */
851 if(!result)
852 result = curl_mime_headers(part, file->contentheader, 0);
853
854 /* Set the content type. */
855 if(!result && file->contenttype)
856 result = curl_mime_type(part, file->contenttype);
857
858 /* Set field name. */
859 if(!result && !post->more)
860 result = setname(part, post->name, post->namelength);
861
862 /* Process contents. */
863 if(!result) {
864 curl_off_t clen = post->contentslength;
865
866 if(post->flags & CURL_HTTPPOST_LARGE)
867 clen = post->contentlen;
868 if(!clen)
869 clen = -1;
870
871 if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) {
872 if(!strcmp(file->contents, "-")) {
873 /* There are a few cases where the code below won't work; in
874 particular, freopen(stdin) by the caller is not guaranteed
875 to result as expected. This feature has been kept for backward
876 compatibility: use of "-" pseudo file name should be avoided. */
877 result = curl_mime_data_cb(part, (curl_off_t) -1,
878 (curl_read_callback) fread,
879 CURLX_FUNCTION_CAST(curl_seek_callback,
880 fseek),
881 NULL, (void *) stdin);
882 }
883 else
884 result = curl_mime_filedata(part, file->contents);
885 if(!result && (post->flags & HTTPPOST_READFILE))
886 result = curl_mime_filename(part, NULL);
887 }
888 else if(post->flags & HTTPPOST_BUFFER)
889 result = curl_mime_data(part, post->buffer,
890 post->bufferlength? post->bufferlength: -1);
891 else if(post->flags & HTTPPOST_CALLBACK)
892 /* the contents should be read with the callback and the size is set
893 with the contentslength */
894 result = curl_mime_data_cb(part, clen,
895 fread_func, NULL, NULL, post->userp);
896 else {
897 result = curl_mime_data(part, post->contents, (ssize_t) clen);
898 #ifdef CURL_DOES_CONVERSIONS
899 /* Convert textual contents now. */
900 if(!result && data && part->datasize)
901 result = Curl_convert_to_network(data, part->data, part->datasize);
902 #endif
903 }
904 }
905
906 /* Set fake file name. */
907 if(!result && post->showfilename)
908 if(post->more || (post->flags & (HTTPPOST_FILENAME | HTTPPOST_BUFFER |
909 HTTPPOST_CALLBACK)))
910 result = curl_mime_filename(part, post->showfilename);
911 }
912 }
913
914 if(result)
915 Curl_mime_cleanpart(finalform);
916
917 return result;
918 }
919
920 #else
921 /* if disabled */
curl_formadd(struct curl_httppost ** httppost,struct curl_httppost ** last_post,...)922 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
923 struct curl_httppost **last_post,
924 ...)
925 {
926 (void)httppost;
927 (void)last_post;
928 return CURL_FORMADD_DISABLED;
929 }
930
curl_formget(struct curl_httppost * form,void * arg,curl_formget_callback append)931 int curl_formget(struct curl_httppost *form, void *arg,
932 curl_formget_callback append)
933 {
934 (void) form;
935 (void) arg;
936 (void) append;
937 return CURL_FORMADD_DISABLED;
938 }
939
curl_formfree(struct curl_httppost * form)940 void curl_formfree(struct curl_httppost *form)
941 {
942 (void)form;
943 /* does nothing HTTP is disabled */
944 }
945
946 #endif /* if disabled */
947