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