Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel (at) 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 https://curl.haxx.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  ***************************************************************************/
     22 
     23 #include "curl_setup.h"
     24 
     25 #include <curl/curl.h>
     26 
     27 #ifndef CURL_DISABLE_HTTP
     28 
     29 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
     30 #include <libgen.h>
     31 #endif
     32 
     33 #include "urldata.h" /* for struct Curl_easy */
     34 #include "formdata.h"
     35 #include "mime.h"
     36 #include "non-ascii.h"
     37 #include "vtls/vtls.h"
     38 #include "strcase.h"
     39 #include "sendf.h"
     40 #include "strdup.h"
     41 #include "rand.h"
     42 /* The last 3 #include files should be in this order */
     43 #include "curl_printf.h"
     44 #include "curl_memory.h"
     45 #include "memdebug.h"
     46 
     47 
     48 /* What kind of Content-Type to use on un-specified files with unrecognized
     49    extensions. */
     50 #define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
     51 
     52 #define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
     53 #define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
     54 #define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
     55 #define HTTPPOST_READFILE CURL_HTTPPOST_READFILE
     56 #define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER
     57 #define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK
     58 #define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER
     59 
     60 /***************************************************************************
     61  *
     62  * AddHttpPost()
     63  *
     64  * Adds a HttpPost structure to the list, if parent_post is given becomes
     65  * a subpost of parent_post instead of a direct list element.
     66  *
     67  * Returns newly allocated HttpPost on success and NULL if malloc failed.
     68  *
     69  ***************************************************************************/
     70 static struct curl_httppost *
     71 AddHttpPost(char *name, size_t namelength,
     72             char *value, curl_off_t contentslength,
     73             char *buffer, size_t bufferlength,
     74             char *contenttype,
     75             long flags,
     76             struct curl_slist *contentHeader,
     77             char *showfilename, char *userp,
     78             struct curl_httppost *parent_post,
     79             struct curl_httppost **httppost,
     80             struct curl_httppost **last_post)
     81 {
     82   struct curl_httppost *post;
     83   post = calloc(1, sizeof(struct curl_httppost));
     84   if(post) {
     85     post->name = name;
     86     post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
     87     post->contents = value;
     88     post->contentlen = contentslength;
     89     post->buffer = buffer;
     90     post->bufferlength = (long)bufferlength;
     91     post->contenttype = contenttype;
     92     post->contentheader = contentHeader;
     93     post->showfilename = showfilename;
     94     post->userp = userp;
     95     post->flags = flags | CURL_HTTPPOST_LARGE;
     96   }
     97   else
     98     return NULL;
     99 
    100   if(parent_post) {
    101     /* now, point our 'more' to the original 'more' */
    102     post->more = parent_post->more;
    103 
    104     /* then move the original 'more' to point to ourselves */
    105     parent_post->more = post;
    106   }
    107   else {
    108     /* make the previous point to this */
    109     if(*last_post)
    110       (*last_post)->next = post;
    111     else
    112       (*httppost) = post;
    113 
    114     (*last_post) = post;
    115   }
    116   return post;
    117 }
    118 
    119 /***************************************************************************
    120  *
    121  * AddFormInfo()
    122  *
    123  * Adds a FormInfo structure to the list presented by parent_form_info.
    124  *
    125  * Returns newly allocated FormInfo on success and NULL if malloc failed/
    126  * parent_form_info is NULL.
    127  *
    128  ***************************************************************************/
    129 static FormInfo * AddFormInfo(char *value,
    130                               char *contenttype,
    131                               FormInfo *parent_form_info)
    132 {
    133   FormInfo *form_info;
    134   form_info = calloc(1, sizeof(struct FormInfo));
    135   if(form_info) {
    136     if(value)
    137       form_info->value = value;
    138     if(contenttype)
    139       form_info->contenttype = contenttype;
    140     form_info->flags = HTTPPOST_FILENAME;
    141   }
    142   else
    143     return NULL;
    144 
    145   if(parent_form_info) {
    146     /* now, point our 'more' to the original 'more' */
    147     form_info->more = parent_form_info->more;
    148 
    149     /* then move the original 'more' to point to ourselves */
    150     parent_form_info->more = form_info;
    151   }
    152 
    153   return form_info;
    154 }
    155 
    156 /***************************************************************************
    157  *
    158  * ContentTypeForFilename()
    159  *
    160  * Provides content type for filename if one of the known types (else
    161  * (either the prevtype or the default is returned).
    162  *
    163  * Returns some valid contenttype for filename.
    164  *
    165  ***************************************************************************/
    166 static const char *ContentTypeForFilename(const char *filename,
    167                                           const char *prevtype)
    168 {
    169   const char *contenttype = NULL;
    170   unsigned int i;
    171   /*
    172    * No type was specified, we scan through a few well-known
    173    * extensions and pick the first we match!
    174    */
    175   struct ContentType {
    176     const char *extension;
    177     const char *type;
    178   };
    179   static const struct ContentType ctts[]={
    180     {".gif",  "image/gif"},
    181     {".jpg",  "image/jpeg"},
    182     {".jpeg", "image/jpeg"},
    183     {".txt",  "text/plain"},
    184     {".html", "text/html"},
    185     {".xml", "application/xml"}
    186   };
    187 
    188   if(prevtype)
    189     /* default to the previously set/used! */
    190     contenttype = prevtype;
    191   else
    192     contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
    193 
    194   if(filename) { /* in case a NULL was passed in */
    195     for(i = 0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
    196       if(strlen(filename) >= strlen(ctts[i].extension)) {
    197         if(strcasecompare(filename +
    198                           strlen(filename) - strlen(ctts[i].extension),
    199                           ctts[i].extension)) {
    200           contenttype = ctts[i].type;
    201           break;
    202         }
    203       }
    204     }
    205   }
    206   /* we have a contenttype by now */
    207   return contenttype;
    208 }
    209 
    210 /***************************************************************************
    211  *
    212  * FormAdd()
    213  *
    214  * Stores a formpost parameter and builds the appropriate linked list.
    215  *
    216  * Has two principal functionalities: using files and byte arrays as
    217  * post parts. Byte arrays are either copied or just the pointer is stored
    218  * (as the user requests) while for files only the filename and not the
    219  * content is stored.
    220  *
    221  * While you may have only one byte array for each name, multiple filenames
    222  * are allowed (and because of this feature CURLFORM_END is needed after
    223  * using CURLFORM_FILE).
    224  *
    225  * Examples:
    226  *
    227  * Simple name/value pair with copied contents:
    228  * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
    229  * CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
    230  *
    231  * name/value pair where only the content pointer is remembered:
    232  * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
    233  * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END);
    234  * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
    235  *
    236  * storing a filename (CONTENTTYPE is optional!):
    237  * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
    238  * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text",
    239  * CURLFORM_END);
    240  *
    241  * storing multiple filenames:
    242  * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
    243  * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
    244  *
    245  * Returns:
    246  * CURL_FORMADD_OK             on success
    247  * CURL_FORMADD_MEMORY         if the FormInfo allocation fails
    248  * CURL_FORMADD_OPTION_TWICE   if one option is given twice for one Form
    249  * CURL_FORMADD_NULL           if a null pointer was given for a char
    250  * CURL_FORMADD_MEMORY         if the allocation of a FormInfo struct failed
    251  * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
    252  * CURL_FORMADD_INCOMPLETE     if the some FormInfo is not complete (or error)
    253  * CURL_FORMADD_MEMORY         if a HttpPost struct cannot be allocated
    254  * CURL_FORMADD_MEMORY         if some allocation for string copying failed.
    255  * CURL_FORMADD_ILLEGAL_ARRAY  if an illegal option is used in an array
    256  *
    257  ***************************************************************************/
    258 
    259 static
    260 CURLFORMcode FormAdd(struct curl_httppost **httppost,
    261                      struct curl_httppost **last_post,
    262                      va_list params)
    263 {
    264   FormInfo *first_form, *current_form, *form = NULL;
    265   CURLFORMcode return_value = CURL_FORMADD_OK;
    266   const char *prevtype = NULL;
    267   struct curl_httppost *post = NULL;
    268   CURLformoption option;
    269   struct curl_forms *forms = NULL;
    270   char *array_value = NULL; /* value read from an array */
    271 
    272   /* This is a state variable, that if TRUE means that we're parsing an
    273      array that we got passed to us. If FALSE we're parsing the input
    274      va_list arguments. */
    275   bool array_state = FALSE;
    276 
    277   /*
    278    * We need to allocate the first struct to fill in.
    279    */
    280   first_form = calloc(1, sizeof(struct FormInfo));
    281   if(!first_form)
    282     return CURL_FORMADD_MEMORY;
    283 
    284   current_form = first_form;
    285 
    286   /*
    287    * Loop through all the options set. Break if we have an error to report.
    288    */
    289   while(return_value == CURL_FORMADD_OK) {
    290 
    291     /* first see if we have more parts of the array param */
    292     if(array_state && forms) {
    293       /* get the upcoming option from the given array */
    294       option = forms->option;
    295       array_value = (char *)forms->value;
    296 
    297       forms++; /* advance this to next entry */
    298       if(CURLFORM_END == option) {
    299         /* end of array state */
    300         array_state = FALSE;
    301         continue;
    302       }
    303     }
    304     else {
    305       /* This is not array-state, get next option */
    306       option = va_arg(params, CURLformoption);
    307       if(CURLFORM_END == option)
    308         break;
    309     }
    310 
    311     switch(option) {
    312     case CURLFORM_ARRAY:
    313       if(array_state)
    314         /* we don't support an array from within an array */
    315         return_value = CURL_FORMADD_ILLEGAL_ARRAY;
    316       else {
    317         forms = va_arg(params, struct curl_forms *);
    318         if(forms)
    319           array_state = TRUE;
    320         else
    321           return_value = CURL_FORMADD_NULL;
    322       }
    323       break;
    324 
    325       /*
    326        * Set the Name property.
    327        */
    328     case CURLFORM_PTRNAME:
    329 #ifdef CURL_DOES_CONVERSIONS
    330       /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy
    331        * the data in all cases so that we'll have safe memory for the eventual
    332        * conversion.
    333        */
    334 #else
    335       current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
    336 #endif
    337       /* FALLTHROUGH */
    338     case CURLFORM_COPYNAME:
    339       if(current_form->name)
    340         return_value = CURL_FORMADD_OPTION_TWICE;
    341       else {
    342         char *name = array_state?
    343           array_value:va_arg(params, char *);
    344         if(name)
    345           current_form->name = name; /* store for the moment */
    346         else
    347           return_value = CURL_FORMADD_NULL;
    348       }
    349       break;
    350     case CURLFORM_NAMELENGTH:
    351       if(current_form->namelength)
    352         return_value = CURL_FORMADD_OPTION_TWICE;
    353       else
    354         current_form->namelength =
    355           array_state?(size_t)array_value:(size_t)va_arg(params, long);
    356       break;
    357 
    358       /*
    359        * Set the contents property.
    360        */
    361     case CURLFORM_PTRCONTENTS:
    362       current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
    363     case CURLFORM_COPYCONTENTS:
    364       if(current_form->value)
    365         return_value = CURL_FORMADD_OPTION_TWICE;
    366       else {
    367         char *value =
    368           array_state?array_value:va_arg(params, char *);
    369         if(value)
    370           current_form->value = value; /* store for the moment */
    371         else
    372           return_value = CURL_FORMADD_NULL;
    373       }
    374       break;
    375     case CURLFORM_CONTENTSLENGTH:
    376       current_form->contentslength =
    377         array_state?(size_t)array_value:(size_t)va_arg(params, long);
    378       break;
    379 
    380     case CURLFORM_CONTENTLEN:
    381       current_form->flags |= CURL_HTTPPOST_LARGE;
    382       current_form->contentslength =
    383         array_state?(curl_off_t)(size_t)array_value:va_arg(params, curl_off_t);
    384       break;
    385 
    386       /* Get contents from a given file name */
    387     case CURLFORM_FILECONTENT:
    388       if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
    389         return_value = CURL_FORMADD_OPTION_TWICE;
    390       else {
    391         const char *filename = array_state?
    392           array_value:va_arg(params, char *);
    393         if(filename) {
    394           current_form->value = strdup(filename);
    395           if(!current_form->value)
    396             return_value = CURL_FORMADD_MEMORY;
    397           else {
    398             current_form->flags |= HTTPPOST_READFILE;
    399             current_form->value_alloc = TRUE;
    400           }
    401         }
    402         else
    403           return_value = CURL_FORMADD_NULL;
    404       }
    405       break;
    406 
    407       /* We upload a file */
    408     case CURLFORM_FILE:
    409       {
    410         const char *filename = array_state?array_value:
    411           va_arg(params, char *);
    412 
    413         if(current_form->value) {
    414           if(current_form->flags & HTTPPOST_FILENAME) {
    415             if(filename) {
    416               char *fname = strdup(filename);
    417               if(!fname)
    418                 return_value = CURL_FORMADD_MEMORY;
    419               else {
    420                 form = AddFormInfo(fname, NULL, current_form);
    421                 if(!form) {
    422                   free(fname);
    423                   return_value = CURL_FORMADD_MEMORY;
    424                 }
    425                 else {
    426                   form->value_alloc = TRUE;
    427                   current_form = form;
    428                   form = NULL;
    429                 }
    430               }
    431             }
    432             else
    433               return_value = CURL_FORMADD_NULL;
    434           }
    435           else
    436             return_value = CURL_FORMADD_OPTION_TWICE;
    437         }
    438         else {
    439           if(filename) {
    440             current_form->value = strdup(filename);
    441             if(!current_form->value)
    442               return_value = CURL_FORMADD_MEMORY;
    443             else {
    444               current_form->flags |= HTTPPOST_FILENAME;
    445               current_form->value_alloc = TRUE;
    446             }
    447           }
    448           else
    449             return_value = CURL_FORMADD_NULL;
    450         }
    451         break;
    452       }
    453 
    454     case CURLFORM_BUFFERPTR:
    455       current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
    456       if(current_form->buffer)
    457         return_value = CURL_FORMADD_OPTION_TWICE;
    458       else {
    459         char *buffer =
    460           array_state?array_value:va_arg(params, char *);
    461         if(buffer) {
    462           current_form->buffer = buffer; /* store for the moment */
    463           current_form->value = buffer; /* make it non-NULL to be accepted
    464                                            as fine */
    465         }
    466         else
    467           return_value = CURL_FORMADD_NULL;
    468       }
    469       break;
    470 
    471     case CURLFORM_BUFFERLENGTH:
    472       if(current_form->bufferlength)
    473         return_value = CURL_FORMADD_OPTION_TWICE;
    474       else
    475         current_form->bufferlength =
    476           array_state?(size_t)array_value:(size_t)va_arg(params, long);
    477       break;
    478 
    479     case CURLFORM_STREAM:
    480       current_form->flags |= HTTPPOST_CALLBACK;
    481       if(current_form->userp)
    482         return_value = CURL_FORMADD_OPTION_TWICE;
    483       else {
    484         char *userp =
    485           array_state?array_value:va_arg(params, char *);
    486         if(userp) {
    487           current_form->userp = userp;
    488           current_form->value = userp; /* this isn't strictly true but we
    489                                           derive a value from this later on
    490                                           and we need this non-NULL to be
    491                                           accepted as a fine form part */
    492         }
    493         else
    494           return_value = CURL_FORMADD_NULL;
    495       }
    496       break;
    497 
    498     case CURLFORM_CONTENTTYPE:
    499       {
    500         const char *contenttype =
    501           array_state?array_value:va_arg(params, char *);
    502         if(current_form->contenttype) {
    503           if(current_form->flags & HTTPPOST_FILENAME) {
    504             if(contenttype) {
    505               char *type = strdup(contenttype);
    506               if(!type)
    507                 return_value = CURL_FORMADD_MEMORY;
    508               else {
    509                 form = AddFormInfo(NULL, type, current_form);
    510                 if(!form) {
    511                   free(type);
    512                   return_value = CURL_FORMADD_MEMORY;
    513                 }
    514                 else {
    515                   form->contenttype_alloc = TRUE;
    516                   current_form = form;
    517                   form = NULL;
    518                 }
    519               }
    520             }
    521             else
    522               return_value = CURL_FORMADD_NULL;
    523           }
    524           else
    525             return_value = CURL_FORMADD_OPTION_TWICE;
    526         }
    527         else {
    528           if(contenttype) {
    529             current_form->contenttype = strdup(contenttype);
    530             if(!current_form->contenttype)
    531               return_value = CURL_FORMADD_MEMORY;
    532             else
    533               current_form->contenttype_alloc = TRUE;
    534           }
    535           else
    536             return_value = CURL_FORMADD_NULL;
    537         }
    538         break;
    539       }
    540     case CURLFORM_CONTENTHEADER:
    541       {
    542         /* this "cast increases required alignment of target type" but
    543            we consider it OK anyway */
    544         struct curl_slist *list = array_state?
    545           (struct curl_slist *)(void *)array_value:
    546           va_arg(params, struct curl_slist *);
    547 
    548         if(current_form->contentheader)
    549           return_value = CURL_FORMADD_OPTION_TWICE;
    550         else
    551           current_form->contentheader = list;
    552 
    553         break;
    554       }
    555     case CURLFORM_FILENAME:
    556     case CURLFORM_BUFFER:
    557       {
    558         const char *filename = array_state?array_value:
    559           va_arg(params, char *);
    560         if(current_form->showfilename)
    561           return_value = CURL_FORMADD_OPTION_TWICE;
    562         else {
    563           current_form->showfilename = strdup(filename);
    564           if(!current_form->showfilename)
    565             return_value = CURL_FORMADD_MEMORY;
    566           else
    567             current_form->showfilename_alloc = TRUE;
    568         }
    569         break;
    570       }
    571     default:
    572       return_value = CURL_FORMADD_UNKNOWN_OPTION;
    573       break;
    574     }
    575   }
    576 
    577   if(CURL_FORMADD_OK != return_value) {
    578     /* On error, free allocated fields for all nodes of the FormInfo linked
    579        list without deallocating nodes. List nodes are deallocated later on */
    580     FormInfo *ptr;
    581     for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
    582       if(ptr->name_alloc) {
    583         Curl_safefree(ptr->name);
    584         ptr->name_alloc = FALSE;
    585       }
    586       if(ptr->value_alloc) {
    587         Curl_safefree(ptr->value);
    588         ptr->value_alloc = FALSE;
    589       }
    590       if(ptr->contenttype_alloc) {
    591         Curl_safefree(ptr->contenttype);
    592         ptr->contenttype_alloc = FALSE;
    593       }
    594       if(ptr->showfilename_alloc) {
    595         Curl_safefree(ptr->showfilename);
    596         ptr->showfilename_alloc = FALSE;
    597       }
    598     }
    599   }
    600 
    601   if(CURL_FORMADD_OK == return_value) {
    602     /* go through the list, check for completeness and if everything is
    603      * alright add the HttpPost item otherwise set return_value accordingly */
    604 
    605     post = NULL;
    606     for(form = first_form;
    607         form != NULL;
    608         form = form->more) {
    609       if(((!form->name || !form->value) && !post) ||
    610          ( (form->contentslength) &&
    611            (form->flags & HTTPPOST_FILENAME) ) ||
    612          ( (form->flags & HTTPPOST_FILENAME) &&
    613            (form->flags & HTTPPOST_PTRCONTENTS) ) ||
    614 
    615          ( (!form->buffer) &&
    616            (form->flags & HTTPPOST_BUFFER) &&
    617            (form->flags & HTTPPOST_PTRBUFFER) ) ||
    618 
    619          ( (form->flags & HTTPPOST_READFILE) &&
    620            (form->flags & HTTPPOST_PTRCONTENTS) )
    621         ) {
    622         return_value = CURL_FORMADD_INCOMPLETE;
    623         break;
    624       }
    625       if(((form->flags & HTTPPOST_FILENAME) ||
    626           (form->flags & HTTPPOST_BUFFER)) &&
    627          !form->contenttype) {
    628         char *f = form->flags & HTTPPOST_BUFFER?
    629           form->showfilename : form->value;
    630 
    631         /* our contenttype is missing */
    632         form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
    633         if(!form->contenttype) {
    634           return_value = CURL_FORMADD_MEMORY;
    635           break;
    636         }
    637         form->contenttype_alloc = TRUE;
    638       }
    639       if(form->name && form->namelength) {
    640         /* Name should not contain nul bytes. */
    641         size_t i;
    642         for(i = 0; i < form->namelength; i++)
    643           if(!form->name[i]) {
    644             return_value = CURL_FORMADD_NULL;
    645             break;
    646           }
    647         if(return_value != CURL_FORMADD_OK)
    648           break;
    649       }
    650       if(!(form->flags & HTTPPOST_PTRNAME) &&
    651          (form == first_form) ) {
    652         /* Note that there's small risk that form->name is NULL here if the
    653            app passed in a bad combo, so we better check for that first. */
    654         if(form->name) {
    655           /* copy name (without strdup; possibly not nul-terminated) */
    656           form->name = Curl_memdup(form->name, form->namelength?
    657                                    form->namelength:
    658                                    strlen(form->name) + 1);
    659         }
    660         if(!form->name) {
    661           return_value = CURL_FORMADD_MEMORY;
    662           break;
    663         }
    664         form->name_alloc = TRUE;
    665       }
    666       if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
    667                           HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
    668                           HTTPPOST_CALLBACK)) && form->value) {
    669         /* copy value (without strdup; possibly contains null characters) */
    670         size_t clen  = (size_t) form->contentslength;
    671         if(!clen)
    672           clen = strlen(form->value) + 1;
    673 
    674         form->value = Curl_memdup(form->value, clen);
    675 
    676         if(!form->value) {
    677           return_value = CURL_FORMADD_MEMORY;
    678           break;
    679         }
    680         form->value_alloc = TRUE;
    681       }
    682       post = AddHttpPost(form->name, form->namelength,
    683                          form->value, form->contentslength,
    684                          form->buffer, form->bufferlength,
    685                          form->contenttype, form->flags,
    686                          form->contentheader, form->showfilename,
    687                          form->userp,
    688                          post, httppost,
    689                          last_post);
    690 
    691       if(!post) {
    692         return_value = CURL_FORMADD_MEMORY;
    693         break;
    694       }
    695 
    696       if(form->contenttype)
    697         prevtype = form->contenttype;
    698     }
    699     if(CURL_FORMADD_OK != return_value) {
    700       /* On error, free allocated fields for nodes of the FormInfo linked
    701          list which are not already owned by the httppost linked list
    702          without deallocating nodes. List nodes are deallocated later on */
    703       FormInfo *ptr;
    704       for(ptr = form; ptr != NULL; ptr = ptr->more) {
    705         if(ptr->name_alloc) {
    706           Curl_safefree(ptr->name);
    707           ptr->name_alloc = FALSE;
    708         }
    709         if(ptr->value_alloc) {
    710           Curl_safefree(ptr->value);
    711           ptr->value_alloc = FALSE;
    712         }
    713         if(ptr->contenttype_alloc) {
    714           Curl_safefree(ptr->contenttype);
    715           ptr->contenttype_alloc = FALSE;
    716         }
    717         if(ptr->showfilename_alloc) {
    718           Curl_safefree(ptr->showfilename);
    719           ptr->showfilename_alloc = FALSE;
    720         }
    721       }
    722     }
    723   }
    724 
    725   /* Always deallocate FormInfo linked list nodes without touching node
    726      fields given that these have either been deallocated or are owned
    727      now by the httppost linked list */
    728   while(first_form) {
    729     FormInfo *ptr = first_form->more;
    730     free(first_form);
    731     first_form = ptr;
    732   }
    733 
    734   return return_value;
    735 }
    736 
    737 /*
    738  * curl_formadd() is a public API to add a section to the multipart formpost.
    739  *
    740  * @unittest: 1308
    741  */
    742 
    743 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
    744                           struct curl_httppost **last_post,
    745                           ...)
    746 {
    747   va_list arg;
    748   CURLFORMcode result;
    749   va_start(arg, last_post);
    750   result = FormAdd(httppost, last_post, arg);
    751   va_end(arg);
    752   return result;
    753 }
    754 
    755 /*
    756  * curl_formget()
    757  * Serialize a curl_httppost struct.
    758  * Returns 0 on success.
    759  *
    760  * @unittest: 1308
    761  */
    762 int curl_formget(struct curl_httppost *form, void *arg,
    763                  curl_formget_callback append)
    764 {
    765   CURLcode result;
    766   curl_mimepart toppart;
    767 
    768   Curl_mime_initpart(&toppart, NULL); /* default form is empty */
    769   result = Curl_getformdata(NULL, &toppart, form, NULL);
    770   if(!result)
    771     result = Curl_mime_prepare_headers(&toppart, "multipart/form-data",
    772                                        NULL, MIMESTRATEGY_FORM);
    773 
    774   while(!result) {
    775     char buffer[8192];
    776     size_t nread = Curl_mime_read(buffer, 1, sizeof buffer, &toppart);
    777 
    778     if(!nread)
    779       break;
    780 
    781     switch(nread) {
    782     default:
    783       if(append(arg, buffer, nread) != nread)
    784         result = CURLE_READ_ERROR;
    785       break;
    786     case CURL_READFUNC_ABORT:
    787     case CURL_READFUNC_PAUSE:
    788       break;
    789     }
    790   }
    791 
    792   Curl_mime_cleanpart(&toppart);
    793   return (int) result;
    794 }
    795 
    796 /*
    797  * curl_formfree() is an external function to free up a whole form post
    798  * chain
    799  */
    800 void curl_formfree(struct curl_httppost *form)
    801 {
    802   struct curl_httppost *next;
    803 
    804   if(!form)
    805     /* no form to free, just get out of this */
    806     return;
    807 
    808   do {
    809     next = form->next;  /* the following form line */
    810 
    811     /* recurse to sub-contents */
    812     curl_formfree(form->more);
    813 
    814     if(!(form->flags & HTTPPOST_PTRNAME))
    815       free(form->name); /* free the name */
    816     if(!(form->flags &
    817          (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK))
    818       )
    819       free(form->contents); /* free the contents */
    820     free(form->contenttype); /* free the content type */
    821     free(form->showfilename); /* free the faked file name */
    822     free(form);       /* free the struct */
    823     form = next;
    824   } while(form); /* continue */
    825 }
    826 
    827 
    828 /* Set mime part name, taking care of non nul-terminated name string. */
    829 static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
    830 {
    831   char *zname;
    832   CURLcode res;
    833 
    834   if(!name || !len)
    835     return curl_mime_name(part, name);
    836   zname = malloc(len + 1);
    837   if(!zname)
    838     return CURLE_OUT_OF_MEMORY;
    839   memcpy(zname, name, len);
    840   zname[len] = '\0';
    841   res = curl_mime_name(part, zname);
    842   free(zname);
    843   return res;
    844 }
    845 
    846 /*
    847  * Curl_getformdata() converts a linked list of "meta data" into a mime
    848  * structure. The input list is in 'post', while the output is stored in
    849  * mime part at '*finalform'.
    850  *
    851  * This function will not do a failf() for the potential memory failures but
    852  * should for all other errors it spots. Just note that this function MAY get
    853  * a NULL pointer in the 'data' argument.
    854  */
    855 
    856 CURLcode Curl_getformdata(struct Curl_easy *data,
    857                           curl_mimepart *finalform,
    858                           struct curl_httppost *post,
    859                           curl_read_callback fread_func)
    860 {
    861   CURLcode result = CURLE_OK;
    862   curl_mime *form = NULL;
    863   curl_mime *multipart;
    864   curl_mimepart *part;
    865   struct curl_httppost *file;
    866 
    867   Curl_mime_cleanpart(finalform); /* default form is empty */
    868 
    869   if(!post)
    870     return result; /* no input => no output! */
    871 
    872   form = curl_mime_init(data);
    873   if(!form)
    874     result = CURLE_OUT_OF_MEMORY;
    875 
    876   if(!result)
    877     result = curl_mime_subparts(finalform, form);
    878 
    879   /* Process each top part. */
    880   for(; !result && post; post = post->next) {
    881     /* If we have more than a file here, create a mime subpart and fill it. */
    882     multipart = form;
    883     if(post->more) {
    884       part = curl_mime_addpart(form);
    885       if(!part)
    886         result = CURLE_OUT_OF_MEMORY;
    887       if(!result)
    888         result = setname(part, post->name, post->namelength);
    889       if(!result) {
    890         multipart = curl_mime_init(data);
    891         if(!multipart)
    892           result = CURLE_OUT_OF_MEMORY;
    893       }
    894       if(!result)
    895         result = curl_mime_subparts(part, multipart);
    896     }
    897 
    898     /* Generate all the part contents. */
    899     for(file = post; !result && file; file = file->more) {
    900       /* Create the part. */
    901       part = curl_mime_addpart(multipart);
    902       if(!part)
    903         result = CURLE_OUT_OF_MEMORY;
    904 
    905       /* Set the headers. */
    906       if(!result)
    907         result = curl_mime_headers(part, file->contentheader, 0);
    908 
    909       /* Set the content type. */
    910       if(!result && file->contenttype)
    911         result = curl_mime_type(part, file->contenttype);
    912 
    913       /* Set field name. */
    914       if(!result && !post->more)
    915         result = setname(part, post->name, post->namelength);
    916 
    917       /* Process contents. */
    918       if(!result) {
    919         curl_off_t clen = post->contentslength;
    920 
    921         if(post->flags & CURL_HTTPPOST_LARGE)
    922           clen = post->contentlen;
    923         if(!clen)
    924           clen = -1;
    925 
    926         if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) {
    927           if(!strcmp(file->contents, "-")) {
    928             /* There are a few cases where the code below won't work; in
    929                particular, freopen(stdin) by the caller is not guaranteed
    930                to result as expected. This feature has been kept for backward
    931                compatibility: use of "-" pseudo file name should be avoided. */
    932             result = curl_mime_data_cb(part, (curl_off_t) -1,
    933                                        (curl_read_callback) fread,
    934                                        (curl_seek_callback) fseek,
    935                                        NULL, (void *) stdin);
    936           }
    937           else
    938             result = curl_mime_filedata(part, file->contents);
    939           if(!result && (post->flags & HTTPPOST_READFILE))
    940             result = curl_mime_filename(part, NULL);
    941         }
    942         else if(post->flags & HTTPPOST_BUFFER)
    943           result = curl_mime_data(part, post->buffer,
    944                                   post->bufferlength? post->bufferlength: -1);
    945         else if(post->flags & HTTPPOST_CALLBACK)
    946           /* the contents should be read with the callback and the size is set
    947              with the contentslength */
    948           result = curl_mime_data_cb(part, clen,
    949                                      fread_func, NULL, NULL, post->userp);
    950         else {
    951           result = curl_mime_data(part, post->contents, (ssize_t) clen);
    952 #ifdef CURL_DOES_CONVERSIONS
    953           /* Convert textual contents now. */
    954           if(!result && data && part->datasize)
    955             result = Curl_convert_to_network(data, part->data, part->datasize);
    956 #endif
    957         }
    958       }
    959 
    960       /* Set fake file name. */
    961       if(!result && post->showfilename)
    962         if(post->more || (post->flags & (HTTPPOST_FILENAME | HTTPPOST_BUFFER |
    963                                         HTTPPOST_CALLBACK)))
    964           result = curl_mime_filename(part, post->showfilename);
    965     }
    966   }
    967 
    968   if(result)
    969     Curl_mime_cleanpart(finalform);
    970 
    971   return result;
    972 }
    973 
    974 #else  /* CURL_DISABLE_HTTP */
    975 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
    976                           struct curl_httppost **last_post,
    977                           ...)
    978 {
    979   (void)httppost;
    980   (void)last_post;
    981   return CURL_FORMADD_DISABLED;
    982 }
    983 
    984 int curl_formget(struct curl_httppost *form, void *arg,
    985                  curl_formget_callback append)
    986 {
    987   (void) form;
    988   (void) arg;
    989   (void) append;
    990   return CURL_FORMADD_DISABLED;
    991 }
    992 
    993 void curl_formfree(struct curl_httppost *form)
    994 {
    995   (void)form;
    996   /* does nothing HTTP is disabled */
    997 }
    998 
    999 
   1000 #endif  /* !defined(CURL_DISABLE_HTTP) */
   1001