smtp: use the upload buffer size for scratch buffer malloc
[platform/upstream/curl.git] / lib / formdata.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2018, 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 #ifndef CURL_DISABLE_HTTP
28
29 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
30 #include <libgen.h>
31 #endif
32
33 #include "urldata.h" /* for struct Curl_easy */
34 #include "formdata.h"
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 /* 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 /* What kind of Content-Type to use on un-specified files with unrecognized
49    extensions. */
50 #define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
51
52 #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
60 /***************************************************************************
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  ***************************************************************************/
70 static struct curl_httppost *
71 AddHttpPost(char *name, size_t namelength,
72             char *value, curl_off_t contentslength,
73             char *buffer, size_t bufferlength,
74             char *contenttype,
75             long flags,
76             struct curl_slist *contentHeader,
77             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;
88     post->contentlen = contentslength;
89     post->buffer = buffer;
90     post->bufferlength = (long)bufferlength;
91     post->contenttype = contenttype;
92     post->contentheader = contentHeader;
93     post->showfilename = showfilename;
94     post->userp = userp;
95     post->flags = flags | CURL_HTTPPOST_LARGE;
96   }
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  ***************************************************************************/
129 static 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   }
152
153   return form_info;
154 }
155
156 /***************************************************************************
157  *
158  * 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
198  * CURL_FORMADD_INCOMPLETE     if the some FormInfo is not complete (or error)
199  * 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
205 static
206 CURLFORMcode 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;
216   char *array_value = NULL; /* value read from an array */
217
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 */
238     if(array_state && forms) {
239       /* 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
257     switch(option) {
258     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
276       /* 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        */
280 #else
281       current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
282 #endif
283       /* FALLTHROUGH */
284     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:
322       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);
330       break;
331
332       /* Get contents from a given file name */
333     case CURLFORM_FILECONTENT:
334       if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
335         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) {
362               char *fname = strdup(filename);
363               if(!fname)
364                 return_value = CURL_FORMADD_MEMORY;
365               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               }
377             }
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
400     case CURLFORM_BUFFERPTR:
401       current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
402       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 *);
407         if(buffer) {
408           current_form->buffer = buffer; /* store for the moment */
409           current_form->value = buffer; /* make it non-NULL to be accepted
410                                            as fine */
411         }
412         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) {
451               char *type = strdup(contenttype);
452               if(!type)
453                 return_value = CURL_FORMADD_MEMORY;
454               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               }
466             }
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 */
490         struct curl_slist *list = array_state?
491           (struct curl_slist *)(void *)array_value:
492           va_arg(params, struct curl_slist *);
493
494         if(current_form->contentheader)
495           return_value = CURL_FORMADD_OPTION_TWICE;
496         else
497           current_form->contentheader = list;
498
499         break;
500       }
501     case CURLFORM_FILENAME:
502     case CURLFORM_BUFFER:
503       {
504         const char *filename = array_state?array_value:
505           va_arg(params, char *);
506         if(current_form->showfilename)
507           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;
519       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       }
544     }
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) {
555       if(((!form->name || !form->value) && !post) ||
556          ( (form->contentslength) &&
557            (form->flags & HTTPPOST_FILENAME) ) ||
558          ( (form->flags & HTTPPOST_FILENAME) &&
559            (form->flags & HTTPPOST_PTRCONTENTS) ) ||
560
561          ( (!form->buffer) &&
562            (form->flags & HTTPPOST_BUFFER) &&
563            (form->flags & HTTPPOST_PTRBUFFER) ) ||
564
565          ( (form->flags & HTTPPOST_READFILE) &&
566            (form->flags & HTTPPOST_PTRCONTENTS) )
567         ) {
568         return_value = CURL_FORMADD_INCOMPLETE;
569         break;
570       }
571       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;
576         char const *type;
577         type = Curl_mime_contenttype(f);
578         if(!type)
579           type = prevtype;
580         if(!type)
581           type = FILE_CONTENTTYPE_DEFAULT;
582
583         /* our contenttype is missing */
584         form->contenttype = strdup(type);
585         if(!form->contenttype) {
586           return_value = CURL_FORMADD_MEMORY;
587           break;
588         }
589         form->contenttype_alloc = TRUE;
590       }
591       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       }
602       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) {
607           /* copy name (without strdup; possibly not nul-terminated) */
608           form->name = Curl_memdup(form->name, form->namelength?
609                                    form->namelength:
610                                    strlen(form->name) + 1);
611         }
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)
624           clen = strlen(form->value) + 1;
625
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;
650     }
651     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       }
674     }
675   }
676
677   /* 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;
684   }
685
686   return return_value;
687 }
688
689 /*
690  * curl_formadd() is a public API to add a section to the multipart formpost.
691  *
692  * @unittest: 1308
693  */
694
695 CURLFORMcode 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
707 /*
708  * curl_formget()
709  * Serialize a curl_httppost struct.
710  * Returns 0 on success.
711  *
712  * @unittest: 1308
713  */
714 int curl_formget(struct curl_httppost *form, void *arg,
715                  curl_formget_callback append)
716 {
717   CURLcode result;
718   curl_mimepart toppart;
719
720   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);
725
726   while(!result) {
727     char buffer[8192];
728     size_t nread = Curl_mime_read(buffer, 1, sizeof buffer, &toppart);
729
730     if(!nread)
731       break;
732
733     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;
741     }
742   }
743
744   Curl_mime_cleanpart(&toppart);
745   return (int) result;
746 }
747
748 /*
749  * curl_formfree() is an external function to free up a whole form post
750  * chain
751  */
752 void 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 {
761     next = form->next;  /* the following form line */
762
763     /* recurse to sub-contents */
764     curl_formfree(form->more);
765
766     if(!(form->flags & HTTPPOST_PTRNAME))
767       free(form->name); /* free the name */
768     if(!(form->flags &
769          (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK))
770       )
771       free(form->contents); /* free the contents */
772     free(form->contenttype); /* free the content type */
773     free(form->showfilename); /* free the faked file name */
774     free(form);       /* free the struct */
775     form = next;
776   } while(form); /* continue */
777 }
778
779
780 /* Set mime part name, taking care of non nul-terminated name string. */
781 static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
782 {
783   char *zname;
784   CURLcode res;
785
786   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;
796 }
797
798 /*
799  * 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'.
802  *
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.
806  */
807
808 CURLcode Curl_getformdata(struct Curl_easy *data,
809                           curl_mimepart *finalform,
810                           struct curl_httppost *post,
811                           curl_read_callback fread_func)
812 {
813   CURLcode result = CURLE_OK;
814   curl_mime *form = NULL;
815   curl_mime *multipart;
816   curl_mimepart *part;
817   struct curl_httppost *file;
818
819   Curl_mime_cleanpart(finalform); /* default form is empty */
820
821   if(!post)
822     return result; /* no input => no output! */
823
824   form = curl_mime_init(data);
825   if(!form)
826     result = CURLE_OUT_OF_MEMORY;
827
828   if(!result)
829     result = curl_mime_subparts(finalform, form);
830
831   /* 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     }
918   }
919
920   if(result)
921     Curl_mime_cleanpart(finalform);
922
923   return result;
924 }
925
926 #else  /* CURL_DISABLE_HTTP */
927 CURLFORMcode 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
936 int 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
945 void curl_formfree(struct curl_httppost *form)
946 {
947   (void)form;
948   /* does nothing HTTP is disabled */
949 }
950
951
952 #endif  /* !defined(CURL_DISABLE_HTTP) */