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