File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / formdata.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (5 years ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>