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