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