build: fix circular header inclusion with other packages
[platform/upstream/curl.git] / lib / formdata.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2012, 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 http://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 /* Length of the random boundary string. */
28 #define BOUNDARY_LENGTH 40
29
30 #if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY)
31
32 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
33 #include <libgen.h>
34 #endif
35
36 #include "urldata.h" /* for struct SessionHandle */
37 #include "formdata.h"
38 #include "curl_rand.h"
39 #include "strequal.h"
40 #include "curl_memory.h"
41 #include "sendf.h"
42
43 #define _MPRINTF_REPLACE /* use our functions only */
44 #include <curl/mprintf.h>
45
46 /* The last #include file should be: */
47 #include "memdebug.h"
48
49 #endif  /* !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) */
50
51 #ifndef CURL_DISABLE_HTTP
52
53 #ifndef HAVE_BASENAME
54 static char *Curl_basename(char *path);
55 #define basename(x)  Curl_basename((x))
56 #endif
57
58 static size_t readfromfile(struct Form *form, char *buffer, size_t size);
59
60 /* What kind of Content-Type to use on un-specified files with unrecognized
61    extensions. */
62 #define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
63
64 #define FORM_FILE_SEPARATOR ','
65 #define FORM_TYPE_SEPARATOR ';'
66
67 /***************************************************************************
68  *
69  * AddHttpPost()
70  *
71  * Adds a HttpPost structure to the list, if parent_post is given becomes
72  * a subpost of parent_post instead of a direct list element.
73  *
74  * Returns newly allocated HttpPost on success and NULL if malloc failed.
75  *
76  ***************************************************************************/
77 static struct curl_httppost *
78 AddHttpPost(char *name, size_t namelength,
79             char *value, size_t contentslength,
80             char *buffer, size_t bufferlength,
81             char *contenttype,
82             long flags,
83             struct curl_slist* contentHeader,
84             char *showfilename, char *userp,
85             struct curl_httppost *parent_post,
86             struct curl_httppost **httppost,
87             struct curl_httppost **last_post)
88 {
89   struct curl_httppost *post;
90   post = calloc(1, sizeof(struct curl_httppost));
91   if(post) {
92     post->name = name;
93     post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
94     post->contents = value;
95     post->contentslength = (long)contentslength;
96     post->buffer = buffer;
97     post->bufferlength = (long)bufferlength;
98     post->contenttype = contenttype;
99     post->contentheader = contentHeader;
100     post->showfilename = showfilename;
101     post->userp = userp,
102     post->flags = flags;
103   }
104   else
105     return NULL;
106
107   if(parent_post) {
108     /* now, point our 'more' to the original 'more' */
109     post->more = parent_post->more;
110
111     /* then move the original 'more' to point to ourselves */
112     parent_post->more = post;
113   }
114   else {
115     /* make the previous point to this */
116     if(*last_post)
117       (*last_post)->next = post;
118     else
119       (*httppost) = post;
120
121     (*last_post) = post;
122   }
123   return post;
124 }
125
126 /***************************************************************************
127  *
128  * AddFormInfo()
129  *
130  * Adds a FormInfo structure to the list presented by parent_form_info.
131  *
132  * Returns newly allocated FormInfo on success and NULL if malloc failed/
133  * parent_form_info is NULL.
134  *
135  ***************************************************************************/
136 static FormInfo * AddFormInfo(char *value,
137                               char *contenttype,
138                               FormInfo *parent_form_info)
139 {
140   FormInfo *form_info;
141   form_info = calloc(1, sizeof(struct FormInfo));
142   if(form_info) {
143     if(value)
144       form_info->value = value;
145     if(contenttype)
146       form_info->contenttype = contenttype;
147     form_info->flags = HTTPPOST_FILENAME;
148   }
149   else
150     return NULL;
151
152   if(parent_form_info) {
153     /* now, point our 'more' to the original 'more' */
154     form_info->more = parent_form_info->more;
155
156     /* then move the original 'more' to point to ourselves */
157     parent_form_info->more = form_info;
158   }
159
160   return form_info;
161 }
162
163 /***************************************************************************
164  *
165  * ContentTypeForFilename()
166  *
167  * Provides content type for filename if one of the known types (else
168  * (either the prevtype or the default is returned).
169  *
170  * Returns some valid contenttype for filename.
171  *
172  ***************************************************************************/
173 static const char * ContentTypeForFilename (const char *filename,
174                                             const char *prevtype)
175 {
176   const char *contenttype = NULL;
177   unsigned int i;
178   /*
179    * No type was specified, we scan through a few well-known
180    * extensions and pick the first we match!
181    */
182   struct ContentType {
183     char extension[6];
184     const char *type;
185   };
186   static const struct ContentType ctts[]={
187     {".gif",  "image/gif"},
188     {".jpg",  "image/jpeg"},
189     {".jpeg", "image/jpeg"},
190     {".txt",  "text/plain"},
191     {".html", "text/html"},
192     {".xml", "application/xml"}
193   };
194
195   if(prevtype)
196     /* default to the previously set/used! */
197     contenttype = prevtype;
198   else
199     contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
200
201   if(filename) { /* in case a NULL was passed in */
202     for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
203       if(strlen(filename) >= strlen(ctts[i].extension)) {
204         if(strequal(filename +
205                     strlen(filename) - strlen(ctts[i].extension),
206                     ctts[i].extension)) {
207           contenttype = ctts[i].type;
208           break;
209         }
210       }
211     }
212   }
213   /* we have a contenttype by now */
214   return contenttype;
215 }
216
217 /***************************************************************************
218  *
219  * memdup()
220  *
221  * Copies the 'source' data to a newly allocated buffer buffer (that is
222  * returned). Uses buffer_length if not null, else uses strlen to determine
223  * the length of the buffer to be copied
224  *
225  * Returns the new pointer or NULL on failure.
226  *
227  ***************************************************************************/
228 static char *memdup(const char *src, size_t buffer_length)
229 {
230   size_t length;
231   bool add = FALSE;
232   char *buffer;
233
234   if(buffer_length)
235     length = buffer_length;
236   else if(src) {
237     length = strlen(src);
238     add = TRUE;
239   }
240   else
241     /* no length and a NULL src pointer! */
242     return strdup("");
243
244   buffer = malloc(length+add);
245   if(!buffer)
246     return NULL; /* fail */
247
248   memcpy(buffer, src, length);
249
250   /* if length unknown do null termination */
251   if(add)
252     buffer[length] = '\0';
253
254   return buffer;
255 }
256
257 /***************************************************************************
258  *
259  * FormAdd()
260  *
261  * Stores a formpost parameter and builds the appropriate linked list.
262  *
263  * Has two principal functionalities: using files and byte arrays as
264  * post parts. Byte arrays are either copied or just the pointer is stored
265  * (as the user requests) while for files only the filename and not the
266  * content is stored.
267  *
268  * While you may have only one byte array for each name, multiple filenames
269  * are allowed (and because of this feature CURLFORM_END is needed after
270  * using CURLFORM_FILE).
271  *
272  * Examples:
273  *
274  * Simple name/value pair with copied contents:
275  * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
276  * CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
277  *
278  * name/value pair where only the content pointer is remembered:
279  * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
280  * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END);
281  * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
282  *
283  * storing a filename (CONTENTTYPE is optional!):
284  * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
285  * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text",
286  * CURLFORM_END);
287  *
288  * storing multiple filenames:
289  * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
290  * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
291  *
292  * Returns:
293  * CURL_FORMADD_OK             on success
294  * CURL_FORMADD_MEMORY         if the FormInfo allocation fails
295  * CURL_FORMADD_OPTION_TWICE   if one option is given twice for one Form
296  * CURL_FORMADD_NULL           if a null pointer was given for a char
297  * CURL_FORMADD_MEMORY         if the allocation of a FormInfo struct failed
298  * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
299  * CURL_FORMADD_INCOMPLETE     if the some FormInfo is not complete (or error)
300  * CURL_FORMADD_MEMORY         if a HttpPost struct cannot be allocated
301  * CURL_FORMADD_MEMORY         if some allocation for string copying failed.
302  * CURL_FORMADD_ILLEGAL_ARRAY  if an illegal option is used in an array
303  *
304  ***************************************************************************/
305
306 static
307 CURLFORMcode FormAdd(struct curl_httppost **httppost,
308                      struct curl_httppost **last_post,
309                      va_list params)
310 {
311   FormInfo *first_form, *current_form, *form = NULL;
312   CURLFORMcode return_value = CURL_FORMADD_OK;
313   const char *prevtype = NULL;
314   struct curl_httppost *post = NULL;
315   CURLformoption option;
316   struct curl_forms *forms = NULL;
317   char *array_value=NULL; /* value read from an array */
318
319   /* This is a state variable, that if TRUE means that we're parsing an
320      array that we got passed to us. If FALSE we're parsing the input
321      va_list arguments. */
322   bool array_state = FALSE;
323
324   /*
325    * We need to allocate the first struct to fill in.
326    */
327   first_form = calloc(1, sizeof(struct FormInfo));
328   if(!first_form)
329     return CURL_FORMADD_MEMORY;
330
331   current_form = first_form;
332
333   /*
334    * Loop through all the options set. Break if we have an error to report.
335    */
336   while(return_value == CURL_FORMADD_OK) {
337
338     /* first see if we have more parts of the array param */
339     if(array_state && forms) {
340       /* get the upcoming option from the given array */
341       option = forms->option;
342       array_value = (char *)forms->value;
343
344       forms++; /* advance this to next entry */
345       if(CURLFORM_END == option) {
346         /* end of array state */
347         array_state = FALSE;
348         continue;
349       }
350     }
351     else {
352       /* This is not array-state, get next option */
353       option = va_arg(params, CURLformoption);
354       if(CURLFORM_END == option)
355         break;
356     }
357
358     switch (option) {
359     case CURLFORM_ARRAY:
360       if(array_state)
361         /* we don't support an array from within an array */
362         return_value = CURL_FORMADD_ILLEGAL_ARRAY;
363       else {
364         forms = va_arg(params, struct curl_forms *);
365         if(forms)
366           array_state = TRUE;
367         else
368           return_value = CURL_FORMADD_NULL;
369       }
370       break;
371
372       /*
373        * Set the Name property.
374        */
375     case CURLFORM_PTRNAME:
376 #ifdef CURL_DOES_CONVERSIONS
377       /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy
378        * the data in all cases so that we'll have safe memory for the eventual
379        * conversion.
380        */
381 #else
382       current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
383 #endif
384     case CURLFORM_COPYNAME:
385       if(current_form->name)
386         return_value = CURL_FORMADD_OPTION_TWICE;
387       else {
388         char *name = array_state?
389           array_value:va_arg(params, char *);
390         if(name)
391           current_form->name = name; /* store for the moment */
392         else
393           return_value = CURL_FORMADD_NULL;
394       }
395       break;
396     case CURLFORM_NAMELENGTH:
397       if(current_form->namelength)
398         return_value = CURL_FORMADD_OPTION_TWICE;
399       else
400         current_form->namelength =
401           array_state?(size_t)array_value:(size_t)va_arg(params, long);
402       break;
403
404       /*
405        * Set the contents property.
406        */
407     case CURLFORM_PTRCONTENTS:
408       current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
409     case CURLFORM_COPYCONTENTS:
410       if(current_form->value)
411         return_value = CURL_FORMADD_OPTION_TWICE;
412       else {
413         char *value =
414           array_state?array_value:va_arg(params, char *);
415         if(value)
416           current_form->value = value; /* store for the moment */
417         else
418           return_value = CURL_FORMADD_NULL;
419       }
420       break;
421     case CURLFORM_CONTENTSLENGTH:
422       if(current_form->contentslength)
423         return_value = CURL_FORMADD_OPTION_TWICE;
424       else
425         current_form->contentslength =
426           array_state?(size_t)array_value:(size_t)va_arg(params, long);
427       break;
428
429       /* Get contents from a given file name */
430     case CURLFORM_FILECONTENT:
431       if(current_form->flags != 0)
432         return_value = CURL_FORMADD_OPTION_TWICE;
433       else {
434         const char *filename = array_state?
435           array_value:va_arg(params, char *);
436         if(filename) {
437           current_form->value = strdup(filename);
438           if(!current_form->value)
439             return_value = CURL_FORMADD_MEMORY;
440           else {
441             current_form->flags |= HTTPPOST_READFILE;
442             current_form->value_alloc = TRUE;
443           }
444         }
445         else
446           return_value = CURL_FORMADD_NULL;
447       }
448       break;
449
450       /* We upload a file */
451     case CURLFORM_FILE:
452       {
453         const char *filename = array_state?array_value:
454           va_arg(params, char *);
455
456         if(current_form->value) {
457           if(current_form->flags & HTTPPOST_FILENAME) {
458             if(filename) {
459               char *fname = strdup(filename);
460               if(!fname)
461                 return_value = CURL_FORMADD_MEMORY;
462               else {
463                 form = AddFormInfo(fname, NULL, current_form);
464                 if(!form) {
465                   Curl_safefree(fname);
466                   return_value = CURL_FORMADD_MEMORY;
467                 }
468                 else {
469                   form->value_alloc = TRUE;
470                   current_form = form;
471                   form = NULL;
472                 }
473               }
474             }
475             else
476               return_value = CURL_FORMADD_NULL;
477           }
478           else
479             return_value = CURL_FORMADD_OPTION_TWICE;
480         }
481         else {
482           if(filename) {
483             current_form->value = strdup(filename);
484             if(!current_form->value)
485               return_value = CURL_FORMADD_MEMORY;
486             else {
487               current_form->flags |= HTTPPOST_FILENAME;
488               current_form->value_alloc = TRUE;
489             }
490           }
491           else
492             return_value = CURL_FORMADD_NULL;
493         }
494         break;
495       }
496
497     case CURLFORM_BUFFERPTR:
498       current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
499       if(current_form->buffer)
500         return_value = CURL_FORMADD_OPTION_TWICE;
501       else {
502         char *buffer =
503           array_state?array_value:va_arg(params, char *);
504         if(buffer) {
505           current_form->buffer = buffer; /* store for the moment */
506           current_form->value = buffer; /* make it non-NULL to be accepted
507                                            as fine */
508         }
509         else
510           return_value = CURL_FORMADD_NULL;
511       }
512       break;
513
514     case CURLFORM_BUFFERLENGTH:
515       if(current_form->bufferlength)
516         return_value = CURL_FORMADD_OPTION_TWICE;
517       else
518         current_form->bufferlength =
519           array_state?(size_t)array_value:(size_t)va_arg(params, long);
520       break;
521
522     case CURLFORM_STREAM:
523       current_form->flags |= HTTPPOST_CALLBACK;
524       if(current_form->userp)
525         return_value = CURL_FORMADD_OPTION_TWICE;
526       else {
527         char *userp =
528           array_state?array_value:va_arg(params, char *);
529         if(userp) {
530           current_form->userp = userp;
531           current_form->value = userp; /* this isn't strictly true but we
532                                           derive a value from this later on
533                                           and we need this non-NULL to be
534                                           accepted as a fine form part */
535         }
536         else
537           return_value = CURL_FORMADD_NULL;
538       }
539       break;
540
541     case CURLFORM_CONTENTTYPE:
542       {
543         const char *contenttype =
544           array_state?array_value:va_arg(params, char *);
545         if(current_form->contenttype) {
546           if(current_form->flags & HTTPPOST_FILENAME) {
547             if(contenttype) {
548               char *type = strdup(contenttype);
549               if(!type)
550                 return_value = CURL_FORMADD_MEMORY;
551               else {
552                 form = AddFormInfo(NULL, type, current_form);
553                 if(!form) {
554                   Curl_safefree(type);
555                   return_value = CURL_FORMADD_MEMORY;
556                 }
557                 else {
558                   form->contenttype_alloc = TRUE;
559                   current_form = form;
560                   form = NULL;
561                 }
562               }
563             }
564             else
565               return_value = CURL_FORMADD_NULL;
566           }
567           else
568             return_value = CURL_FORMADD_OPTION_TWICE;
569         }
570         else {
571           if(contenttype) {
572             current_form->contenttype = strdup(contenttype);
573             if(!current_form->contenttype)
574               return_value = CURL_FORMADD_MEMORY;
575             else
576               current_form->contenttype_alloc = TRUE;
577           }
578           else
579             return_value = CURL_FORMADD_NULL;
580         }
581         break;
582       }
583     case CURLFORM_CONTENTHEADER:
584       {
585         /* this "cast increases required alignment of target type" but
586            we consider it OK anyway */
587         struct curl_slist* list = array_state?
588           (struct curl_slist*)array_value:
589           va_arg(params, struct curl_slist*);
590
591         if(current_form->contentheader)
592           return_value = CURL_FORMADD_OPTION_TWICE;
593         else
594           current_form->contentheader = list;
595
596         break;
597       }
598     case CURLFORM_FILENAME:
599     case CURLFORM_BUFFER:
600       {
601         const char *filename = array_state?array_value:
602           va_arg(params, char *);
603         if(current_form->showfilename)
604           return_value = CURL_FORMADD_OPTION_TWICE;
605         else {
606           current_form->showfilename = strdup(filename);
607           if(!current_form->showfilename)
608             return_value = CURL_FORMADD_MEMORY;
609           else
610             current_form->showfilename_alloc = TRUE;
611         }
612         break;
613       }
614     default:
615       return_value = CURL_FORMADD_UNKNOWN_OPTION;
616       break;
617     }
618   }
619
620   if(CURL_FORMADD_OK != return_value) {
621     /* On error, free allocated fields for all nodes of the FormInfo linked
622        list without deallocating nodes. List nodes are deallocated later on */
623     FormInfo *ptr;
624     for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
625       if(ptr->name_alloc) {
626         Curl_safefree(ptr->name);
627         ptr->name_alloc = FALSE;
628       }
629       if(ptr->value_alloc) {
630         Curl_safefree(ptr->value);
631         ptr->value_alloc = FALSE;
632       }
633       if(ptr->contenttype_alloc) {
634         Curl_safefree(ptr->contenttype);
635         ptr->contenttype_alloc = FALSE;
636       }
637       if(ptr->showfilename_alloc) {
638         Curl_safefree(ptr->showfilename);
639         ptr->showfilename_alloc = FALSE;
640       }
641     }
642   }
643
644   if(CURL_FORMADD_OK == return_value) {
645     /* go through the list, check for completeness and if everything is
646      * alright add the HttpPost item otherwise set return_value accordingly */
647
648     post = NULL;
649     for(form = first_form;
650         form != NULL;
651         form = form->more) {
652       if(((!form->name || !form->value) && !post) ||
653          ( (form->contentslength) &&
654            (form->flags & HTTPPOST_FILENAME) ) ||
655          ( (form->flags & HTTPPOST_FILENAME) &&
656            (form->flags & HTTPPOST_PTRCONTENTS) ) ||
657
658          ( (!form->buffer) &&
659            (form->flags & HTTPPOST_BUFFER) &&
660            (form->flags & HTTPPOST_PTRBUFFER) ) ||
661
662          ( (form->flags & HTTPPOST_READFILE) &&
663            (form->flags & HTTPPOST_PTRCONTENTS) )
664         ) {
665         return_value = CURL_FORMADD_INCOMPLETE;
666         break;
667       }
668       else {
669         if(((form->flags & HTTPPOST_FILENAME) ||
670             (form->flags & HTTPPOST_BUFFER)) &&
671            !form->contenttype ) {
672           /* our contenttype is missing */
673           form->contenttype
674             = strdup(ContentTypeForFilename(form->value, prevtype));
675           if(!form->contenttype) {
676             return_value = CURL_FORMADD_MEMORY;
677             break;
678           }
679           form->contenttype_alloc = TRUE;
680         }
681         if(!(form->flags & HTTPPOST_PTRNAME) &&
682            (form == first_form) ) {
683           /* Note that there's small risk that form->name is NULL here if the
684              app passed in a bad combo, so we better check for that first. */
685           if(form->name)
686             /* copy name (without strdup; possibly contains null characters) */
687             form->name = memdup(form->name, form->namelength);
688           if(!form->name) {
689             return_value = CURL_FORMADD_MEMORY;
690             break;
691           }
692           form->name_alloc = TRUE;
693         }
694         if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
695                             HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
696                             HTTPPOST_CALLBACK)) ) {
697           /* copy value (without strdup; possibly contains null characters) */
698           form->value = memdup(form->value, form->contentslength);
699           if(!form->value) {
700             return_value = CURL_FORMADD_MEMORY;
701             break;
702           }
703           form->value_alloc = TRUE;
704         }
705         post = AddHttpPost(form->name, form->namelength,
706                            form->value, form->contentslength,
707                            form->buffer, form->bufferlength,
708                            form->contenttype, form->flags,
709                            form->contentheader, form->showfilename,
710                            form->userp,
711                            post, httppost,
712                            last_post);
713
714         if(!post) {
715           return_value = CURL_FORMADD_MEMORY;
716           break;
717         }
718
719         if(form->contenttype)
720           prevtype = form->contenttype;
721       }
722     }
723     if(CURL_FORMADD_OK != return_value) {
724       /* On error, free allocated fields for nodes of the FormInfo linked
725          list which are not already owned by the httppost linked list
726          without deallocating nodes. List nodes are deallocated later on */
727       FormInfo *ptr;
728       for(ptr = form; ptr != NULL; ptr = ptr->more) {
729         if(ptr->name_alloc) {
730           Curl_safefree(ptr->name);
731           ptr->name_alloc = FALSE;
732         }
733         if(ptr->value_alloc) {
734           Curl_safefree(ptr->value);
735           ptr->value_alloc = FALSE;
736         }
737         if(ptr->contenttype_alloc) {
738           Curl_safefree(ptr->contenttype);
739           ptr->contenttype_alloc = FALSE;
740         }
741         if(ptr->showfilename_alloc) {
742           Curl_safefree(ptr->showfilename);
743           ptr->showfilename_alloc = FALSE;
744         }
745       }
746     }
747   }
748
749   /* Always deallocate FormInfo linked list nodes without touching node
750      fields given that these have either been deallocated or are owned
751      now by the httppost linked list */
752   while(first_form) {
753     FormInfo *ptr = first_form->more;
754     Curl_safefree(first_form);
755     first_form = ptr;
756   }
757
758   return return_value;
759 }
760
761 /*
762  * curl_formadd() is a public API to add a section to the multipart formpost.
763  *
764  * @unittest: 1308
765  */
766
767 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
768                           struct curl_httppost **last_post,
769                           ...)
770 {
771   va_list arg;
772   CURLFORMcode result;
773   va_start(arg, last_post);
774   result = FormAdd(httppost, last_post, arg);
775   va_end(arg);
776   return result;
777 }
778
779 /*
780  * AddFormData() adds a chunk of data to the FormData linked list.
781  *
782  * size is incremented by the chunk length, unless it is NULL
783  */
784 static CURLcode AddFormData(struct FormData **formp,
785                             enum formtype type,
786                             const void *line,
787                             size_t length,
788                             curl_off_t *size)
789 {
790   struct FormData *newform = malloc(sizeof(struct FormData));
791   if(!newform)
792     return CURLE_OUT_OF_MEMORY;
793   newform->next = NULL;
794
795   if(type <= FORM_CONTENT) {
796     /* we make it easier for plain strings: */
797     if(!length)
798       length = strlen((char *)line);
799
800     newform->line = malloc(length+1);
801     if(!newform->line) {
802       free(newform);
803       return CURLE_OUT_OF_MEMORY;
804     }
805     memcpy(newform->line, line, length);
806     newform->length = length;
807     newform->line[length]=0; /* zero terminate for easier debugging */
808   }
809   else
810     /* For callbacks and files we don't have any actual data so we just keep a
811        pointer to whatever this points to */
812     newform->line = (char *)line;
813
814   newform->type = type;
815
816   if(*formp) {
817     (*formp)->next = newform;
818     *formp = newform;
819   }
820   else
821     *formp = newform;
822
823   if(size) {
824     if(type != FORM_FILE)
825       /* for static content as well as callback data we add the size given
826          as input argument */
827       *size += length;
828     else {
829       /* Since this is a file to be uploaded here, add the size of the actual
830          file */
831       if(!strequal("-", newform->line)) {
832         struct_stat file;
833         if(!stat(newform->line, &file)) {
834           *size += file.st_size;
835         }
836       }
837     }
838   }
839   return CURLE_OK;
840 }
841
842 /*
843  * AddFormDataf() adds printf()-style formatted data to the formdata chain.
844  */
845
846 static CURLcode AddFormDataf(struct FormData **formp,
847                              curl_off_t *size,
848                              const char *fmt, ...)
849 {
850   char s[4096];
851   va_list ap;
852   va_start(ap, fmt);
853   vsnprintf(s, sizeof(s), fmt, ap);
854   va_end(ap);
855
856   return AddFormData(formp, FORM_DATA, s, 0, size);
857 }
858
859 /*
860  * Curl_formclean() is used from http.c, this cleans a built FormData linked
861  * list
862  */
863 void Curl_formclean(struct FormData **form_ptr)
864 {
865   struct FormData *next, *form;
866
867   form = *form_ptr;
868   if(!form)
869     return;
870
871   do {
872     next=form->next;  /* the following form line */
873     if(form->type <= FORM_CONTENT)
874       free(form->line); /* free the line */
875     free(form);       /* free the struct */
876
877   } while((form = next) != NULL); /* continue */
878
879   *form_ptr = NULL;
880 }
881
882 /*
883  * curl_formget()
884  * Serialize a curl_httppost struct.
885  * Returns 0 on success.
886  *
887  * @unittest: 1308
888  */
889 int curl_formget(struct curl_httppost *form, void *arg,
890                  curl_formget_callback append)
891 {
892   CURLcode rc;
893   curl_off_t size;
894   struct FormData *data, *ptr;
895
896   rc = Curl_getformdata(NULL, &data, form, NULL, &size);
897   if(rc != CURLE_OK)
898     return (int)rc;
899
900   for(ptr = data; ptr; ptr = ptr->next) {
901     if((ptr->type == FORM_FILE) || (ptr->type == FORM_CALLBACK)) {
902       char buffer[8192];
903       size_t nread;
904       struct Form temp;
905
906       Curl_FormInit(&temp, ptr);
907
908       do {
909         nread = readfromfile(&temp, buffer, sizeof(buffer));
910         if((nread == (size_t) -1) ||
911            (nread > sizeof(buffer)) ||
912            (nread != append(arg, buffer, nread))) {
913           if(temp.fp)
914             fclose(temp.fp);
915           Curl_formclean(&data);
916           return -1;
917         }
918       } while(nread);
919     }
920     else {
921       if(ptr->length != append(arg, ptr->line, ptr->length)) {
922         Curl_formclean(&data);
923         return -1;
924       }
925     }
926   }
927   Curl_formclean(&data);
928   return 0;
929 }
930
931 /*
932  * curl_formfree() is an external function to free up a whole form post
933  * chain
934  */
935 void curl_formfree(struct curl_httppost *form)
936 {
937   struct curl_httppost *next;
938
939   if(!form)
940     /* no form to free, just get out of this */
941     return;
942
943   do {
944     next=form->next;  /* the following form line */
945
946     /* recurse to sub-contents */
947     if(form->more)
948       curl_formfree(form->more);
949
950     if(!(form->flags & HTTPPOST_PTRNAME) && form->name)
951       free(form->name); /* free the name */
952     if(!(form->flags &
953          (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) &&
954        form->contents)
955       free(form->contents); /* free the contents */
956     if(form->contenttype)
957       free(form->contenttype); /* free the content type */
958     if(form->showfilename)
959       free(form->showfilename); /* free the faked file name */
960     free(form);       /* free the struct */
961
962   } while((form = next) != NULL); /* continue */
963 }
964
965 #ifndef HAVE_BASENAME
966 /*
967   (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
968   Edition)
969
970   The basename() function shall take the pathname pointed to by path and
971   return a pointer to the final component of the pathname, deleting any
972   trailing '/' characters.
973
974   If the string pointed to by path consists entirely of the '/' character,
975   basename() shall return a pointer to the string "/". If the string pointed
976   to by path is exactly "//", it is implementation-defined whether '/' or "//"
977   is returned.
978
979   If path is a null pointer or points to an empty string, basename() shall
980   return a pointer to the string ".".
981
982   The basename() function may modify the string pointed to by path, and may
983   return a pointer to static storage that may then be overwritten by a
984   subsequent call to basename().
985
986   The basename() function need not be reentrant. A function that is not
987   required to be reentrant is not required to be thread-safe.
988
989 */
990 static char *Curl_basename(char *path)
991 {
992   /* Ignore all the details above for now and make a quick and simple
993      implementaion here */
994   char *s1;
995   char *s2;
996
997   s1=strrchr(path, '/');
998   s2=strrchr(path, '\\');
999
1000   if(s1 && s2) {
1001     path = (s1 > s2? s1 : s2)+1;
1002   }
1003   else if(s1)
1004     path = s1 + 1;
1005   else if(s2)
1006     path = s2 + 1;
1007
1008   return path;
1009 }
1010 #endif
1011
1012 static char *strippath(const char *fullfile)
1013 {
1014   char *filename;
1015   char *base;
1016   filename = strdup(fullfile); /* duplicate since basename() may ruin the
1017                                   buffer it works on */
1018   if(!filename)
1019     return NULL;
1020   base = strdup(basename(filename));
1021
1022   free(filename); /* free temporary buffer */
1023
1024   return base; /* returns an allocated string or NULL ! */
1025 }
1026
1027 /*
1028  * Curl_getformdata() converts a linked list of "meta data" into a complete
1029  * (possibly huge) multipart formdata. The input list is in 'post', while the
1030  * output resulting linked lists gets stored in '*finalform'. *sizep will get
1031  * the total size of the whole POST.
1032  * A multipart/form_data content-type is built, unless a custom content-type
1033  * is passed in 'custom_content_type'.
1034  *
1035  * This function will not do a failf() for the potential memory failures but
1036  * should for all other errors it spots. Just note that this function MAY get
1037  * a NULL pointer in the 'data' argument.
1038  */
1039
1040 CURLcode Curl_getformdata(struct SessionHandle *data,
1041                           struct FormData **finalform,
1042                           struct curl_httppost *post,
1043                           const char *custom_content_type,
1044                           curl_off_t *sizep)
1045 {
1046   struct FormData *form = NULL;
1047   struct FormData *firstform;
1048   struct curl_httppost *file;
1049   CURLcode result = CURLE_OK;
1050
1051   curl_off_t size = 0; /* support potentially ENORMOUS formposts */
1052   char *boundary;
1053   char *fileboundary = NULL;
1054   struct curl_slist* curList;
1055
1056   *finalform = NULL; /* default form is empty */
1057
1058   if(!post)
1059     return result; /* no input => no output! */
1060
1061   boundary = Curl_FormBoundary();
1062   if(!boundary)
1063     return CURLE_OUT_OF_MEMORY;
1064
1065   /* Make the first line of the output */
1066   result = AddFormDataf(&form, NULL,
1067                         "%s; boundary=%s\r\n",
1068                         custom_content_type?custom_content_type:
1069                         "Content-Type: multipart/form-data",
1070                         boundary);
1071
1072   if(result) {
1073     Curl_safefree(boundary);
1074     return result;
1075   }
1076   /* we DO NOT include that line in the total size of the POST, since it'll be
1077      part of the header! */
1078
1079   firstform = form;
1080
1081   do {
1082
1083     if(size) {
1084       result = AddFormDataf(&form, &size, "\r\n");
1085       if(result)
1086         break;
1087     }
1088
1089     /* boundary */
1090     result = AddFormDataf(&form, &size, "--%s\r\n", boundary);
1091     if(result)
1092       break;
1093
1094     /* Maybe later this should be disabled when a custom_content_type is
1095        passed, since Content-Disposition is not meaningful for all multipart
1096        types.
1097     */
1098     result = AddFormDataf(&form, &size,
1099                           "Content-Disposition: form-data; name=\"");
1100     if(result)
1101       break;
1102
1103     result = AddFormData(&form, FORM_DATA, post->name, post->namelength,
1104                          &size);
1105     if(result)
1106       break;
1107
1108     result = AddFormDataf(&form, &size, "\"");
1109     if(result)
1110       break;
1111
1112     if(post->more) {
1113       /* If used, this is a link to more file names, we must then do
1114          the magic to include several files with the same field name */
1115
1116       Curl_safefree(fileboundary);
1117       fileboundary = Curl_FormBoundary();
1118       if(!fileboundary) {
1119         result = CURLE_OUT_OF_MEMORY;
1120         break;
1121       }
1122
1123       result = AddFormDataf(&form, &size,
1124                             "\r\nContent-Type: multipart/mixed,"
1125                             " boundary=%s\r\n",
1126                             fileboundary);
1127       if(result)
1128         break;
1129     }
1130
1131     file = post;
1132
1133     do {
1134
1135       /* If 'showfilename' is set, that is a faked name passed on to us
1136          to use to in the formpost. If that is not set, the actually used
1137          local file name should be added. */
1138
1139       if(post->more) {
1140         /* if multiple-file */
1141         char *filebasename = NULL;
1142         if(!file->showfilename) {
1143           filebasename = strippath(file->contents);
1144           if(!filebasename) {
1145             result = CURLE_OUT_OF_MEMORY;
1146             break;
1147           }
1148         }
1149
1150         result = AddFormDataf(&form, &size,
1151                               "\r\n--%s\r\nContent-Disposition: "
1152                               "attachment; filename=\"%s\"",
1153                               fileboundary,
1154                               (file->showfilename?file->showfilename:
1155                                filebasename));
1156         Curl_safefree(filebasename);
1157         if(result)
1158           break;
1159       }
1160       else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER|
1161                              HTTPPOST_CALLBACK)) {
1162         /* it should be noted that for the HTTPPOST_FILENAME and
1163            HTTPPOST_CALLBACK cases the ->showfilename struct member is always
1164            assigned at this point */
1165         if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) {
1166           char *filebasename=
1167             (!post->showfilename)?strippath(post->contents):NULL;
1168
1169           result = AddFormDataf(&form, &size,
1170                                 "; filename=\"%s\"",
1171                                 (post->showfilename?post->showfilename:
1172                                  filebasename));
1173           Curl_safefree(filebasename);
1174         }
1175
1176         if(result)
1177           break;
1178       }
1179
1180       if(file->contenttype) {
1181         /* we have a specified type */
1182         result = AddFormDataf(&form, &size,
1183                               "\r\nContent-Type: %s",
1184                               file->contenttype);
1185         if(result)
1186           break;
1187       }
1188
1189       curList = file->contentheader;
1190       while(curList) {
1191         /* Process the additional headers specified for this form */
1192         result = AddFormDataf( &form, &size, "\r\n%s", curList->data );
1193         if(result)
1194           break;
1195         curList = curList->next;
1196       }
1197       if(result)
1198         break;
1199
1200       result = AddFormDataf(&form, &size, "\r\n\r\n");
1201       if(result)
1202         break;
1203
1204       if((post->flags & HTTPPOST_FILENAME) ||
1205          (post->flags & HTTPPOST_READFILE)) {
1206         /* we should include the contents from the specified file */
1207         FILE *fileread;
1208
1209         fileread = strequal("-", file->contents)?
1210           stdin:fopen(file->contents, "rb"); /* binary read for win32  */
1211
1212         /*
1213          * VMS: This only allows for stream files on VMS.  Stream files are
1214          * OK, as are FIXED & VAR files WITHOUT implied CC For implied CC,
1215          * every record needs to have a \n appended & 1 added to SIZE
1216          */
1217
1218         if(fileread) {
1219           if(fileread != stdin) {
1220             /* close the file */
1221             fclose(fileread);
1222             /* add the file name only - for later reading from this */
1223             result = AddFormData(&form, FORM_FILE, file->contents, 0, &size);
1224           }
1225           else {
1226             /* When uploading from stdin, we can't know the size of the file,
1227              * thus must read the full file as before. We *could* use chunked
1228              * transfer-encoding, but that only works for HTTP 1.1 and we
1229              * can't be sure we work with such a server.
1230              */
1231             size_t nread;
1232             char buffer[512];
1233             while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
1234               result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
1235               if(result)
1236                 break;
1237             }
1238           }
1239         }
1240         else {
1241           if(data)
1242             failf(data, "couldn't open file \"%s\"", file->contents);
1243           *finalform = NULL;
1244           result = CURLE_READ_ERROR;
1245         }
1246       }
1247       else if(post->flags & HTTPPOST_BUFFER)
1248         /* include contents of buffer */
1249         result = AddFormData(&form, FORM_CONTENT, post->buffer,
1250                              post->bufferlength, &size);
1251       else if(post->flags & HTTPPOST_CALLBACK)
1252         /* the contents should be read with the callback and the size
1253            is set with the contentslength */
1254         result = AddFormData(&form, FORM_CALLBACK, post->userp,
1255                              post->contentslength, &size);
1256       else
1257         /* include the contents we got */
1258         result = AddFormData(&form, FORM_CONTENT, post->contents,
1259                              post->contentslength, &size);
1260
1261       file = file->more;
1262     } while(file && !result); /* for each specified file for this field */
1263
1264     if(result)
1265       break;
1266
1267     if(post->more) {
1268       /* this was a multiple-file inclusion, make a termination file
1269          boundary: */
1270       result = AddFormDataf(&form, &size,
1271                            "\r\n--%s--",
1272                            fileboundary);
1273       if(result)
1274         break;
1275     }
1276
1277   } while((post = post->next) != NULL); /* for each field */
1278
1279   /* end-boundary for everything */
1280   if(CURLE_OK == result)
1281     result = AddFormDataf(&form, &size,
1282                           "\r\n--%s--\r\n",
1283                           boundary);
1284
1285   if(result) {
1286     Curl_formclean(&firstform);
1287     Curl_safefree(fileboundary);
1288     Curl_safefree(boundary);
1289     return result;
1290   }
1291
1292   *sizep = size;
1293
1294   Curl_safefree(fileboundary);
1295   Curl_safefree(boundary);
1296
1297   *finalform = firstform;
1298
1299   return result;
1300 }
1301
1302 /*
1303  * Curl_FormInit() inits the struct 'form' points to with the 'formdata'
1304  * and resets the 'sent' counter.
1305  */
1306 int Curl_FormInit(struct Form *form, struct FormData *formdata )
1307 {
1308   if(!formdata)
1309     return 1; /* error */
1310
1311   form->data = formdata;
1312   form->sent = 0;
1313   form->fp = NULL;
1314   form->fread_func = ZERO_NULL;
1315
1316   return 0;
1317 }
1318
1319 /*
1320  * readfromfile()
1321  *
1322  * The read callback that this function may use can return a value larger than
1323  * 'size' (which then this function returns) that indicates a problem and it
1324  * must be properly dealt with
1325  */
1326 static size_t readfromfile(struct Form *form, char *buffer,
1327                            size_t size)
1328 {
1329   size_t nread;
1330   bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE;
1331
1332   if(callback) {
1333     if(form->fread_func == ZERO_NULL)
1334       return 0;
1335     else
1336       nread = form->fread_func(buffer, 1, size, form->data->line);
1337   }
1338   else {
1339     if(!form->fp) {
1340       /* this file hasn't yet been opened */
1341       form->fp = fopen(form->data->line, "rb"); /* b is for binary */
1342       if(!form->fp)
1343         return (size_t)-1; /* failure */
1344     }
1345     nread = fread(buffer, 1, size, form->fp);
1346   }
1347   if(!nread) {
1348     /* this is the last chunk from the file, move on */
1349     if(form->fp) {
1350       fclose(form->fp);
1351       form->fp = NULL;
1352     }
1353     form->data = form->data->next;
1354   }
1355
1356   return nread;
1357 }
1358
1359 /*
1360  * Curl_FormReader() is the fread() emulation function that will be used to
1361  * deliver the formdata to the transfer loop and then sent away to the peer.
1362  */
1363 size_t Curl_FormReader(char *buffer,
1364                        size_t size,
1365                        size_t nitems,
1366                        FILE *mydata)
1367 {
1368   struct Form *form;
1369   size_t wantedsize;
1370   size_t gotsize = 0;
1371
1372   form=(struct Form *)mydata;
1373
1374   wantedsize = size * nitems;
1375
1376   if(!form->data)
1377     return 0; /* nothing, error, empty */
1378
1379   if((form->data->type == FORM_FILE) ||
1380      (form->data->type == FORM_CALLBACK)) {
1381     gotsize = readfromfile(form, buffer, wantedsize);
1382
1383     if(gotsize)
1384       /* If positive or -1, return. If zero, continue! */
1385       return gotsize;
1386   }
1387   do {
1388
1389     if((form->data->length - form->sent ) > wantedsize - gotsize) {
1390
1391       memcpy(buffer + gotsize , form->data->line + form->sent,
1392              wantedsize - gotsize);
1393
1394       form->sent += wantedsize-gotsize;
1395
1396       return wantedsize;
1397     }
1398
1399     memcpy(buffer+gotsize,
1400            form->data->line + form->sent,
1401            (form->data->length - form->sent) );
1402     gotsize += form->data->length - form->sent;
1403
1404     form->sent = 0;
1405
1406     form->data = form->data->next; /* advance */
1407
1408   } while(form->data && (form->data->type < FORM_CALLBACK));
1409   /* If we got an empty line and we have more data, we proceed to the next
1410      line immediately to avoid returning zero before we've reached the end. */
1411
1412   return gotsize;
1413 }
1414
1415 /*
1416  * Curl_formpostheader() returns the first line of the formpost, the
1417  * request-header part (which is not part of the request-body like the rest of
1418  * the post).
1419  */
1420 char *Curl_formpostheader(void *formp, size_t *len)
1421 {
1422   char *header;
1423   struct Form *form=(struct Form *)formp;
1424
1425   if(!form->data)
1426     return 0; /* nothing, ERROR! */
1427
1428   header = form->data->line;
1429   *len = form->data->length;
1430
1431   form->data = form->data->next; /* advance */
1432
1433   return header;
1434 }
1435
1436 #else  /* CURL_DISABLE_HTTP */
1437 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
1438                           struct curl_httppost **last_post,
1439                           ...)
1440 {
1441   (void)httppost;
1442   (void)last_post;
1443   return CURL_FORMADD_DISABLED;
1444 }
1445
1446 int curl_formget(struct curl_httppost *form, void *arg,
1447                  curl_formget_callback append)
1448 {
1449   (void) form;
1450   (void) arg;
1451   (void) append;
1452   return CURL_FORMADD_DISABLED;
1453 }
1454
1455 void curl_formfree(struct curl_httppost *form)
1456 {
1457   (void)form;
1458   /* does nothing HTTP is disabled */
1459 }
1460
1461 #endif  /* CURL_DISABLE_HTTP */
1462
1463 #if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY)
1464
1465 /*
1466  * Curl_FormBoundary() creates a suitable boundary string and returns an
1467  * allocated one. This is also used by SSL-code so it must be present even
1468  * if HTTP is disabled!
1469  */
1470 char *Curl_FormBoundary(void)
1471 {
1472   char *retstring;
1473   size_t i;
1474
1475   static const char table16[]="0123456789abcdef";
1476
1477   retstring = malloc(BOUNDARY_LENGTH+1);
1478
1479   if(!retstring)
1480     return NULL; /* failed */
1481
1482   strcpy(retstring, "----------------------------");
1483
1484   for(i=strlen(retstring); i<BOUNDARY_LENGTH; i++)
1485     retstring[i] = table16[Curl_rand()%16];
1486
1487   /* 28 dashes and 12 hexadecimal digits makes 12^16 (184884258895036416)
1488      combinations */
1489   retstring[BOUNDARY_LENGTH]=0; /* zero terminate */
1490
1491   return retstring;
1492 }
1493
1494 #endif  /* !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) */