formadd: reject trying to read a directory where a file is expected
[platform/upstream/curl.git] / lib / formdata.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2013, 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) && S_ISREG(file.st_mode))
834           *size += file.st_size;
835         else
836           return CURLE_BAD_FUNCTION_ARGUMENT;
837       }
838     }
839   }
840   return CURLE_OK;
841 }
842
843 /*
844  * AddFormDataf() adds printf()-style formatted data to the formdata chain.
845  */
846
847 static CURLcode AddFormDataf(struct FormData **formp,
848                              curl_off_t *size,
849                              const char *fmt, ...)
850 {
851   char s[4096];
852   va_list ap;
853   va_start(ap, fmt);
854   vsnprintf(s, sizeof(s), fmt, ap);
855   va_end(ap);
856
857   return AddFormData(formp, FORM_DATA, s, 0, size);
858 }
859
860 /*
861  * Curl_formclean() is used from http.c, this cleans a built FormData linked
862  * list
863  */
864 void Curl_formclean(struct FormData **form_ptr)
865 {
866   struct FormData *next, *form;
867
868   form = *form_ptr;
869   if(!form)
870     return;
871
872   do {
873     next=form->next;  /* the following form line */
874     if(form->type <= FORM_CONTENT)
875       free(form->line); /* free the line */
876     free(form);       /* free the struct */
877
878   } while((form = next) != NULL); /* continue */
879
880   *form_ptr = NULL;
881 }
882
883 /*
884  * curl_formget()
885  * Serialize a curl_httppost struct.
886  * Returns 0 on success.
887  *
888  * @unittest: 1308
889  */
890 int curl_formget(struct curl_httppost *form, void *arg,
891                  curl_formget_callback append)
892 {
893   CURLcode rc;
894   curl_off_t size;
895   struct FormData *data, *ptr;
896
897   rc = Curl_getformdata(NULL, &data, form, NULL, &size);
898   if(rc != CURLE_OK)
899     return (int)rc;
900
901   for(ptr = data; ptr; ptr = ptr->next) {
902     if((ptr->type == FORM_FILE) || (ptr->type == FORM_CALLBACK)) {
903       char buffer[8192];
904       size_t nread;
905       struct Form temp;
906
907       Curl_FormInit(&temp, ptr);
908
909       do {
910         nread = readfromfile(&temp, buffer, sizeof(buffer));
911         if((nread == (size_t) -1) ||
912            (nread > sizeof(buffer)) ||
913            (nread != append(arg, buffer, nread))) {
914           if(temp.fp)
915             fclose(temp.fp);
916           Curl_formclean(&data);
917           return -1;
918         }
919       } while(nread);
920     }
921     else {
922       if(ptr->length != append(arg, ptr->line, ptr->length)) {
923         Curl_formclean(&data);
924         return -1;
925       }
926     }
927   }
928   Curl_formclean(&data);
929   return 0;
930 }
931
932 /*
933  * curl_formfree() is an external function to free up a whole form post
934  * chain
935  */
936 void curl_formfree(struct curl_httppost *form)
937 {
938   struct curl_httppost *next;
939
940   if(!form)
941     /* no form to free, just get out of this */
942     return;
943
944   do {
945     next=form->next;  /* the following form line */
946
947     /* recurse to sub-contents */
948     if(form->more)
949       curl_formfree(form->more);
950
951     if(!(form->flags & HTTPPOST_PTRNAME) && form->name)
952       free(form->name); /* free the name */
953     if(!(form->flags &
954          (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) &&
955        form->contents)
956       free(form->contents); /* free the contents */
957     if(form->contenttype)
958       free(form->contenttype); /* free the content type */
959     if(form->showfilename)
960       free(form->showfilename); /* free the faked file name */
961     free(form);       /* free the struct */
962
963   } while((form = next) != NULL); /* continue */
964 }
965
966 #ifndef HAVE_BASENAME
967 /*
968   (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
969   Edition)
970
971   The basename() function shall take the pathname pointed to by path and
972   return a pointer to the final component of the pathname, deleting any
973   trailing '/' characters.
974
975   If the string pointed to by path consists entirely of the '/' character,
976   basename() shall return a pointer to the string "/". If the string pointed
977   to by path is exactly "//", it is implementation-defined whether '/' or "//"
978   is returned.
979
980   If path is a null pointer or points to an empty string, basename() shall
981   return a pointer to the string ".".
982
983   The basename() function may modify the string pointed to by path, and may
984   return a pointer to static storage that may then be overwritten by a
985   subsequent call to basename().
986
987   The basename() function need not be reentrant. A function that is not
988   required to be reentrant is not required to be thread-safe.
989
990 */
991 static char *Curl_basename(char *path)
992 {
993   /* Ignore all the details above for now and make a quick and simple
994      implementaion here */
995   char *s1;
996   char *s2;
997
998   s1=strrchr(path, '/');
999   s2=strrchr(path, '\\');
1000
1001   if(s1 && s2) {
1002     path = (s1 > s2? s1 : s2)+1;
1003   }
1004   else if(s1)
1005     path = s1 + 1;
1006   else if(s2)
1007     path = s2 + 1;
1008
1009   return path;
1010 }
1011 #endif
1012
1013 static char *strippath(const char *fullfile)
1014 {
1015   char *filename;
1016   char *base;
1017   filename = strdup(fullfile); /* duplicate since basename() may ruin the
1018                                   buffer it works on */
1019   if(!filename)
1020     return NULL;
1021   base = strdup(basename(filename));
1022
1023   free(filename); /* free temporary buffer */
1024
1025   return base; /* returns an allocated string or NULL ! */
1026 }
1027
1028 /*
1029  * Curl_getformdata() converts a linked list of "meta data" into a complete
1030  * (possibly huge) multipart formdata. The input list is in 'post', while the
1031  * output resulting linked lists gets stored in '*finalform'. *sizep will get
1032  * the total size of the whole POST.
1033  * A multipart/form_data content-type is built, unless a custom content-type
1034  * is passed in 'custom_content_type'.
1035  *
1036  * This function will not do a failf() for the potential memory failures but
1037  * should for all other errors it spots. Just note that this function MAY get
1038  * a NULL pointer in the 'data' argument.
1039  */
1040
1041 CURLcode Curl_getformdata(struct SessionHandle *data,
1042                           struct FormData **finalform,
1043                           struct curl_httppost *post,
1044                           const char *custom_content_type,
1045                           curl_off_t *sizep)
1046 {
1047   struct FormData *form = NULL;
1048   struct FormData *firstform;
1049   struct curl_httppost *file;
1050   CURLcode result = CURLE_OK;
1051
1052   curl_off_t size = 0; /* support potentially ENORMOUS formposts */
1053   char *boundary;
1054   char *fileboundary = NULL;
1055   struct curl_slist* curList;
1056
1057   *finalform = NULL; /* default form is empty */
1058
1059   if(!post)
1060     return result; /* no input => no output! */
1061
1062   boundary = Curl_FormBoundary();
1063   if(!boundary)
1064     return CURLE_OUT_OF_MEMORY;
1065
1066   /* Make the first line of the output */
1067   result = AddFormDataf(&form, NULL,
1068                         "%s; boundary=%s\r\n",
1069                         custom_content_type?custom_content_type:
1070                         "Content-Type: multipart/form-data",
1071                         boundary);
1072
1073   if(result) {
1074     Curl_safefree(boundary);
1075     return result;
1076   }
1077   /* we DO NOT include that line in the total size of the POST, since it'll be
1078      part of the header! */
1079
1080   firstform = form;
1081
1082   do {
1083
1084     if(size) {
1085       result = AddFormDataf(&form, &size, "\r\n");
1086       if(result)
1087         break;
1088     }
1089
1090     /* boundary */
1091     result = AddFormDataf(&form, &size, "--%s\r\n", boundary);
1092     if(result)
1093       break;
1094
1095     /* Maybe later this should be disabled when a custom_content_type is
1096        passed, since Content-Disposition is not meaningful for all multipart
1097        types.
1098     */
1099     result = AddFormDataf(&form, &size,
1100                           "Content-Disposition: form-data; name=\"");
1101     if(result)
1102       break;
1103
1104     result = AddFormData(&form, FORM_DATA, post->name, post->namelength,
1105                          &size);
1106     if(result)
1107       break;
1108
1109     result = AddFormDataf(&form, &size, "\"");
1110     if(result)
1111       break;
1112
1113     if(post->more) {
1114       /* If used, this is a link to more file names, we must then do
1115          the magic to include several files with the same field name */
1116
1117       Curl_safefree(fileboundary);
1118       fileboundary = Curl_FormBoundary();
1119       if(!fileboundary) {
1120         result = CURLE_OUT_OF_MEMORY;
1121         break;
1122       }
1123
1124       result = AddFormDataf(&form, &size,
1125                             "\r\nContent-Type: multipart/mixed,"
1126                             " boundary=%s\r\n",
1127                             fileboundary);
1128       if(result)
1129         break;
1130     }
1131
1132     file = post;
1133
1134     do {
1135
1136       /* If 'showfilename' is set, that is a faked name passed on to us
1137          to use to in the formpost. If that is not set, the actually used
1138          local file name should be added. */
1139
1140       if(post->more) {
1141         /* if multiple-file */
1142         char *filebasename = NULL;
1143         if(!file->showfilename) {
1144           filebasename = strippath(file->contents);
1145           if(!filebasename) {
1146             result = CURLE_OUT_OF_MEMORY;
1147             break;
1148           }
1149         }
1150
1151         result = AddFormDataf(&form, &size,
1152                               "\r\n--%s\r\nContent-Disposition: "
1153                               "attachment; filename=\"%s\"",
1154                               fileboundary,
1155                               (file->showfilename?file->showfilename:
1156                                filebasename));
1157         Curl_safefree(filebasename);
1158         if(result)
1159           break;
1160       }
1161       else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER|
1162                              HTTPPOST_CALLBACK)) {
1163         /* it should be noted that for the HTTPPOST_FILENAME and
1164            HTTPPOST_CALLBACK cases the ->showfilename struct member is always
1165            assigned at this point */
1166         if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) {
1167           char *filebasename=
1168             (!post->showfilename)?strippath(post->contents):NULL;
1169
1170           result = AddFormDataf(&form, &size,
1171                                 "; filename=\"%s\"",
1172                                 (post->showfilename?post->showfilename:
1173                                  filebasename));
1174           Curl_safefree(filebasename);
1175         }
1176
1177         if(result)
1178           break;
1179       }
1180
1181       if(file->contenttype) {
1182         /* we have a specified type */
1183         result = AddFormDataf(&form, &size,
1184                               "\r\nContent-Type: %s",
1185                               file->contenttype);
1186         if(result)
1187           break;
1188       }
1189
1190       curList = file->contentheader;
1191       while(curList) {
1192         /* Process the additional headers specified for this form */
1193         result = AddFormDataf( &form, &size, "\r\n%s", curList->data );
1194         if(result)
1195           break;
1196         curList = curList->next;
1197       }
1198       if(result)
1199         break;
1200
1201       result = AddFormDataf(&form, &size, "\r\n\r\n");
1202       if(result)
1203         break;
1204
1205       if((post->flags & HTTPPOST_FILENAME) ||
1206          (post->flags & HTTPPOST_READFILE)) {
1207         /* we should include the contents from the specified file */
1208         FILE *fileread;
1209
1210         fileread = strequal("-", file->contents)?
1211           stdin:fopen(file->contents, "rb"); /* binary read for win32  */
1212
1213         /*
1214          * VMS: This only allows for stream files on VMS.  Stream files are
1215          * OK, as are FIXED & VAR files WITHOUT implied CC For implied CC,
1216          * every record needs to have a \n appended & 1 added to SIZE
1217          */
1218
1219         if(fileread) {
1220           if(fileread != stdin) {
1221             /* close the file */
1222             fclose(fileread);
1223             /* add the file name only - for later reading from this */
1224             result = AddFormData(&form, FORM_FILE, file->contents, 0, &size);
1225           }
1226           else {
1227             /* When uploading from stdin, we can't know the size of the file,
1228              * thus must read the full file as before. We *could* use chunked
1229              * transfer-encoding, but that only works for HTTP 1.1 and we
1230              * can't be sure we work with such a server.
1231              */
1232             size_t nread;
1233             char buffer[512];
1234             while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
1235               result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
1236               if(result)
1237                 break;
1238             }
1239           }
1240         }
1241         else {
1242           if(data)
1243             failf(data, "couldn't open file \"%s\"", file->contents);
1244           *finalform = NULL;
1245           result = CURLE_READ_ERROR;
1246         }
1247       }
1248       else if(post->flags & HTTPPOST_BUFFER)
1249         /* include contents of buffer */
1250         result = AddFormData(&form, FORM_CONTENT, post->buffer,
1251                              post->bufferlength, &size);
1252       else if(post->flags & HTTPPOST_CALLBACK)
1253         /* the contents should be read with the callback and the size
1254            is set with the contentslength */
1255         result = AddFormData(&form, FORM_CALLBACK, post->userp,
1256                              post->contentslength, &size);
1257       else
1258         /* include the contents we got */
1259         result = AddFormData(&form, FORM_CONTENT, post->contents,
1260                              post->contentslength, &size);
1261
1262       file = file->more;
1263     } while(file && !result); /* for each specified file for this field */
1264
1265     if(result)
1266       break;
1267
1268     if(post->more) {
1269       /* this was a multiple-file inclusion, make a termination file
1270          boundary: */
1271       result = AddFormDataf(&form, &size,
1272                            "\r\n--%s--",
1273                            fileboundary);
1274       if(result)
1275         break;
1276     }
1277
1278   } while((post = post->next) != NULL); /* for each field */
1279
1280   /* end-boundary for everything */
1281   if(CURLE_OK == result)
1282     result = AddFormDataf(&form, &size,
1283                           "\r\n--%s--\r\n",
1284                           boundary);
1285
1286   if(result) {
1287     Curl_formclean(&firstform);
1288     Curl_safefree(fileboundary);
1289     Curl_safefree(boundary);
1290     return result;
1291   }
1292
1293   *sizep = size;
1294
1295   Curl_safefree(fileboundary);
1296   Curl_safefree(boundary);
1297
1298   *finalform = firstform;
1299
1300   return result;
1301 }
1302
1303 /*
1304  * Curl_FormInit() inits the struct 'form' points to with the 'formdata'
1305  * and resets the 'sent' counter.
1306  */
1307 int Curl_FormInit(struct Form *form, struct FormData *formdata )
1308 {
1309   if(!formdata)
1310     return 1; /* error */
1311
1312   form->data = formdata;
1313   form->sent = 0;
1314   form->fp = NULL;
1315   form->fread_func = ZERO_NULL;
1316
1317   return 0;
1318 }
1319
1320 /*
1321  * readfromfile()
1322  *
1323  * The read callback that this function may use can return a value larger than
1324  * 'size' (which then this function returns) that indicates a problem and it
1325  * must be properly dealt with
1326  */
1327 static size_t readfromfile(struct Form *form, char *buffer,
1328                            size_t size)
1329 {
1330   size_t nread;
1331   bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE;
1332
1333   if(callback) {
1334     if(form->fread_func == ZERO_NULL)
1335       return 0;
1336     else
1337       nread = form->fread_func(buffer, 1, size, form->data->line);
1338   }
1339   else {
1340     if(!form->fp) {
1341       /* this file hasn't yet been opened */
1342       form->fp = fopen(form->data->line, "rb"); /* b is for binary */
1343       if(!form->fp)
1344         return (size_t)-1; /* failure */
1345     }
1346     nread = fread(buffer, 1, size, form->fp);
1347   }
1348   if(!nread) {
1349     /* this is the last chunk from the file, move on */
1350     if(form->fp) {
1351       fclose(form->fp);
1352       form->fp = NULL;
1353     }
1354     form->data = form->data->next;
1355   }
1356
1357   return nread;
1358 }
1359
1360 /*
1361  * Curl_FormReader() is the fread() emulation function that will be used to
1362  * deliver the formdata to the transfer loop and then sent away to the peer.
1363  */
1364 size_t Curl_FormReader(char *buffer,
1365                        size_t size,
1366                        size_t nitems,
1367                        FILE *mydata)
1368 {
1369   struct Form *form;
1370   size_t wantedsize;
1371   size_t gotsize = 0;
1372
1373   form=(struct Form *)mydata;
1374
1375   wantedsize = size * nitems;
1376
1377   if(!form->data)
1378     return 0; /* nothing, error, empty */
1379
1380   if((form->data->type == FORM_FILE) ||
1381      (form->data->type == FORM_CALLBACK)) {
1382     gotsize = readfromfile(form, buffer, wantedsize);
1383
1384     if(gotsize)
1385       /* If positive or -1, return. If zero, continue! */
1386       return gotsize;
1387   }
1388   do {
1389
1390     if((form->data->length - form->sent ) > wantedsize - gotsize) {
1391
1392       memcpy(buffer + gotsize , form->data->line + form->sent,
1393              wantedsize - gotsize);
1394
1395       form->sent += wantedsize-gotsize;
1396
1397       return wantedsize;
1398     }
1399
1400     memcpy(buffer+gotsize,
1401            form->data->line + form->sent,
1402            (form->data->length - form->sent) );
1403     gotsize += form->data->length - form->sent;
1404
1405     form->sent = 0;
1406
1407     form->data = form->data->next; /* advance */
1408
1409   } while(form->data && (form->data->type < FORM_CALLBACK));
1410   /* If we got an empty line and we have more data, we proceed to the next
1411      line immediately to avoid returning zero before we've reached the end. */
1412
1413   return gotsize;
1414 }
1415
1416 /*
1417  * Curl_formpostheader() returns the first line of the formpost, the
1418  * request-header part (which is not part of the request-body like the rest of
1419  * the post).
1420  */
1421 char *Curl_formpostheader(void *formp, size_t *len)
1422 {
1423   char *header;
1424   struct Form *form=(struct Form *)formp;
1425
1426   if(!form->data)
1427     return 0; /* nothing, ERROR! */
1428
1429   header = form->data->line;
1430   *len = form->data->length;
1431
1432   form->data = form->data->next; /* advance */
1433
1434   return header;
1435 }
1436
1437 #else  /* CURL_DISABLE_HTTP */
1438 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
1439                           struct curl_httppost **last_post,
1440                           ...)
1441 {
1442   (void)httppost;
1443   (void)last_post;
1444   return CURL_FORMADD_DISABLED;
1445 }
1446
1447 int curl_formget(struct curl_httppost *form, void *arg,
1448                  curl_formget_callback append)
1449 {
1450   (void) form;
1451   (void) arg;
1452   (void) append;
1453   return CURL_FORMADD_DISABLED;
1454 }
1455
1456 void curl_formfree(struct curl_httppost *form)
1457 {
1458   (void)form;
1459   /* does nothing HTTP is disabled */
1460 }
1461
1462 #endif  /* CURL_DISABLE_HTTP */
1463
1464 #if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY)
1465
1466 /*
1467  * Curl_FormBoundary() creates a suitable boundary string and returns an
1468  * allocated one. This is also used by SSL-code so it must be present even
1469  * if HTTP is disabled!
1470  */
1471 char *Curl_FormBoundary(void)
1472 {
1473   char *retstring;
1474   size_t i;
1475
1476   static const char table16[]="0123456789abcdef";
1477
1478   retstring = malloc(BOUNDARY_LENGTH+1);
1479
1480   if(!retstring)
1481     return NULL; /* failed */
1482
1483   strcpy(retstring, "----------------------------");
1484
1485   for(i=strlen(retstring); i<BOUNDARY_LENGTH; i++)
1486     retstring[i] = table16[Curl_rand()%16];
1487
1488   /* 28 dashes and 12 hexadecimal digits makes 12^16 (184884258895036416)
1489      combinations */
1490   retstring[BOUNDARY_LENGTH]=0; /* zero terminate */
1491
1492   return retstring;
1493 }
1494
1495 #endif  /* !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) */