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