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