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