diff options
author | Brad King <brad.king@kitware.com> | 2014-10-08 20:30:41 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2014-10-29 20:43:21 (GMT) |
commit | 80c881f7938969dab169f4fc4fbf8bc3d4355fc2 (patch) | |
tree | 77abe643bf8fcb388056480350b99b666f543965 /Utilities/cmcurl/lib/formdata.c | |
parent | ff67d2b57946a29e18d1947efe71f26ece9e1747 (diff) | |
parent | 3fe5d9bff98b4716e219516c30d71462495324f4 (diff) | |
download | CMake-80c881f7938969dab169f4fc4fbf8bc3d4355fc2.zip CMake-80c881f7938969dab169f4fc4fbf8bc3d4355fc2.tar.gz CMake-80c881f7938969dab169f4fc4fbf8bc3d4355fc2.tar.bz2 |
Merge branch 'curl-upstream' into update-curl
Resolve all conflicts in favor of the upstream side.
We can re-apply specific changes later.
Diffstat (limited to 'Utilities/cmcurl/lib/formdata.c')
-rw-r--r-- | Utilities/cmcurl/lib/formdata.c | 1182 |
1 files changed, 542 insertions, 640 deletions
diff --git a/Utilities/cmcurl/lib/formdata.c b/Utilities/cmcurl/lib/formdata.c index f10c6c7..3260928 100644 --- a/Utilities/cmcurl/lib/formdata.c +++ b/Utilities/cmcurl/lib/formdata.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -18,111 +18,24 @@ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * - * $Id$ ***************************************************************************/ -/* - Debug the form generator stand-alone by compiling this source file with: - - gcc -DHAVE_CONFIG_H -I../ -g -D_FORM_DEBUG -DCURLDEBUG -o formdata -I../include formdata.c strequal.c memdebug.c mprintf.c strerror.c - - run the 'formdata' executable the output should end with: - All Tests seem to have worked ... - and the following parts should be there: - -Content-Disposition: form-data; name="simple_COPYCONTENTS" -value for simple COPYCONTENTS - -Content-Disposition: form-data; name="COPYCONTENTS_+_CONTENTTYPE" -Content-Type: image/gif -value for COPYCONTENTS + CONTENTTYPE - -Content-Disposition: form-data; name="PRNAME_+_NAMELENGTH_+_COPYNAME_+_CONTENTSLENGTH" -vlue for PTRNAME + NAMELENGTH + COPYNAME + CONTENTSLENGTH -(or you might see P^@RNAME and v^@lue at the start) - -Content-Disposition: form-data; name="simple_PTRCONTENTS" -value for simple PTRCONTENTS - -Content-Disposition: form-data; name="PTRCONTENTS_+_CONTENTSLENGTH" -vlue for PTRCONTENTS + CONTENTSLENGTH -(or you might see v^@lue at the start) - -Content-Disposition: form-data; name="PTRCONTENTS_+_CONTENTSLENGTH_+_CONTENTTYPE" -Content-Type: text/plain -vlue for PTRCOTNENTS + CONTENTSLENGTH + CONTENTTYPE -(or you might see v^@lue at the start) - -Content-Disposition: form-data; name="FILE1_+_CONTENTTYPE"; filename="inet_ntoa_r.h" -Content-Type: text/html -... - -Content-Disposition: form-data; name="FILE1_+_FILE2" -Content-Type: multipart/mixed, boundary=curlz1s0dkticx49MV1KGcYP5cvfSsz -... -Content-Disposition: attachment; filename="inet_ntoa_r.h" -Content-Type: text/plain -... -Content-Disposition: attachment; filename="Makefile.b32" -Content-Type: text/plain -... - -Content-Disposition: form-data; name="FILE1_+_FILE2_+_FILE3" -Content-Type: multipart/mixed, boundary=curlirkYPmPwu6FrJ1vJ1u1BmtIufh1 -... -Content-Disposition: attachment; filename="inet_ntoa_r.h" -Content-Type: text/plain -... -Content-Disposition: attachment; filename="Makefile.b32" -Content-Type: text/plain -... -Content-Disposition: attachment; filename="inet_ntoa_r.h" -Content-Type: text/plain -... - - -Content-Disposition: form-data; name="ARRAY: FILE1_+_FILE2_+_FILE3" -Content-Type: multipart/mixed, boundary=curlirkYPmPwu6FrJ1vJ1u1BmtIufh1 -... -Content-Disposition: attachment; filename="inet_ntoa_r.h" -Content-Type: text/plain -... -Content-Disposition: attachment; filename="Makefile.b32" -Content-Type: text/plain -... -Content-Disposition: attachment; filename="inet_ntoa_r.h" -Content-Type: text/plain -... - -Content-Disposition: form-data; name="FILECONTENT" -... - - */ +#include "curl_setup.h" -#include "setup.h" #include <curl/curl.h> -/* Length of the random boundary string. */ -#define BOUNDARY_LENGTH 40 - #if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <time.h> -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) #include <libgen.h> #endif + #include "urldata.h" /* for struct SessionHandle */ -#include "easyif.h" /* for Curl_convert_... prototypes */ #include "formdata.h" +#include "vtls/vtls.h" #include "strequal.h" -#include "memory.h" +#include "curl_memory.h" +#include "sendf.h" #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> @@ -134,12 +47,13 @@ Content-Disposition: form-data; name="FILECONTENT" #ifndef CURL_DISABLE_HTTP -#if defined(HAVE_BASENAME) && defined(NEED_BASENAME_PROTO) -/* This system has a basename() but no prototype for it! */ -char *basename(char *path); +#ifndef HAVE_BASENAME +static char *Curl_basename(char *path); +#define basename(x) Curl_basename((x)) #endif static size_t readfromfile(struct Form *form, char *buffer, size_t size); +static char *formboundary(struct SessionHandle *data); /* What kind of Content-Type to use on un-specified files with unrecognized extensions. */ @@ -159,19 +73,19 @@ static size_t readfromfile(struct Form *form, char *buffer, size_t size); * ***************************************************************************/ static struct curl_httppost * -AddHttpPost(char * name, size_t namelength, - char * value, size_t contentslength, - char * buffer, size_t bufferlength, +AddHttpPost(char *name, size_t namelength, + char *value, size_t contentslength, + char *buffer, size_t bufferlength, char *contenttype, long flags, struct curl_slist* contentHeader, - char *showfilename, + char *showfilename, char *userp, struct curl_httppost *parent_post, struct curl_httppost **httppost, struct curl_httppost **last_post) { struct curl_httppost *post; - post = (struct curl_httppost *)calloc(sizeof(struct curl_httppost), 1); + post = calloc(1, sizeof(struct curl_httppost)); if(post) { post->name = name; post->namelength = (long)(name?(namelength?namelength:strlen(name)):0); @@ -182,12 +96,13 @@ AddHttpPost(char * name, size_t namelength, post->contenttype = contenttype; post->contentheader = contentHeader; post->showfilename = showfilename; + post->userp = userp, post->flags = flags; } else return NULL; - if (parent_post) { + if(parent_post) { /* now, point our 'more' to the original 'more' */ post->more = parent_post->more; @@ -221,27 +136,24 @@ static FormInfo * AddFormInfo(char *value, FormInfo *parent_form_info) { FormInfo *form_info; - form_info = (FormInfo *)malloc(sizeof(FormInfo)); + form_info = calloc(1, sizeof(struct FormInfo)); if(form_info) { - memset(form_info, 0, sizeof(FormInfo)); - if (value) + if(value) form_info->value = value; - if (contenttype) + if(contenttype) form_info->contenttype = contenttype; form_info->flags = HTTPPOST_FILENAME; } else return NULL; - if (parent_form_info) { + if(parent_form_info) { /* now, point our 'more' to the original 'more' */ form_info->more = parent_form_info->more; /* then move the original 'more' to point to ourselves */ parent_form_info->more = form_info; } - else - return NULL; return form_info; } @@ -256,8 +168,8 @@ static FormInfo * AddFormInfo(char *value, * Returns some valid contenttype for filename. * ***************************************************************************/ -static const char * ContentTypeForFilename (const char *filename, - const char *prevtype) +static const char *ContentTypeForFilename(const char *filename, + const char *prevtype) { const char *contenttype = NULL; unsigned int i; @@ -274,24 +186,25 @@ static const char * ContentTypeForFilename (const char *filename, {".jpg", "image/jpeg"}, {".jpeg", "image/jpeg"}, {".txt", "text/plain"}, - {".html", "text/html"} + {".html", "text/html"}, + {".xml", "application/xml"} }; if(prevtype) /* default to the previously set/used! */ contenttype = prevtype; else - /* It seems RFC1867 defines no Content-Type to default to - text/plain so we don't actually need to set this: */ contenttype = HTTPPOST_CONTENTTYPE_DEFAULT; - for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) { - if(strlen(filename) >= strlen(ctts[i].extension)) { - if(strequal(filename + - strlen(filename) - strlen(ctts[i].extension), - ctts[i].extension)) { - contenttype = ctts[i].type; - break; + if(filename) { /* in case a NULL was passed in */ + for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) { + if(strlen(filename) >= strlen(ctts[i].extension)) { + if(strequal(filename + + strlen(filename) - strlen(ctts[i].extension), + ctts[i].extension)) { + contenttype = ctts[i].type; + break; + } } } } @@ -316,20 +229,24 @@ static char *memdup(const char *src, size_t buffer_length) bool add = FALSE; char *buffer; - if (buffer_length) + if(buffer_length) length = buffer_length; - else { + else if(src) { length = strlen(src); add = TRUE; } - buffer = (char*)malloc(length+add); - if (!buffer) + else + /* no length and a NULL src pointer! */ + return strdup(""); + + buffer = malloc(length+add); + if(!buffer) return NULL; /* fail */ memcpy(buffer, src, length); /* if length unknown do null termination */ - if (add) + if(add) buffer[length] = '\0'; return buffer; @@ -377,7 +294,7 @@ static char *memdup(const char *src, size_t buffer_length) * CURL_FORMADD_NULL if a null pointer was given for a char * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used - * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or an error) + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated * CURL_FORMADD_MEMORY if some allocation for string copying failed. * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array @@ -405,7 +322,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, /* * We need to allocate the first struct to fill in. */ - first_form = (FormInfo *)calloc(sizeof(struct FormInfo), 1); + first_form = calloc(1, sizeof(struct FormInfo)); if(!first_form) return CURL_FORMADD_MEMORY; @@ -414,16 +331,16 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, /* * Loop through all the options set. Break if we have an error to report. */ - while (return_value == CURL_FORMADD_OK) { + while(return_value == CURL_FORMADD_OK) { /* first see if we have more parts of the array param */ - if ( array_state ) { + if(array_state && forms) { /* get the upcoming option from the given array */ option = forms->option; array_value = (char *)forms->value; forms++; /* advance this to next entry */ - if (CURLFORM_END == option) { + if(CURLFORM_END == option) { /* end of array state */ array_state = FALSE; continue; @@ -432,7 +349,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, else { /* This is not array-state, get next option */ option = va_arg(params, CURLformoption); - if (CURLFORM_END == option) + if(CURLFORM_END == option) break; } @@ -443,7 +360,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, return_value = CURL_FORMADD_ILLEGAL_ARRAY; else { forms = va_arg(params, struct curl_forms *); - if (forms) + if(forms) array_state = TRUE; else return_value = CURL_FORMADD_NULL; @@ -455,29 +372,31 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, */ case CURLFORM_PTRNAME: #ifdef CURL_DOES_CONVERSIONS - /* treat CURLFORM_PTR like CURLFORM_COPYNAME so we'll - have safe memory for the eventual conversion */ + /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy + * the data in all cases so that we'll have safe memory for the eventual + * conversion. + */ #else current_form->flags |= HTTPPOST_PTRNAME; /* fall through */ #endif case CURLFORM_COPYNAME: - if (current_form->name) + if(current_form->name) return_value = CURL_FORMADD_OPTION_TWICE; else { char *name = array_state? array_value:va_arg(params, char *); - if (name) + if(name) current_form->name = name; /* store for the moment */ else return_value = CURL_FORMADD_NULL; } break; case CURLFORM_NAMELENGTH: - if (current_form->namelength) + if(current_form->namelength) return_value = CURL_FORMADD_OPTION_TWICE; else current_form->namelength = - array_state?(long)array_value:(long)va_arg(params, long); + array_state?(size_t)array_value:(size_t)va_arg(params, long); break; /* @@ -486,33 +405,33 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, case CURLFORM_PTRCONTENTS: current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */ case CURLFORM_COPYCONTENTS: - if (current_form->value) + if(current_form->value) return_value = CURL_FORMADD_OPTION_TWICE; else { char *value = array_state?array_value:va_arg(params, char *); - if (value) + if(value) current_form->value = value; /* store for the moment */ else return_value = CURL_FORMADD_NULL; } break; case CURLFORM_CONTENTSLENGTH: - if (current_form->contentslength) + if(current_form->contentslength) return_value = CURL_FORMADD_OPTION_TWICE; else current_form->contentslength = - array_state?(long)array_value:va_arg(params, long); + array_state?(size_t)array_value:(size_t)va_arg(params, long); break; /* Get contents from a given file name */ case CURLFORM_FILECONTENT: - if (current_form->flags != 0) + if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE)) return_value = CURL_FORMADD_OPTION_TWICE; else { - char *filename = array_state? + const char *filename = array_state? array_value:va_arg(params, char *); - if (filename) { + if(filename) { current_form->value = strdup(filename); if(!current_form->value) return_value = CURL_FORMADD_MEMORY; @@ -529,15 +448,27 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, /* We upload a file */ case CURLFORM_FILE: { - char *filename = array_state?array_value: + const char *filename = array_state?array_value: va_arg(params, char *); - if (current_form->value) { - if (current_form->flags & HTTPPOST_FILENAME) { - if (filename) { - if ((current_form = AddFormInfo(strdup(filename), - NULL, current_form)) == NULL) + if(current_form->value) { + if(current_form->flags & HTTPPOST_FILENAME) { + if(filename) { + char *fname = strdup(filename); + if(!fname) return_value = CURL_FORMADD_MEMORY; + else { + form = AddFormInfo(fname, NULL, current_form); + if(!form) { + Curl_safefree(fname); + return_value = CURL_FORMADD_MEMORY; + } + else { + form->value_alloc = TRUE; + current_form = form; + form = NULL; + } + } } else return_value = CURL_FORMADD_NULL; @@ -546,7 +477,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, return_value = CURL_FORMADD_OPTION_TWICE; } else { - if (filename) { + if(filename) { current_form->value = strdup(filename); if(!current_form->value) return_value = CURL_FORMADD_MEMORY; @@ -561,70 +492,72 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, break; } - case CURLFORM_BUFFER: - { - char *filename = array_state?array_value: - va_arg(params, char *); - - if (current_form->value) { - if (current_form->flags & HTTPPOST_BUFFER) { - if (filename) { - if ((current_form = AddFormInfo(strdup(filename), - NULL, current_form)) == NULL) - return_value = CURL_FORMADD_MEMORY; - } - else - return_value = CURL_FORMADD_NULL; - } - else - return_value = CURL_FORMADD_OPTION_TWICE; - } - else { - if (filename) { - current_form->value = strdup(filename); - if(!current_form->value) - return_value = CURL_FORMADD_MEMORY; - } - else - return_value = CURL_FORMADD_NULL; - current_form->flags |= HTTPPOST_BUFFER; - } - break; - } - case CURLFORM_BUFFERPTR: - current_form->flags |= HTTPPOST_PTRBUFFER; - if (current_form->buffer) + current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER; + if(current_form->buffer) return_value = CURL_FORMADD_OPTION_TWICE; else { char *buffer = array_state?array_value:va_arg(params, char *); - if (buffer) + if(buffer) { current_form->buffer = buffer; /* store for the moment */ + current_form->value = buffer; /* make it non-NULL to be accepted + as fine */ + } else return_value = CURL_FORMADD_NULL; } break; case CURLFORM_BUFFERLENGTH: - if (current_form->bufferlength) + if(current_form->bufferlength) return_value = CURL_FORMADD_OPTION_TWICE; else current_form->bufferlength = - array_state?(long)array_value:va_arg(params, long); + array_state?(size_t)array_value:(size_t)va_arg(params, long); + break; + + case CURLFORM_STREAM: + current_form->flags |= HTTPPOST_CALLBACK; + if(current_form->userp) + return_value = CURL_FORMADD_OPTION_TWICE; + else { + char *userp = + array_state?array_value:va_arg(params, char *); + if(userp) { + current_form->userp = userp; + current_form->value = userp; /* this isn't strictly true but we + derive a value from this later on + and we need this non-NULL to be + accepted as a fine form part */ + } + else + return_value = CURL_FORMADD_NULL; + } break; case CURLFORM_CONTENTTYPE: { - char *contenttype = + const char *contenttype = array_state?array_value:va_arg(params, char *); - if (current_form->contenttype) { - if (current_form->flags & HTTPPOST_FILENAME) { - if (contenttype) { - if ((current_form = AddFormInfo(NULL, - strdup(contenttype), - current_form)) == NULL) + if(current_form->contenttype) { + if(current_form->flags & HTTPPOST_FILENAME) { + if(contenttype) { + char *type = strdup(contenttype); + if(!type) return_value = CURL_FORMADD_MEMORY; + else { + form = AddFormInfo(NULL, type, current_form); + if(!form) { + Curl_safefree(type); + return_value = CURL_FORMADD_MEMORY; + } + else { + form->contenttype_alloc = TRUE; + current_form = form; + form = NULL; + } + } } else return_value = CURL_FORMADD_NULL; @@ -633,7 +566,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, return_value = CURL_FORMADD_OPTION_TWICE; } else { - if (contenttype) { + if(contenttype) { current_form->contenttype = strdup(contenttype); if(!current_form->contenttype) return_value = CURL_FORMADD_MEMORY; @@ -653,7 +586,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, (struct curl_slist*)array_value: va_arg(params, struct curl_slist*); - if( current_form->contentheader ) + if(current_form->contentheader) return_value = CURL_FORMADD_OPTION_TWICE; else current_form->contentheader = list; @@ -661,10 +594,11 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, break; } case CURLFORM_FILENAME: + case CURLFORM_BUFFER: { - char *filename = array_state?array_value: + const char *filename = array_state?array_value: va_arg(params, char *); - if( current_form->showfilename ) + if(current_form->showfilename) return_value = CURL_FORMADD_OPTION_TWICE; else { current_form->showfilename = strdup(filename); @@ -677,63 +611,92 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, } default: return_value = CURL_FORMADD_UNKNOWN_OPTION; + break; + } + } + + if(CURL_FORMADD_OK != return_value) { + /* On error, free allocated fields for all nodes of the FormInfo linked + list without deallocating nodes. List nodes are deallocated later on */ + FormInfo *ptr; + for(ptr = first_form; ptr != NULL; ptr = ptr->more) { + if(ptr->name_alloc) { + Curl_safefree(ptr->name); + ptr->name_alloc = FALSE; + } + if(ptr->value_alloc) { + Curl_safefree(ptr->value); + ptr->value_alloc = FALSE; + } + if(ptr->contenttype_alloc) { + Curl_safefree(ptr->contenttype); + ptr->contenttype_alloc = FALSE; + } + if(ptr->showfilename_alloc) { + Curl_safefree(ptr->showfilename); + ptr->showfilename_alloc = FALSE; + } } } if(CURL_FORMADD_OK == return_value) { - /* go through the list, check for copleteness and if everything is + /* go through the list, check for completeness and if everything is * alright add the HttpPost item otherwise set return_value accordingly */ post = NULL; for(form = first_form; form != NULL; form = form->more) { - if ( ((!form->name || !form->value) && !post) || - ( (form->contentslength) && - (form->flags & HTTPPOST_FILENAME) ) || - ( (form->flags & HTTPPOST_FILENAME) && - (form->flags & HTTPPOST_PTRCONTENTS) ) || - - ( (!form->buffer) && - (form->flags & HTTPPOST_BUFFER) && - (form->flags & HTTPPOST_PTRBUFFER) ) || - - ( (form->flags & HTTPPOST_READFILE) && - (form->flags & HTTPPOST_PTRCONTENTS) ) - ) { + if(((!form->name || !form->value) && !post) || + ( (form->contentslength) && + (form->flags & HTTPPOST_FILENAME) ) || + ( (form->flags & HTTPPOST_FILENAME) && + (form->flags & HTTPPOST_PTRCONTENTS) ) || + + ( (!form->buffer) && + (form->flags & HTTPPOST_BUFFER) && + (form->flags & HTTPPOST_PTRBUFFER) ) || + + ( (form->flags & HTTPPOST_READFILE) && + (form->flags & HTTPPOST_PTRCONTENTS) ) + ) { return_value = CURL_FORMADD_INCOMPLETE; break; } else { - if ( ((form->flags & HTTPPOST_FILENAME) || - (form->flags & HTTPPOST_BUFFER)) && - !form->contenttype ) { + if(((form->flags & HTTPPOST_FILENAME) || + (form->flags & HTTPPOST_BUFFER)) && + !form->contenttype ) { + char *f = form->flags & HTTPPOST_BUFFER? + form->showfilename : form->value; + /* our contenttype is missing */ - form->contenttype - = strdup(ContentTypeForFilename(form->value, prevtype)); + form->contenttype = strdup(ContentTypeForFilename(f, prevtype)); if(!form->contenttype) { return_value = CURL_FORMADD_MEMORY; break; } form->contenttype_alloc = TRUE; } - if ( !(form->flags & HTTPPOST_PTRNAME) && - (form == first_form) ) { - /* copy name (without strdup; possibly contains null characters) */ - form->name = memdup(form->name, form->namelength); - if (!form->name) { + if(!(form->flags & HTTPPOST_PTRNAME) && + (form == first_form) ) { + /* Note that there's small risk that form->name is NULL here if the + app passed in a bad combo, so we better check for that first. */ + if(form->name) + /* copy name (without strdup; possibly contains null characters) */ + form->name = memdup(form->name, form->namelength); + if(!form->name) { return_value = CURL_FORMADD_MEMORY; break; } form->name_alloc = TRUE; } - if ( !(form->flags & HTTPPOST_FILENAME) && - !(form->flags & HTTPPOST_READFILE) && - !(form->flags & HTTPPOST_PTRCONTENTS) && - !(form->flags & HTTPPOST_PTRBUFFER) ) { + if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE | + HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER | + HTTPPOST_CALLBACK)) ) { /* copy value (without strdup; possibly contains null characters) */ form->value = memdup(form->value, form->contentslength); - if (!form->value) { + if(!form->value) { return_value = CURL_FORMADD_MEMORY; break; } @@ -744,6 +707,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, form->buffer, form->bufferlength, form->contenttype, form->flags, form->contentheader, form->showfilename, + form->userp, post, httppost, last_post); @@ -752,36 +716,43 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, break; } - if (form->contenttype) + if(form->contenttype) prevtype = form->contenttype; } } - } - - if(return_value) { - /* we return on error, free possibly allocated fields */ - if(!form) - form = current_form; - if(form) { - if(form->name_alloc) - free(form->name); - if(form->value_alloc) - free(form->value); - if(form->contenttype_alloc) - free(form->contenttype); - if(form->showfilename_alloc) - free(form->showfilename); + if(CURL_FORMADD_OK != return_value) { + /* On error, free allocated fields for nodes of the FormInfo linked + list which are not already owned by the httppost linked list + without deallocating nodes. List nodes are deallocated later on */ + FormInfo *ptr; + for(ptr = form; ptr != NULL; ptr = ptr->more) { + if(ptr->name_alloc) { + Curl_safefree(ptr->name); + ptr->name_alloc = FALSE; + } + if(ptr->value_alloc) { + Curl_safefree(ptr->value); + ptr->value_alloc = FALSE; + } + if(ptr->contenttype_alloc) { + Curl_safefree(ptr->contenttype); + ptr->contenttype_alloc = FALSE; + } + if(ptr->showfilename_alloc) { + Curl_safefree(ptr->showfilename); + ptr->showfilename_alloc = FALSE; + } + } } } - /* always delete the allocated memory before returning */ - form = first_form; - while (form != NULL) { - FormInfo *delete_form; - - delete_form = form; - form = form->more; - free (delete_form); + /* Always deallocate FormInfo linked list nodes without touching node + fields given that these have either been deallocated or are owned + now by the httppost linked list */ + while(first_form) { + FormInfo *ptr = first_form->more; + Curl_safefree(first_form); + first_form = ptr; } return return_value; @@ -789,6 +760,8 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, /* * curl_formadd() is a public API to add a section to the multipart formpost. + * + * @unittest: 1308 */ CURLFORMcode curl_formadd(struct curl_httppost **httppost, @@ -803,6 +776,70 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost, return result; } +#ifdef __VMS +#include <fabdef.h> +/* + * get_vms_file_size does what it takes to get the real size of the file + * + * For fixed files, find out the size of the EOF block and adjust. + * + * For all others, have to read the entire file in, discarding the contents. + * Most posted text files will be small, and binary files like zlib archives + * and CD/DVD images should be either a STREAM_LF format or a fixed format. + * + */ +curl_off_t VmsRealFileSize(const char * name, + const struct_stat * stat_buf) +{ + char buffer[8192]; + curl_off_t count; + int ret_stat; + FILE * file; + + file = fopen(name, "r"); + if(file == NULL) + return 0; + + count = 0; + ret_stat = 1; + while(ret_stat > 0) { + ret_stat = fread(buffer, 1, sizeof(buffer), file); + if(ret_stat != 0) + count += ret_stat; + } + fclose(file); + + return count; +} + +/* + * + * VmsSpecialSize checks to see if the stat st_size can be trusted and + * if not to call a routine to get the correct size. + * + */ +static curl_off_t VmsSpecialSize(const char * name, + const struct_stat * stat_buf) +{ + switch(stat_buf->st_fab_rfm) { + case FAB$C_VAR: + case FAB$C_VFC: + return VmsRealFileSize(name, stat_buf); + break; + default: + return stat_buf->st_size; + } +} + +#endif + +#ifndef __VMS +#define filesize(name, stat_data) (stat_data.st_size) +#else + /* Getting the expected file size needs help on VMS */ +#define filesize(name, stat_data) VmsSpecialSize(name, &stat_data) +#endif + /* * AddFormData() adds a chunk of data to the FormData linked list. * @@ -814,24 +851,30 @@ static CURLcode AddFormData(struct FormData **formp, size_t length, curl_off_t *size) { - struct FormData *newform = (struct FormData *) - malloc(sizeof(struct FormData)); - if (!newform) + struct FormData *newform = malloc(sizeof(struct FormData)); + if(!newform) return CURLE_OUT_OF_MEMORY; newform->next = NULL; - /* we make it easier for plain strings: */ - if(!length) - length = strlen((char *)line); + if(type <= FORM_CONTENT) { + /* we make it easier for plain strings: */ + if(!length) + length = strlen((char *)line); - newform->line = (char *)malloc(length+1); - if (!newform->line) { - free(newform); - return CURLE_OUT_OF_MEMORY; + newform->line = malloc(length+1); + if(!newform->line) { + free(newform); + return CURLE_OUT_OF_MEMORY; + } + memcpy(newform->line, line, length); + newform->length = length; + newform->line[length]=0; /* zero terminate for easier debugging */ } - memcpy(newform->line, line, length); - newform->length = length; - newform->line[length]=0; /* zero terminate for easier debugging */ + else + /* For callbacks and files we don't have any actual data so we just keep a + pointer to whatever this points to */ + newform->line = (char *)line; + newform->type = type; if(*formp) { @@ -841,17 +884,20 @@ static CURLcode AddFormData(struct FormData **formp, else *formp = newform; - if (size) { - if((type == FORM_DATA) || (type == FORM_CONTENT)) + if(size) { + if(type != FORM_FILE) + /* for static content as well as callback data we add the size given + as input argument */ *size += length; else { /* Since this is a file to be uploaded here, add the size of the actual file */ if(!strequal("-", newform->line)) { struct_stat file; - if(!stat(newform->line, &file)) { - *size += file.st_size; - } + if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode)) + *size += filesize(newform->line, file); + else + return CURLE_BAD_FUNCTION_ARGUMENT; } } } @@ -889,48 +935,21 @@ void Curl_formclean(struct FormData **form_ptr) do { next=form->next; /* the following form line */ - free(form->line); /* free the line */ + if(form->type <= FORM_CONTENT) + free(form->line); /* free the line */ free(form); /* free the struct */ - } while ((form = next) != NULL); /* continue */ + } while((form = next) != NULL); /* continue */ *form_ptr = NULL; } -#ifdef CURL_DOES_CONVERSIONS -/* - * Curl_formcovert() is used from http.c, this converts any - form items that need to be sent in the network encoding. - Returns CURLE_OK on success. - */ -CURLcode Curl_formconvert(struct SessionHandle *data, struct FormData *form) -{ - struct FormData *next; - CURLcode rc; - - if(!form) - return CURLE_OK; - - if(!data) - return CURLE_BAD_FUNCTION_ARGUMENT; - - do { - next=form->next; /* the following form line */ - if (form->type == FORM_DATA) { - rc = Curl_convert_to_network(data, form->line, form->length); - /* Curl_convert_to_network calls failf if unsuccessful */ - if (rc != CURLE_OK) - return rc; - } - } while ((form = next) != NULL); /* continue */ - return CURLE_OK; -} -#endif /* CURL_DOES_CONVERSIONS */ - /* * curl_formget() * Serialize a curl_httppost struct. * Returns 0 on success. + * + * @unittest: 1308 */ int curl_formget(struct curl_httppost *form, void *arg, curl_formget_callback append) @@ -939,30 +958,32 @@ int curl_formget(struct curl_httppost *form, void *arg, curl_off_t size; struct FormData *data, *ptr; - rc = Curl_getFormData(&data, form, NULL, &size); - if (rc != CURLE_OK) + rc = Curl_getformdata(NULL, &data, form, NULL, &size); + if(rc != CURLE_OK) return (int)rc; - for (ptr = data; ptr; ptr = ptr->next) { - if (ptr->type == FORM_FILE) { + for(ptr = data; ptr; ptr = ptr->next) { + if((ptr->type == FORM_FILE) || (ptr->type == FORM_CALLBACK)) { char buffer[8192]; - size_t read; + size_t nread; struct Form temp; Curl_FormInit(&temp, ptr); do { - read = readfromfile(&temp, buffer, sizeof(buffer)); - if ((read == (size_t) -1) || (read != append(arg, buffer, read))) { - if (temp.fp) { + nread = readfromfile(&temp, buffer, sizeof(buffer)); + if((nread == (size_t) -1) || + (nread > sizeof(buffer)) || + (nread != append(arg, buffer, nread))) { + if(temp.fp) fclose(temp.fp); - } Curl_formclean(&data); return -1; } - } while (read == sizeof(buffer)); - } else { - if (ptr->length != append(arg, ptr->line, ptr->length)) { + } while(nread); + } + else { + if(ptr->length != append(arg, ptr->line, ptr->length)) { Curl_formclean(&data); return -1; } @@ -991,9 +1012,11 @@ void curl_formfree(struct curl_httppost *form) if(form->more) curl_formfree(form->more); - if( !(form->flags & HTTPPOST_PTRNAME) && form->name) + if(!(form->flags & HTTPPOST_PTRNAME) && form->name) free(form->name); /* free the name */ - if( !(form->flags & HTTPPOST_PTRCONTENTS) && form->contents) + if(!(form->flags & + (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) && + form->contents) free(form->contents); /* free the contents */ if(form->contenttype) free(form->contenttype); /* free the content type */ @@ -1001,7 +1024,7 @@ void curl_formfree(struct curl_httppost *form) free(form->showfilename); /* free the faked file name */ free(form); /* free the struct */ - } while ((form = next) != NULL); /* continue */ + } while((form = next) != NULL); /* continue */ } #ifndef HAVE_BASENAME @@ -1029,7 +1052,7 @@ void curl_formfree(struct curl_httppost *form) required to be reentrant is not required to be thread-safe. */ -static char *basename(char *path) +static char *Curl_basename(char *path) { /* Ignore all the details above for now and make a quick and simple implementaion here */ @@ -1051,7 +1074,7 @@ static char *basename(char *path) } #endif -static char *strippath(char *fullfile) +static char *strippath(const char *fullfile) { char *filename; char *base; @@ -1063,19 +1086,67 @@ static char *strippath(char *fullfile) free(filename); /* free temporary buffer */ - return base; /* returns an allocated string! */ + return base; /* returns an allocated string or NULL ! */ +} + +static CURLcode formdata_add_filename(const struct curl_httppost *file, + struct FormData **form, + curl_off_t *size) +{ + CURLcode result = CURLE_OK; + char *filename = file->showfilename; + char *filebasename = NULL; + char *filename_escaped = NULL; + + if(!filename) { + filebasename = strippath(file->contents); + if(!filebasename) + return CURLE_OUT_OF_MEMORY; + filename = filebasename; + } + + if(strchr(filename, '\\') || strchr(filename, '"')) { + char *p0, *p1; + + /* filename need be escaped */ + filename_escaped = malloc(strlen(filename)*2+1); + if(!filename_escaped) { + Curl_safefree(filebasename); + return CURLE_OUT_OF_MEMORY; + } + p0 = filename_escaped; + p1 = filename; + while(*p1) { + if(*p1 == '\\' || *p1 == '"') + *p0++ = '\\'; + *p0++ = *p1++; + } + *p0 = '\0'; + filename = filename_escaped; + } + result = AddFormDataf(form, size, + "; filename=\"%s\"", + filename); + Curl_safefree(filename_escaped); + Curl_safefree(filebasename); + return result; } /* - * Curl_getFormData() converts a linked list of "meta data" into a complete + * Curl_getformdata() converts a linked list of "meta data" into a complete * (possibly huge) multipart formdata. The input list is in 'post', while the * output resulting linked lists gets stored in '*finalform'. *sizep will get * the total size of the whole POST. * A multipart/form_data content-type is built, unless a custom content-type * is passed in 'custom_content_type'. + * + * This function will not do a failf() for the potential memory failures but + * should for all other errors it spots. Just note that this function MAY get + * a NULL pointer in the 'data' argument. */ -CURLcode Curl_getFormData(struct FormData **finalform, +CURLcode Curl_getformdata(struct SessionHandle *data, + struct FormData **finalform, struct curl_httppost *post, const char *custom_content_type, curl_off_t *sizep) @@ -1085,17 +1156,17 @@ CURLcode Curl_getFormData(struct FormData **finalform, struct curl_httppost *file; CURLcode result = CURLE_OK; - curl_off_t size=0; /* support potentially ENORMOUS formposts */ + curl_off_t size = 0; /* support potentially ENORMOUS formposts */ char *boundary; - char *fileboundary=NULL; + char *fileboundary = NULL; struct curl_slist* curList; - *finalform=NULL; /* default form is empty */ + *finalform = NULL; /* default form is empty */ if(!post) return result; /* no input => no output! */ - boundary = Curl_FormBoundary(); + boundary = formboundary(data); if(!boundary) return CURLE_OUT_OF_MEMORY; @@ -1106,8 +1177,8 @@ CURLcode Curl_getFormData(struct FormData **finalform, "Content-Type: multipart/form-data", boundary); - if (result) { - free(boundary); + if(result) { + Curl_safefree(boundary); return result; } /* we DO NOT include that line in the total size of the POST, since it'll be @@ -1119,13 +1190,13 @@ CURLcode Curl_getFormData(struct FormData **finalform, if(size) { result = AddFormDataf(&form, &size, "\r\n"); - if (result) + if(result) break; } /* boundary */ result = AddFormDataf(&form, &size, "--%s\r\n", boundary); - if (result) + if(result) break; /* Maybe later this should be disabled when a custom_content_type is @@ -1134,29 +1205,34 @@ CURLcode Curl_getFormData(struct FormData **finalform, */ result = AddFormDataf(&form, &size, "Content-Disposition: form-data; name=\""); - if (result) + if(result) break; result = AddFormData(&form, FORM_DATA, post->name, post->namelength, &size); - if (result) + if(result) break; result = AddFormDataf(&form, &size, "\""); - if (result) + if(result) break; if(post->more) { /* If used, this is a link to more file names, we must then do the magic to include several files with the same field name */ - fileboundary = Curl_FormBoundary(); + Curl_safefree(fileboundary); + fileboundary = formboundary(data); + if(!fileboundary) { + result = CURLE_OUT_OF_MEMORY; + break; + } result = AddFormDataf(&form, &size, - "\r\nContent-Type: multipart/mixed," + "\r\nContent-Type: multipart/mixed;" " boundary=%s\r\n", fileboundary); - if (result) + if(result) break; } @@ -1170,34 +1246,26 @@ CURLcode Curl_getFormData(struct FormData **finalform, if(post->more) { /* if multiple-file */ - char *filebasename= - (!file->showfilename)?strippath(file->contents):NULL; - result = AddFormDataf(&form, &size, "\r\n--%s\r\nContent-Disposition: " - "attachment; filename=\"%s\"", - fileboundary, - (file->showfilename?file->showfilename: - filebasename)); - if (filebasename) - free(filebasename); - if (result) + "attachment", + fileboundary); + if(result) + break; + result = formdata_add_filename(file, &form, &size); + if(result) break; } - else if((post->flags & HTTPPOST_FILENAME) || - (post->flags & HTTPPOST_BUFFER)) { - - char *filebasename= - (!post->showfilename)?strippath(post->contents):NULL; - - result = AddFormDataf(&form, &size, - "; filename=\"%s\"", - (post->showfilename?post->showfilename: - filebasename)); - if (filebasename) - free(filebasename); + else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER| + HTTPPOST_CALLBACK)) { + /* it should be noted that for the HTTPPOST_FILENAME and + HTTPPOST_CALLBACK cases the ->showfilename struct member is always + assigned at this point */ + if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) { + result = formdata_add_filename(post, &form, &size); + } - if (result) + if(result) break; } @@ -1206,43 +1274,23 @@ CURLcode Curl_getFormData(struct FormData **finalform, result = AddFormDataf(&form, &size, "\r\nContent-Type: %s", file->contenttype); - if (result) + if(result) break; } curList = file->contentheader; - while( curList ) { + while(curList) { /* Process the additional headers specified for this form */ result = AddFormDataf( &form, &size, "\r\n%s", curList->data ); - if (result) + if(result) break; curList = curList->next; } - if (result) { - Curl_formclean(&firstform); - free(boundary); - return result; - } - -#if 0 - /* The header Content-Transfer-Encoding: seems to confuse some receivers - * (like the built-in PHP engine). While I can't see any reason why it - * should, I can just as well skip this to the benefit of the users who - * are using such confused receivers. - */ - - if(file->contenttype && - !checkprefix("text/", file->contenttype)) { - /* this is not a text content, mention our binary encoding */ - result = AddFormDataf(&form, &size, - "\r\nContent-Transfer-Encoding: binary"); - if (result) - break; - } -#endif + if(result) + break; result = AddFormDataf(&form, &size, "\r\n\r\n"); - if (result) + if(result) break; if((post->flags & HTTPPOST_FILENAME) || @@ -1261,7 +1309,7 @@ CURLcode Curl_getFormData(struct FormData **finalform, if(fileread) { if(fileread != stdin) { - /* close the file again */ + /* close the file */ fclose(fileread); /* add the file name only - for later reading from this */ result = AddFormData(&form, FORM_FILE, file->contents, 0, &size); @@ -1274,54 +1322,39 @@ CURLcode Curl_getFormData(struct FormData **finalform, */ size_t nread; char buffer[512]; - while ((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) { + while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) { result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size); - if (result) + if(result) break; } } - - if (result) { - Curl_formclean(&firstform); - free(boundary); - return result; - } - } else { -#ifdef _FORM_DEBUG - fprintf(stderr, - "\n==> Curl_getFormData couldn't open/read \"%s\"\n", - file->contents); -#endif - Curl_formclean(&firstform); - free(boundary); + if(data) + failf(data, "couldn't open file \"%s\"", file->contents); *finalform = NULL; - return CURLE_READ_ERROR; + result = CURLE_READ_ERROR; } - } - else if (post->flags & HTTPPOST_BUFFER) { + else if(post->flags & HTTPPOST_BUFFER) /* include contents of buffer */ result = AddFormData(&form, FORM_CONTENT, post->buffer, post->bufferlength, &size); - if (result) - break; - } - - else { + else if(post->flags & HTTPPOST_CALLBACK) + /* the contents should be read with the callback and the size + is set with the contentslength */ + result = AddFormData(&form, FORM_CALLBACK, post->userp, + post->contentslength, &size); + else /* include the contents we got */ result = AddFormData(&form, FORM_CONTENT, post->contents, post->contentslength, &size); - if (result) - break; - } - } while ((file = file->more) != NULL); /* for each specified file for this field */ - if (result) { - Curl_formclean(&firstform); - free(boundary); - return result; - } + + file = file->more; + } while(file && !result); /* for each specified file for this field */ + + if(result) + break; if(post->more) { /* this was a multiple-file inclusion, make a termination file @@ -1329,33 +1362,31 @@ CURLcode Curl_getFormData(struct FormData **finalform, result = AddFormDataf(&form, &size, "\r\n--%s--", fileboundary); - free(fileboundary); - if (result) + if(result) break; } - } while ((post = post->next) != NULL); /* for each field */ - if (result) { - Curl_formclean(&firstform); - free(boundary); - return result; - } + } while((post = post->next) != NULL); /* for each field */ /* end-boundary for everything */ - result = AddFormDataf(&form, &size, - "\r\n--%s--\r\n", - boundary); - if (result) { + if(CURLE_OK == result) + result = AddFormDataf(&form, &size, + "\r\n--%s--\r\n", + boundary); + + if(result) { Curl_formclean(&firstform); - free(boundary); + Curl_safefree(fileboundary); + Curl_safefree(boundary); return result; } *sizep = size; - free(boundary); + Curl_safefree(fileboundary); + Curl_safefree(boundary); - *finalform=firstform; + *finalform = firstform; return result; } @@ -1372,25 +1403,75 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata ) form->data = formdata; form->sent = 0; form->fp = NULL; + form->fread_func = ZERO_NULL; return 0; } -static size_t readfromfile(struct Form *form, char *buffer, size_t size) +#ifndef __VMS +# define fopen_read fopen +#else + /* + * vmsfopenread + * + * For upload to work as expected on VMS, different optional + * parameters must be added to the fopen command based on + * record format of the file. + * + */ +# define fopen_read vmsfopenread +static FILE * vmsfopenread(const char *file, const char *mode) { + struct_stat statbuf; + int result; + + result = stat(file, &statbuf); + + switch (statbuf.st_fab_rfm) { + case FAB$C_VAR: + case FAB$C_VFC: + case FAB$C_STMCR: + return fopen(file, "r"); + break; + default: + return fopen(file, "r", "rfm=stmlf", "ctx=stm"); + } +} +#endif + +/* + * readfromfile() + * + * The read callback that this function may use can return a value larger than + * 'size' (which then this function returns) that indicates a problem and it + * must be properly dealt with + */ +static size_t readfromfile(struct Form *form, char *buffer, + size_t size) { size_t nread; - if(!form->fp) { - /* this file hasn't yet been opened */ - form->fp = fopen(form->data->line, "rb"); /* b is for binary */ - if(!form->fp) - return (size_t)-1; /* failure */ - } - nread = fread(buffer, 1, size, form->fp); + bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE; - if(nread != size) { + if(callback) { + if(form->fread_func == ZERO_NULL) + return 0; + else + nread = form->fread_func(buffer, 1, size, form->data->line); + } + else { + if(!form->fp) { + /* this file hasn't yet been opened */ + form->fp = fopen_read(form->data->line, "rb"); /* b is for binary */ + if(!form->fp) + return (size_t)-1; /* failure */ + } + nread = fread(buffer, 1, size, form->fp); + } + if(!nread) { /* this is the last chunk from the file, move on */ - fclose(form->fp); - form->fp = NULL; + if(form->fp) { + fclose(form->fp); + form->fp = NULL; + } form->data = form->data->next; } @@ -1417,7 +1498,8 @@ size_t Curl_FormReader(char *buffer, if(!form->data) return 0; /* nothing, error, empty */ - if(form->data->type == FORM_FILE) { + if((form->data->type == FORM_FILE) || + (form->data->type == FORM_CALLBACK)) { gotsize = readfromfile(form, buffer, wantedsize); if(gotsize) @@ -1426,7 +1508,7 @@ size_t Curl_FormReader(char *buffer, } do { - if( (form->data->length - form->sent ) > wantedsize - gotsize) { + if((form->data->length - form->sent ) > wantedsize - gotsize) { memcpy(buffer + gotsize , form->data->line + form->sent, wantedsize - gotsize); @@ -1445,10 +1527,9 @@ size_t Curl_FormReader(char *buffer, form->data = form->data->next; /* advance */ - } while(form->data && (form->data->type != FORM_FILE)); + } while(form->data && (form->data->type < FORM_CALLBACK)); /* If we got an empty line and we have more data, we proceed to the next - line immediately to avoid returning zero before we've reached the end. - This is the bug reported November 22 1999 on curl 6.3. (Daniel) */ + line immediately to avoid returning zero before we've reached the end. */ return gotsize; } @@ -1474,161 +1555,18 @@ char *Curl_formpostheader(void *formp, size_t *len) return header; } - -#ifdef _FORM_DEBUG -int FormAddTest(const char * errormsg, - struct curl_httppost **httppost, - struct curl_httppost **last_post, - ...) -{ - int result; - va_list arg; - va_start(arg, last_post); - if ((result = FormAdd(httppost, last_post, arg))) - fprintf (stderr, "ERROR doing FormAdd ret: %d action: %s\n", result, - errormsg); - va_end(arg); - return result; -} - - -int main() +/* + * formboundary() creates a suitable boundary string and returns an allocated + * one. + */ +static char *formboundary(struct SessionHandle *data) { - char name1[] = "simple_COPYCONTENTS"; - char name2[] = "COPYCONTENTS_+_CONTENTTYPE"; - char name3[] = "PTRNAME_+_NAMELENGTH_+_COPYNAME_+_CONTENTSLENGTH"; - char name4[] = "simple_PTRCONTENTS"; - char name5[] = "PTRCONTENTS_+_CONTENTSLENGTH"; - char name6[] = "PTRCONTENTS_+_CONTENTSLENGTH_+_CONTENTTYPE"; - char name7[] = "FILE1_+_CONTENTTYPE"; - char name8[] = "FILE1_+_FILE2"; - char name9[] = "FILE1_+_FILE2_+_FILE3"; - char name10[] = "ARRAY: FILE1_+_FILE2_+_FILE3"; - char name11[] = "FILECONTENT"; - char value1[] = "value for simple COPYCONTENTS"; - char value2[] = "value for COPYCONTENTS + CONTENTTYPE"; - char value3[] = "value for PTRNAME + NAMELENGTH + COPYNAME + CONTENTSLENGTH"; - char value4[] = "value for simple PTRCONTENTS"; - char value5[] = "value for PTRCONTENTS + CONTENTSLENGTH"; - char value6[] = "value for PTRCOTNENTS + CONTENTSLENGTH + CONTENTTYPE"; - char value7[] = "inet_ntoa_r.h"; - char value8[] = "Makefile.b32"; - char type2[] = "image/gif"; - char type6[] = "text/plain"; - char type7[] = "text/html"; - int name3length = strlen(name3); - int value3length = strlen(value3); - int value5length = strlen(value4); - int value6length = strlen(value5); - int errors = 0; - CURLcode rc; - size_t size; - size_t nread; - char buffer[4096]; - struct curl_httppost *httppost=NULL; - struct curl_httppost *last_post=NULL; - struct curl_forms forms[4]; - - struct FormData *form; - struct Form formread; - - if (FormAddTest("simple COPYCONTENTS test", &httppost, &last_post, - CURLFORM_COPYNAME, name1, CURLFORM_COPYCONTENTS, value1, - CURLFORM_END)) - ++errors; - if (FormAddTest("COPYCONTENTS + CONTENTTYPE test", &httppost, &last_post, - CURLFORM_COPYNAME, name2, CURLFORM_COPYCONTENTS, value2, - CURLFORM_CONTENTTYPE, type2, CURLFORM_END)) - ++errors; - /* make null character at start to check that contentslength works - correctly */ - name3[1] = '\0'; - value3[1] = '\0'; - if (FormAddTest("PTRNAME + NAMELENGTH + COPYNAME + CONTENTSLENGTH test", - &httppost, &last_post, - CURLFORM_PTRNAME, name3, CURLFORM_COPYCONTENTS, value3, - CURLFORM_CONTENTSLENGTH, value3length, - CURLFORM_NAMELENGTH, name3length, CURLFORM_END)) - ++errors; - if (FormAddTest("simple PTRCONTENTS test", &httppost, &last_post, - CURLFORM_COPYNAME, name4, CURLFORM_PTRCONTENTS, value4, - CURLFORM_END)) - ++errors; - /* make null character at start to check that contentslength works - correctly */ - value5[1] = '\0'; - if (FormAddTest("PTRCONTENTS + CONTENTSLENGTH test", &httppost, &last_post, - CURLFORM_COPYNAME, name5, CURLFORM_PTRCONTENTS, value5, - CURLFORM_CONTENTSLENGTH, value5length, CURLFORM_END)) - ++errors; - /* make null character at start to check that contentslength works - correctly */ - value6[1] = '\0'; - if (FormAddTest("PTRCONTENTS + CONTENTSLENGTH + CONTENTTYPE test", - &httppost, &last_post, - CURLFORM_COPYNAME, name6, CURLFORM_PTRCONTENTS, value6, - CURLFORM_CONTENTSLENGTH, value6length, - CURLFORM_CONTENTTYPE, type6, CURLFORM_END)) - ++errors; - if (FormAddTest("FILE + CONTENTTYPE test", &httppost, &last_post, - CURLFORM_COPYNAME, name7, CURLFORM_FILE, value7, - CURLFORM_CONTENTTYPE, type7, CURLFORM_END)) - ++errors; - if (FormAddTest("FILE1 + FILE2 test", &httppost, &last_post, - CURLFORM_COPYNAME, name8, CURLFORM_FILE, value7, - CURLFORM_FILE, value8, CURLFORM_END)) - ++errors; - if (FormAddTest("FILE1 + FILE2 + FILE3 test", &httppost, &last_post, - CURLFORM_COPYNAME, name9, CURLFORM_FILE, value7, - CURLFORM_FILE, value8, CURLFORM_FILE, value7, CURLFORM_END)) - ++errors; - forms[0].option = CURLFORM_FILE; - forms[0].value = value7; - forms[1].option = CURLFORM_FILE; - forms[1].value = value8; - forms[2].option = CURLFORM_FILE; - forms[2].value = value7; - forms[3].option = CURLFORM_END; - if (FormAddTest("FILE1 + FILE2 + FILE3 ARRAY test", &httppost, &last_post, - CURLFORM_COPYNAME, name10, CURLFORM_ARRAY, forms, - CURLFORM_END)) - ++errors; - if (FormAddTest("FILECONTENT test", &httppost, &last_post, - CURLFORM_COPYNAME, name11, CURLFORM_FILECONTENT, value7, - CURLFORM_END)) - ++errors; - - rc = Curl_getFormData(&form, httppost, NULL, &size); - if(rc != CURLE_OK) { - if(rc != CURLE_READ_ERROR) { - const char *errortext = curl_easy_strerror(rc); - fprintf(stdout, "\n==> Curl_getFormData error: %s\n", errortext); - } - return 0; - } - - Curl_FormInit(&formread, form); - - do { - nread = Curl_FormReader(buffer, 1, sizeof(buffer), - (FILE *)&formread); - - if(nread < 1) - break; - fwrite(buffer, nread, 1, stdout); - } while(1); - - fprintf(stdout, "size: %d\n", size); - if (errors) - fprintf(stdout, "\n==> %d Test(s) failed!\n", errors); - else - fprintf(stdout, "\nAll Tests seem to have worked (please check output)\n"); - - return 0; + /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615) + combinations */ + return aprintf("------------------------%08x%08x", + Curl_rand(data), Curl_rand(data)); } -#endif /* _FORM_DEBUG */ - #else /* CURL_DISABLE_HTTP */ CURLFORMcode curl_formadd(struct curl_httppost **httppost, struct curl_httppost **last_post, @@ -1654,41 +1592,5 @@ void curl_formfree(struct curl_httppost *form) /* does nothing HTTP is disabled */ } -#endif /* CURL_DISABLE_HTTP */ -#if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) - -/* - * Curl_FormBoundary() creates a suitable boundary string and returns an - * allocated one. This is also used by SSL-code so it must be present even - * if HTTP is disabled! - */ -char *Curl_FormBoundary(void) -{ - char *retstring; - static int randomizer; /* this is just so that two boundaries within - the same form won't be identical */ - size_t i; - - static const char table16[]="abcdef0123456789"; - - retstring = (char *)malloc(BOUNDARY_LENGTH+1); - - if(!retstring) - return NULL; /* failed */ - - srand((unsigned int)time(NULL)+randomizer++); /* seed */ - - strcpy(retstring, "----------------------------"); - - for(i=strlen(retstring); i<BOUNDARY_LENGTH; i++) - retstring[i] = table16[rand()%16]; - - /* 28 dashes and 12 hexadecimal digits makes 12^16 (184884258895036416) - combinations */ - retstring[BOUNDARY_LENGTH]=0; /* zero terminate */ - - return retstring; -} - -#endif /* !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) */ +#endif /* !defined(CURL_DISABLE_HTTP) */ |