* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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
- * are also available at http://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
#include <libgen.h>
#endif
-#include "urldata.h" /* for struct SessionHandle */
+#include "urldata.h" /* for struct Curl_easy */
#include "formdata.h"
#include "vtls/vtls.h"
-#include "strequal.h"
+#include "strcase.h"
#include "sendf.h"
#include "strdup.h"
+#include "rand.h"
+/* The last 3 #include files should be in this order */
#include "curl_printf.h"
-
-/* The last #include files should be: */
#include "curl_memory.h"
#include "memdebug.h"
#endif
static size_t readfromfile(struct Form *form, char *buffer, size_t size);
-static char *formboundary(struct SessionHandle *data);
+static char *formboundary(struct Curl_easy *data);
/* What kind of Content-Type to use on un-specified files with unrecognized
extensions. */
#define FORM_FILE_SEPARATOR ','
#define FORM_TYPE_SEPARATOR ';'
+#define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
+#define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
+#define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
+#define HTTPPOST_READFILE CURL_HTTPPOST_READFILE
+#define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER
+#define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK
+#define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER
+
/***************************************************************************
*
* AddHttpPost()
***************************************************************************/
static struct curl_httppost *
AddHttpPost(char *name, size_t namelength,
- char *value, size_t contentslength,
+ char *value, curl_off_t contentslength,
char *buffer, size_t bufferlength,
char *contenttype,
long flags,
- struct curl_slist* contentHeader,
+ struct curl_slist *contentHeader,
char *showfilename, char *userp,
struct curl_httppost *parent_post,
struct curl_httppost **httppost,
post->name = name;
post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
post->contents = value;
- post->contentslength = (long)contentslength;
+ post->contentlen = contentslength;
post->buffer = buffer;
post->bufferlength = (long)bufferlength;
post->contenttype = contenttype;
post->contentheader = contentHeader;
post->showfilename = showfilename;
post->userp = userp,
- post->flags = flags;
+ post->flags = flags | CURL_HTTPPOST_LARGE;
}
else
return NULL;
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)) {
+ if(strcasecompare(filename +
+ strlen(filename) - strlen(ctts[i].extension),
+ ctts[i].extension)) {
contenttype = ctts[i].type;
break;
}
break;
}
- switch (option) {
+ switch(option) {
case CURLFORM_ARRAY:
if(array_state)
/* we don't support an array from within an array */
}
break;
case CURLFORM_CONTENTSLENGTH:
- if(current_form->contentslength)
- return_value = CURL_FORMADD_OPTION_TWICE;
- else
- current_form->contentslength =
- array_state?(size_t)array_value:(size_t)va_arg(params, long);
+ current_form->contentslength =
+ array_state?(size_t)array_value:(size_t)va_arg(params, long);
+ break;
+
+ case CURLFORM_CONTENTLEN:
+ current_form->flags |= CURL_HTTPPOST_LARGE;
+ current_form->contentslength =
+ array_state?(curl_off_t)(size_t)array_value:va_arg(params, curl_off_t);
break;
/* Get contents from a given file name */
{
/* this "cast increases required alignment of target type" but
we consider it OK anyway */
- struct curl_slist* list = array_state?
- (struct curl_slist*)array_value:
- va_arg(params, struct curl_slist*);
+ struct curl_slist *list = array_state?
+ (struct curl_slist *)(void *)array_value:
+ va_arg(params, struct curl_slist *);
if(current_form->contentheader)
return_value = CURL_FORMADD_OPTION_TWICE;
else {
if(((form->flags & HTTPPOST_FILENAME) ||
(form->flags & HTTPPOST_BUFFER)) &&
- !form->contenttype ) {
+ !form->contenttype) {
char *f = form->flags & HTTPPOST_BUFFER?
form->showfilename : form->value;
HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
HTTPPOST_CALLBACK)) && form->value) {
/* copy value (without strdup; possibly contains null characters) */
- form->value = Curl_memdup(form->value, form->contentslength?
- form->contentslength:
- strlen(form->value)+1);
+ size_t clen = (size_t) form->contentslength;
+ if(!clen)
+ clen = strlen(form->value)+1;
+
+ form->value = Curl_memdup(form->value, clen);
+
if(!form->value) {
return_value = CURL_FORMADD_MEMORY;
break;
* 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)
+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"); /* VMS */
+ file = fopen(name, FOPEN_READTEXT); /* VMS */
if(file == NULL)
return 0;
* if not to call a routine to get the correct size.
*
*/
-static curl_off_t VmsSpecialSize(const char * name,
- const struct_stat * stat_buf)
+static curl_off_t VmsSpecialSize(const char *name,
+ const struct_stat *stat_buf)
{
switch(stat_buf->st_fab_rfm) {
case FAB$C_VAR:
static CURLcode AddFormData(struct FormData **formp,
enum formtype type,
const void *line,
- size_t length,
+ curl_off_t length,
curl_off_t *size)
{
- struct FormData *newform = malloc(sizeof(struct FormData));
+ struct FormData *newform;
+ char *alloc2 = NULL;
+ CURLcode result = CURLE_OK;
+ if(length < 0 || (size && *size < 0))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ 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 (SIZEOF_SIZE_T < CURL_SIZEOF_CURL_OFF_T)
+ else if(length >= (curl_off_t)(size_t)-1) {
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto error;
+ }
+#endif
+ if(type != FORM_DATAMEM) {
+ newform->line = malloc((size_t)length+1);
+ if(!newform->line) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto error;
+ }
+ alloc2 = newform->line;
+ memcpy(newform->line, line, (size_t)length);
- newform->line = malloc(length+1);
- if(!newform->line) {
- free(newform);
- return CURLE_OUT_OF_MEMORY;
+ /* zero terminate for easier debugging */
+ newform->line[(size_t)length]=0;
}
- memcpy(newform->line, line, length);
- newform->length = length;
- newform->line[length]=0; /* zero terminate for easier debugging */
+ else {
+ newform->line = (char *)line;
+ type = FORM_DATA; /* in all other aspects this is just FORM_DATA */
+ }
+ newform->length = (size_t)length;
}
else
/* For callbacks and files we don't have any actual data so we just keep a
newform->type = type;
- if(*formp) {
- (*formp)->next = newform;
- *formp = newform;
- }
- else
- *formp = newform;
-
if(size) {
if(type != FORM_FILE)
/* for static content as well as callback data we add the size given
else {
/* Since this is a file to be uploaded here, add the size of the actual
file */
- if(!strequal("-", newform->line)) {
+ if(strcmp("-", newform->line)) {
struct_stat file;
if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
*size += filesize(newform->line, file);
- else
- return CURLE_BAD_FUNCTION_ARGUMENT;
+ else {
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto error;
+ }
}
}
}
+
+ if(*formp) {
+ (*formp)->next = newform;
+ *formp = newform;
+ }
+ else
+ *formp = newform;
+
return CURLE_OK;
+ error:
+ if(newform)
+ free(newform);
+ if(alloc2)
+ free(alloc2);
+ return result;
}
/*
curl_off_t *size,
const char *fmt, ...)
{
- char s[4096];
+ char *s;
+ CURLcode result;
va_list ap;
va_start(ap, fmt);
- vsnprintf(s, sizeof(s), fmt, ap);
+ s = curl_mvaprintf(fmt, ap);
va_end(ap);
- return AddFormData(formp, FORM_DATA, s, 0, size);
+ if(!s)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = AddFormData(formp, FORM_DATAMEM, s, 0, size);
+ if(result)
+ free(s);
+
+ return result;
}
/*
if(form->type <= FORM_CONTENT)
free(form->line); /* free the line */
free(form); /* free the struct */
-
- } while((form = next) != NULL); /* continue */
+ form = next;
+ } while(form); /* continue */
*form_ptr = NULL;
}
free(form->contenttype); /* free the content type */
free(form->showfilename); /* free the faked file name */
free(form); /* free the struct */
-
- } while((form = next) != NULL); /* continue */
+ form = next;
+ } while(form); /* continue */
}
#ifndef HAVE_BASENAME
* a NULL pointer in the 'data' argument.
*/
-CURLcode Curl_getformdata(struct SessionHandle *data,
+CURLcode Curl_getformdata(struct Curl_easy *data,
struct FormData **finalform,
struct curl_httppost *post,
const char *custom_content_type,
curl_off_t size = 0; /* support potentially ENORMOUS formposts */
char *boundary;
char *fileboundary = NULL;
- struct curl_slist* curList;
+ struct curl_slist *curList;
*finalform = NULL; /* default form is empty */
curList = file->contentheader;
while(curList) {
/* Process the additional headers specified for this form */
- result = AddFormDataf( &form, &size, "\r\n%s", curList->data );
+ result = AddFormDataf(&form, &size, "\r\n%s", curList->data);
if(result)
break;
curList = curList->next;
/* we should include the contents from the specified file */
FILE *fileread;
- fileread = strequal("-", file->contents)?
+ fileread = !strcmp("-", file->contents)?
stdin:fopen(file->contents, "rb"); /* binary read for win32 */
/*
char buffer[512];
while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
- if(result)
+ if(result || feof(fileread) || ferror(fileread))
break;
}
}
result = AddFormData(&form, FORM_CONTENT, post->buffer,
post->bufferlength, &size);
else if(post->flags & HTTPPOST_CALLBACK)
- /* the contents should be read with the callback and the size
- is set with the contentslength */
+ /* 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);
+ post->flags&CURL_HTTPPOST_LARGE?
+ post->contentlen:post->contentslength, &size);
else
/* include the contents we got */
result = AddFormData(&form, FORM_CONTENT, post->contents,
- post->contentslength, &size);
-
+ post->flags&CURL_HTTPPOST_LARGE?
+ post->contentlen:post->contentslength, &size);
file = file->more;
} while(file && !result); /* for each specified file for this field */
if(result)
break;
}
-
- } while((post = post->next) != NULL); /* for each field */
+ post = post->next;
+ } while(post); /* for each field */
/* end-boundary for everything */
if(!result)
* Curl_FormInit() inits the struct 'form' points to with the 'formdata'
* and resets the 'sent' counter.
*/
-int Curl_FormInit(struct Form *form, struct FormData *formdata )
+int Curl_FormInit(struct Form *form, struct FormData *formdata)
{
if(!formdata)
return 1; /* error */
*
*/
# define fopen_read vmsfopenread
-static FILE * vmsfopenread(const char *file, const char *mode) {
+static FILE * vmsfopenread(const char *file, const char *mode)
+{
struct_stat statbuf;
int result;
result = stat(file, &statbuf);
- switch (statbuf.st_fab_rfm) {
+ switch(statbuf.st_fab_rfm) {
case FAB$C_VAR:
case FAB$C_VFC:
case FAB$C_STMCR:
- return fopen(file, "r"); /* VMS */
+ return fopen(file, FOPEN_READTEXT); /* VMS */
break;
default:
- return fopen(file, "r", "rfm=stmlf", "ctx=stm");
+ return fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm");
}
}
#endif
}
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,
+ memcpy(buffer + gotsize, form->data->line + form->sent,
wantedsize - gotsize);
form->sent += wantedsize-gotsize;
struct Form *form=(struct Form *)formp;
if(!form->data)
- return 0; /* nothing, ERROR! */
+ return NULL; /* nothing, ERROR! */
header = form->data->line;
*len = form->data->length;
* formboundary() creates a suitable boundary string and returns an allocated
* one.
*/
-static char *formboundary(struct SessionHandle *data)
+static char *formboundary(struct Curl_easy *data)
{
/* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
combinations */
- return aprintf("------------------------%08x%08x",
- Curl_rand(data), Curl_rand(data));
+ unsigned int rnd[2];
+ CURLcode result = Curl_rand(data, &rnd[0], 2);
+ if(result)
+ return NULL;
+
+ return aprintf("------------------------%08x%08x", rnd[0], rnd[1]);
}
#else /* CURL_DISABLE_HTTP */