1
/***************************************************************************
3
* Project ___| | | | _ \| |
5
* | (__| |_| | _ <| |___
6
* \___|\___/|_| \_\_____|
8
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
10
* This software is licensed as described in the file COPYING, which
11
* you should have received as part of this distribution. The terms
12
* are also available at http://curl.haxx.se/docs/copyright.html.
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.
18
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
* KIND, either express or implied.
21
***************************************************************************/
23
#include "curl_setup.h"
25
#include <curl/curl.h>
27
#if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY)
29
#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
33
#include "urldata.h" /* for struct SessionHandle */
35
#include "vtls/vtls.h"
37
#include "curl_memory.h"
40
#define _MPRINTF_REPLACE /* use our functions only */
41
#include <curl/mprintf.h>
43
/* The last #include file should be: */
46
#endif /* !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) */
48
#ifndef CURL_DISABLE_HTTP
51
static char *Curl_basename(char *path);
52
#define basename(x) Curl_basename((x))
55
static size_t readfromfile(struct Form *form, char *buffer, size_t size);
56
static char *formboundary(struct SessionHandle *data);
58
/* What kind of Content-Type to use on un-specified files with unrecognized
60
#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
62
#define FORM_FILE_SEPARATOR ','
63
#define FORM_TYPE_SEPARATOR ';'
65
/***************************************************************************
69
* Adds a HttpPost structure to the list, if parent_post is given becomes
70
* a subpost of parent_post instead of a direct list element.
72
* Returns newly allocated HttpPost on success and NULL if malloc failed.
74
***************************************************************************/
75
static struct curl_httppost *
76
AddHttpPost(char *name, size_t namelength,
77
char *value, size_t contentslength,
78
char *buffer, size_t bufferlength,
81
struct curl_slist* contentHeader,
82
char *showfilename, char *userp,
83
struct curl_httppost *parent_post,
84
struct curl_httppost **httppost,
85
struct curl_httppost **last_post)
87
struct curl_httppost *post;
88
post = calloc(1, sizeof(struct curl_httppost));
91
post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
92
post->contents = value;
93
post->contentslength = (long)contentslength;
94
post->buffer = buffer;
95
post->bufferlength = (long)bufferlength;
96
post->contenttype = contenttype;
97
post->contentheader = contentHeader;
98
post->showfilename = showfilename;
106
/* now, point our 'more' to the original 'more' */
107
post->more = parent_post->more;
109
/* then move the original 'more' to point to ourselves */
110
parent_post->more = post;
113
/* make the previous point to this */
115
(*last_post)->next = post;
124
/***************************************************************************
128
* Adds a FormInfo structure to the list presented by parent_form_info.
130
* Returns newly allocated FormInfo on success and NULL if malloc failed/
131
* parent_form_info is NULL.
133
***************************************************************************/
134
static FormInfo * AddFormInfo(char *value,
136
FormInfo *parent_form_info)
139
form_info = calloc(1, sizeof(struct FormInfo));
142
form_info->value = value;
144
form_info->contenttype = contenttype;
145
form_info->flags = HTTPPOST_FILENAME;
150
if(parent_form_info) {
151
/* now, point our 'more' to the original 'more' */
152
form_info->more = parent_form_info->more;
154
/* then move the original 'more' to point to ourselves */
155
parent_form_info->more = form_info;
161
/***************************************************************************
163
* ContentTypeForFilename()
165
* Provides content type for filename if one of the known types (else
166
* (either the prevtype or the default is returned).
168
* Returns some valid contenttype for filename.
170
***************************************************************************/
171
static const char *ContentTypeForFilename(const char *filename,
172
const char *prevtype)
174
const char *contenttype = NULL;
177
* No type was specified, we scan through a few well-known
178
* extensions and pick the first we match!
181
const char *extension;
184
static const struct ContentType ctts[]={
185
{".gif", "image/gif"},
186
{".jpg", "image/jpeg"},
187
{".jpeg", "image/jpeg"},
188
{".txt", "text/plain"},
189
{".html", "text/html"},
190
{".xml", "application/xml"}
194
/* default to the previously set/used! */
195
contenttype = prevtype;
197
contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
199
if(filename) { /* in case a NULL was passed in */
200
for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
201
if(strlen(filename) >= strlen(ctts[i].extension)) {
202
if(strequal(filename +
203
strlen(filename) - strlen(ctts[i].extension),
204
ctts[i].extension)) {
205
contenttype = ctts[i].type;
211
/* we have a contenttype by now */
215
/***************************************************************************
219
* Copies the 'source' data to a newly allocated buffer buffer (that is
220
* returned). Uses buffer_length if not null, else uses strlen to determine
221
* the length of the buffer to be copied
223
* Returns the new pointer or NULL on failure.
225
***************************************************************************/
226
static char *memdup(const char *src, size_t buffer_length)
233
length = buffer_length;
235
length = strlen(src);
239
/* no length and a NULL src pointer! */
242
buffer = malloc(length+add);
244
return NULL; /* fail */
246
memcpy(buffer, src, length);
248
/* if length unknown do null termination */
250
buffer[length] = '\0';
255
/***************************************************************************
259
* Stores a formpost parameter and builds the appropriate linked list.
261
* Has two principal functionalities: using files and byte arrays as
262
* post parts. Byte arrays are either copied or just the pointer is stored
263
* (as the user requests) while for files only the filename and not the
266
* While you may have only one byte array for each name, multiple filenames
267
* are allowed (and because of this feature CURLFORM_END is needed after
268
* using CURLFORM_FILE).
272
* Simple name/value pair with copied contents:
273
* curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
274
* CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
276
* name/value pair where only the content pointer is remembered:
277
* curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
278
* CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END);
279
* (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
281
* storing a filename (CONTENTTYPE is optional!):
282
* curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
283
* CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text",
286
* storing multiple filenames:
287
* curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
288
* CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
291
* CURL_FORMADD_OK on success
292
* CURL_FORMADD_MEMORY if the FormInfo allocation fails
293
* CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
294
* CURL_FORMADD_NULL if a null pointer was given for a char
295
* CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
296
* CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
297
* CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
298
* CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated
299
* CURL_FORMADD_MEMORY if some allocation for string copying failed.
300
* CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
302
***************************************************************************/
305
CURLFORMcode FormAdd(struct curl_httppost **httppost,
306
struct curl_httppost **last_post,
309
FormInfo *first_form, *current_form, *form = NULL;
310
CURLFORMcode return_value = CURL_FORMADD_OK;
311
const char *prevtype = NULL;
312
struct curl_httppost *post = NULL;
313
CURLformoption option;
314
struct curl_forms *forms = NULL;
315
char *array_value=NULL; /* value read from an array */
317
/* This is a state variable, that if TRUE means that we're parsing an
318
array that we got passed to us. If FALSE we're parsing the input
319
va_list arguments. */
320
bool array_state = FALSE;
323
* We need to allocate the first struct to fill in.
325
first_form = calloc(1, sizeof(struct FormInfo));
327
return CURL_FORMADD_MEMORY;
329
current_form = first_form;
332
* Loop through all the options set. Break if we have an error to report.
334
while(return_value == CURL_FORMADD_OK) {
336
/* first see if we have more parts of the array param */
337
if(array_state && forms) {
338
/* get the upcoming option from the given array */
339
option = forms->option;
340
array_value = (char *)forms->value;
342
forms++; /* advance this to next entry */
343
if(CURLFORM_END == option) {
344
/* end of array state */
350
/* This is not array-state, get next option */
351
option = va_arg(params, CURLformoption);
352
if(CURLFORM_END == option)
359
/* we don't support an array from within an array */
360
return_value = CURL_FORMADD_ILLEGAL_ARRAY;
362
forms = va_arg(params, struct curl_forms *);
366
return_value = CURL_FORMADD_NULL;
371
* Set the Name property.
373
case CURLFORM_PTRNAME:
374
#ifdef CURL_DOES_CONVERSIONS
375
/* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy
376
* the data in all cases so that we'll have safe memory for the eventual
380
current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
382
case CURLFORM_COPYNAME:
383
if(current_form->name)
384
return_value = CURL_FORMADD_OPTION_TWICE;
386
char *name = array_state?
387
array_value:va_arg(params, char *);
389
current_form->name = name; /* store for the moment */
391
return_value = CURL_FORMADD_NULL;
394
case CURLFORM_NAMELENGTH:
395
if(current_form->namelength)
396
return_value = CURL_FORMADD_OPTION_TWICE;
398
current_form->namelength =
399
array_state?(size_t)array_value:(size_t)va_arg(params, long);
403
* Set the contents property.
405
case CURLFORM_PTRCONTENTS:
406
current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
407
case CURLFORM_COPYCONTENTS:
408
if(current_form->value)
409
return_value = CURL_FORMADD_OPTION_TWICE;
412
array_state?array_value:va_arg(params, char *);
414
current_form->value = value; /* store for the moment */
416
return_value = CURL_FORMADD_NULL;
419
case CURLFORM_CONTENTSLENGTH:
420
if(current_form->contentslength)
421
return_value = CURL_FORMADD_OPTION_TWICE;
423
current_form->contentslength =
424
array_state?(size_t)array_value:(size_t)va_arg(params, long);
427
/* Get contents from a given file name */
428
case CURLFORM_FILECONTENT:
429
if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
430
return_value = CURL_FORMADD_OPTION_TWICE;
432
const char *filename = array_state?
433
array_value:va_arg(params, char *);
435
current_form->value = strdup(filename);
436
if(!current_form->value)
437
return_value = CURL_FORMADD_MEMORY;
439
current_form->flags |= HTTPPOST_READFILE;
440
current_form->value_alloc = TRUE;
444
return_value = CURL_FORMADD_NULL;
448
/* We upload a file */
451
const char *filename = array_state?array_value:
452
va_arg(params, char *);
454
if(current_form->value) {
455
if(current_form->flags & HTTPPOST_FILENAME) {
457
char *fname = strdup(filename);
459
return_value = CURL_FORMADD_MEMORY;
461
form = AddFormInfo(fname, NULL, current_form);
463
Curl_safefree(fname);
464
return_value = CURL_FORMADD_MEMORY;
467
form->value_alloc = TRUE;
474
return_value = CURL_FORMADD_NULL;
477
return_value = CURL_FORMADD_OPTION_TWICE;
481
current_form->value = strdup(filename);
482
if(!current_form->value)
483
return_value = CURL_FORMADD_MEMORY;
485
current_form->flags |= HTTPPOST_FILENAME;
486
current_form->value_alloc = TRUE;
490
return_value = CURL_FORMADD_NULL;
495
case CURLFORM_BUFFERPTR:
496
current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
497
if(current_form->buffer)
498
return_value = CURL_FORMADD_OPTION_TWICE;
501
array_state?array_value:va_arg(params, char *);
503
current_form->buffer = buffer; /* store for the moment */
504
current_form->value = buffer; /* make it non-NULL to be accepted
508
return_value = CURL_FORMADD_NULL;
512
case CURLFORM_BUFFERLENGTH:
513
if(current_form->bufferlength)
514
return_value = CURL_FORMADD_OPTION_TWICE;
516
current_form->bufferlength =
517
array_state?(size_t)array_value:(size_t)va_arg(params, long);
520
case CURLFORM_STREAM:
521
current_form->flags |= HTTPPOST_CALLBACK;
522
if(current_form->userp)
523
return_value = CURL_FORMADD_OPTION_TWICE;
526
array_state?array_value:va_arg(params, char *);
528
current_form->userp = userp;
529
current_form->value = userp; /* this isn't strictly true but we
530
derive a value from this later on
531
and we need this non-NULL to be
532
accepted as a fine form part */
535
return_value = CURL_FORMADD_NULL;
539
case CURLFORM_CONTENTTYPE:
541
const char *contenttype =
542
array_state?array_value:va_arg(params, char *);
543
if(current_form->contenttype) {
544
if(current_form->flags & HTTPPOST_FILENAME) {
546
char *type = strdup(contenttype);
548
return_value = CURL_FORMADD_MEMORY;
550
form = AddFormInfo(NULL, type, current_form);
553
return_value = CURL_FORMADD_MEMORY;
556
form->contenttype_alloc = TRUE;
563
return_value = CURL_FORMADD_NULL;
566
return_value = CURL_FORMADD_OPTION_TWICE;
570
current_form->contenttype = strdup(contenttype);
571
if(!current_form->contenttype)
572
return_value = CURL_FORMADD_MEMORY;
574
current_form->contenttype_alloc = TRUE;
577
return_value = CURL_FORMADD_NULL;
581
case CURLFORM_CONTENTHEADER:
583
/* this "cast increases required alignment of target type" but
584
we consider it OK anyway */
585
struct curl_slist* list = array_state?
586
(struct curl_slist*)array_value:
587
va_arg(params, struct curl_slist*);
589
if(current_form->contentheader)
590
return_value = CURL_FORMADD_OPTION_TWICE;
592
current_form->contentheader = list;
596
case CURLFORM_FILENAME:
597
case CURLFORM_BUFFER:
599
const char *filename = array_state?array_value:
600
va_arg(params, char *);
601
if(current_form->showfilename)
602
return_value = CURL_FORMADD_OPTION_TWICE;
604
current_form->showfilename = strdup(filename);
605
if(!current_form->showfilename)
606
return_value = CURL_FORMADD_MEMORY;
608
current_form->showfilename_alloc = TRUE;
613
return_value = CURL_FORMADD_UNKNOWN_OPTION;
618
if(CURL_FORMADD_OK != return_value) {
619
/* On error, free allocated fields for all nodes of the FormInfo linked
620
list without deallocating nodes. List nodes are deallocated later on */
622
for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
623
if(ptr->name_alloc) {
624
Curl_safefree(ptr->name);
625
ptr->name_alloc = FALSE;
627
if(ptr->value_alloc) {
628
Curl_safefree(ptr->value);
629
ptr->value_alloc = FALSE;
631
if(ptr->contenttype_alloc) {
632
Curl_safefree(ptr->contenttype);
633
ptr->contenttype_alloc = FALSE;
635
if(ptr->showfilename_alloc) {
636
Curl_safefree(ptr->showfilename);
637
ptr->showfilename_alloc = FALSE;
642
if(CURL_FORMADD_OK == return_value) {
643
/* go through the list, check for completeness and if everything is
644
* alright add the HttpPost item otherwise set return_value accordingly */
647
for(form = first_form;
650
if(((!form->name || !form->value) && !post) ||
651
( (form->contentslength) &&
652
(form->flags & HTTPPOST_FILENAME) ) ||
653
( (form->flags & HTTPPOST_FILENAME) &&
654
(form->flags & HTTPPOST_PTRCONTENTS) ) ||
657
(form->flags & HTTPPOST_BUFFER) &&
658
(form->flags & HTTPPOST_PTRBUFFER) ) ||
660
( (form->flags & HTTPPOST_READFILE) &&
661
(form->flags & HTTPPOST_PTRCONTENTS) )
663
return_value = CURL_FORMADD_INCOMPLETE;
667
if(((form->flags & HTTPPOST_FILENAME) ||
668
(form->flags & HTTPPOST_BUFFER)) &&
669
!form->contenttype ) {
670
char *f = form->flags & HTTPPOST_BUFFER?
671
form->showfilename : form->value;
673
/* our contenttype is missing */
674
form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
675
if(!form->contenttype) {
676
return_value = CURL_FORMADD_MEMORY;
679
form->contenttype_alloc = TRUE;
681
if(!(form->flags & HTTPPOST_PTRNAME) &&
682
(form == first_form) ) {
683
/* Note that there's small risk that form->name is NULL here if the
684
app passed in a bad combo, so we better check for that first. */
686
/* copy name (without strdup; possibly contains null characters) */
687
form->name = memdup(form->name, form->namelength);
689
return_value = CURL_FORMADD_MEMORY;
692
form->name_alloc = TRUE;
694
if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
695
HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
696
HTTPPOST_CALLBACK)) ) {
697
/* copy value (without strdup; possibly contains null characters) */
698
form->value = memdup(form->value, form->contentslength);
700
return_value = CURL_FORMADD_MEMORY;
703
form->value_alloc = TRUE;
705
post = AddHttpPost(form->name, form->namelength,
706
form->value, form->contentslength,
707
form->buffer, form->bufferlength,
708
form->contenttype, form->flags,
709
form->contentheader, form->showfilename,
715
return_value = CURL_FORMADD_MEMORY;
719
if(form->contenttype)
720
prevtype = form->contenttype;
723
if(CURL_FORMADD_OK != return_value) {
724
/* On error, free allocated fields for nodes of the FormInfo linked
725
list which are not already owned by the httppost linked list
726
without deallocating nodes. List nodes are deallocated later on */
728
for(ptr = form; ptr != NULL; ptr = ptr->more) {
729
if(ptr->name_alloc) {
730
Curl_safefree(ptr->name);
731
ptr->name_alloc = FALSE;
733
if(ptr->value_alloc) {
734
Curl_safefree(ptr->value);
735
ptr->value_alloc = FALSE;
737
if(ptr->contenttype_alloc) {
738
Curl_safefree(ptr->contenttype);
739
ptr->contenttype_alloc = FALSE;
741
if(ptr->showfilename_alloc) {
742
Curl_safefree(ptr->showfilename);
743
ptr->showfilename_alloc = FALSE;
749
/* Always deallocate FormInfo linked list nodes without touching node
750
fields given that these have either been deallocated or are owned
751
now by the httppost linked list */
753
FormInfo *ptr = first_form->more;
754
Curl_safefree(first_form);
762
* curl_formadd() is a public API to add a section to the multipart formpost.
767
CURLFORMcode curl_formadd(struct curl_httppost **httppost,
768
struct curl_httppost **last_post,
773
va_start(arg, last_post);
774
result = FormAdd(httppost, last_post, arg);
782
* get_vms_file_size does what it takes to get the real size of the file
784
* For fixed files, find out the size of the EOF block and adjust.
786
* For all others, have to read the entire file in, discarding the contents.
787
* Most posted text files will be small, and binary files like zlib archives
788
* and CD/DVD images should be either a STREAM_LF format or a fixed format.
791
curl_off_t VmsRealFileSize(const char * name,
792
const struct_stat * stat_buf)
799
file = fopen(name, "r");
805
while(ret_stat > 0) {
806
ret_stat = fread(buffer, 1, sizeof(buffer), file);
817
* VmsSpecialSize checks to see if the stat st_size can be trusted and
818
* if not to call a routine to get the correct size.
821
static curl_off_t VmsSpecialSize(const char * name,
822
const struct_stat * stat_buf)
824
switch(stat_buf->st_fab_rfm) {
827
return VmsRealFileSize(name, stat_buf);
830
return stat_buf->st_size;
837
#define filesize(name, stat_data) (stat_data.st_size)
839
/* Getting the expected file size needs help on VMS */
840
#define filesize(name, stat_data) VmsSpecialSize(name, &stat_data)
844
* AddFormData() adds a chunk of data to the FormData linked list.
846
* size is incremented by the chunk length, unless it is NULL
848
static CURLcode AddFormData(struct FormData **formp,
854
struct FormData *newform = malloc(sizeof(struct FormData));
856
return CURLE_OUT_OF_MEMORY;
857
newform->next = NULL;
859
if(type <= FORM_CONTENT) {
860
/* we make it easier for plain strings: */
862
length = strlen((char *)line);
864
newform->line = malloc(length+1);
867
return CURLE_OUT_OF_MEMORY;
869
memcpy(newform->line, line, length);
870
newform->length = length;
871
newform->line[length]=0; /* zero terminate for easier debugging */
874
/* For callbacks and files we don't have any actual data so we just keep a
875
pointer to whatever this points to */
876
newform->line = (char *)line;
878
newform->type = type;
881
(*formp)->next = newform;
888
if(type != FORM_FILE)
889
/* for static content as well as callback data we add the size given
893
/* Since this is a file to be uploaded here, add the size of the actual
895
if(!strequal("-", newform->line)) {
897
if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
898
*size += filesize(newform->line, file);
900
return CURLE_BAD_FUNCTION_ARGUMENT;
908
* AddFormDataf() adds printf()-style formatted data to the formdata chain.
911
static CURLcode AddFormDataf(struct FormData **formp,
913
const char *fmt, ...)
918
vsnprintf(s, sizeof(s), fmt, ap);
921
return AddFormData(formp, FORM_DATA, s, 0, size);
925
* Curl_formclean() is used from http.c, this cleans a built FormData linked
928
void Curl_formclean(struct FormData **form_ptr)
930
struct FormData *next, *form;
937
next=form->next; /* the following form line */
938
if(form->type <= FORM_CONTENT)
939
free(form->line); /* free the line */
940
free(form); /* free the struct */
942
} while((form = next) != NULL); /* continue */
949
* Serialize a curl_httppost struct.
950
* Returns 0 on success.
954
int curl_formget(struct curl_httppost *form, void *arg,
955
curl_formget_callback append)
959
struct FormData *data, *ptr;
961
rc = Curl_getformdata(NULL, &data, form, NULL, &size);
965
for(ptr = data; ptr; ptr = ptr->next) {
966
if((ptr->type == FORM_FILE) || (ptr->type == FORM_CALLBACK)) {
971
Curl_FormInit(&temp, ptr);
974
nread = readfromfile(&temp, buffer, sizeof(buffer));
975
if((nread == (size_t) -1) ||
976
(nread > sizeof(buffer)) ||
977
(nread != append(arg, buffer, nread))) {
980
Curl_formclean(&data);
986
if(ptr->length != append(arg, ptr->line, ptr->length)) {
987
Curl_formclean(&data);
992
Curl_formclean(&data);
997
* curl_formfree() is an external function to free up a whole form post
1000
void curl_formfree(struct curl_httppost *form)
1002
struct curl_httppost *next;
1005
/* no form to free, just get out of this */
1009
next=form->next; /* the following form line */
1011
/* recurse to sub-contents */
1013
curl_formfree(form->more);
1015
if(!(form->flags & HTTPPOST_PTRNAME) && form->name)
1016
free(form->name); /* free the name */
1018
(HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) &&
1020
free(form->contents); /* free the contents */
1021
if(form->contenttype)
1022
free(form->contenttype); /* free the content type */
1023
if(form->showfilename)
1024
free(form->showfilename); /* free the faked file name */
1025
free(form); /* free the struct */
1027
} while((form = next) != NULL); /* continue */
1030
#ifndef HAVE_BASENAME
1032
(Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
1035
The basename() function shall take the pathname pointed to by path and
1036
return a pointer to the final component of the pathname, deleting any
1037
trailing '/' characters.
1039
If the string pointed to by path consists entirely of the '/' character,
1040
basename() shall return a pointer to the string "/". If the string pointed
1041
to by path is exactly "//", it is implementation-defined whether '/' or "//"
1044
If path is a null pointer or points to an empty string, basename() shall
1045
return a pointer to the string ".".
1047
The basename() function may modify the string pointed to by path, and may
1048
return a pointer to static storage that may then be overwritten by a
1049
subsequent call to basename().
1051
The basename() function need not be reentrant. A function that is not
1052
required to be reentrant is not required to be thread-safe.
1055
static char *Curl_basename(char *path)
1057
/* Ignore all the details above for now and make a quick and simple
1058
implementaion here */
1062
s1=strrchr(path, '/');
1063
s2=strrchr(path, '\\');
1066
path = (s1 > s2? s1 : s2)+1;
1077
static char *strippath(const char *fullfile)
1081
filename = strdup(fullfile); /* duplicate since basename() may ruin the
1082
buffer it works on */
1085
base = strdup(basename(filename));
1087
free(filename); /* free temporary buffer */
1089
return base; /* returns an allocated string or NULL ! */
1092
static CURLcode formdata_add_filename(const struct curl_httppost *file,
1093
struct FormData **form,
1096
CURLcode result = CURLE_OK;
1097
char *filename = file->showfilename;
1098
char *filebasename = NULL;
1099
char *filename_escaped = NULL;
1102
filebasename = strippath(file->contents);
1104
return CURLE_OUT_OF_MEMORY;
1105
filename = filebasename;
1108
if(strchr(filename, '\\') || strchr(filename, '"')) {
1111
/* filename need be escaped */
1112
filename_escaped = malloc(strlen(filename)*2+1);
1113
if(!filename_escaped)
1114
return CURLE_OUT_OF_MEMORY;
1115
p0 = filename_escaped;
1118
if(*p1 == '\\' || *p1 == '"')
1123
filename = filename_escaped;
1125
result = AddFormDataf(form, size,
1126
"; filename=\"%s\"",
1128
Curl_safefree(filename_escaped);
1129
Curl_safefree(filebasename);
1134
* Curl_getformdata() converts a linked list of "meta data" into a complete
1135
* (possibly huge) multipart formdata. The input list is in 'post', while the
1136
* output resulting linked lists gets stored in '*finalform'. *sizep will get
1137
* the total size of the whole POST.
1138
* A multipart/form_data content-type is built, unless a custom content-type
1139
* is passed in 'custom_content_type'.
1141
* This function will not do a failf() for the potential memory failures but
1142
* should for all other errors it spots. Just note that this function MAY get
1143
* a NULL pointer in the 'data' argument.
1146
CURLcode Curl_getformdata(struct SessionHandle *data,
1147
struct FormData **finalform,
1148
struct curl_httppost *post,
1149
const char *custom_content_type,
1152
struct FormData *form = NULL;
1153
struct FormData *firstform;
1154
struct curl_httppost *file;
1155
CURLcode result = CURLE_OK;
1157
curl_off_t size = 0; /* support potentially ENORMOUS formposts */
1159
char *fileboundary = NULL;
1160
struct curl_slist* curList;
1162
*finalform = NULL; /* default form is empty */
1165
return result; /* no input => no output! */
1167
boundary = formboundary(data);
1169
return CURLE_OUT_OF_MEMORY;
1171
/* Make the first line of the output */
1172
result = AddFormDataf(&form, NULL,
1173
"%s; boundary=%s\r\n",
1174
custom_content_type?custom_content_type:
1175
"Content-Type: multipart/form-data",
1179
Curl_safefree(boundary);
1182
/* we DO NOT include that line in the total size of the POST, since it'll be
1183
part of the header! */
1190
result = AddFormDataf(&form, &size, "\r\n");
1196
result = AddFormDataf(&form, &size, "--%s\r\n", boundary);
1200
/* Maybe later this should be disabled when a custom_content_type is
1201
passed, since Content-Disposition is not meaningful for all multipart
1204
result = AddFormDataf(&form, &size,
1205
"Content-Disposition: form-data; name=\"");
1209
result = AddFormData(&form, FORM_DATA, post->name, post->namelength,
1214
result = AddFormDataf(&form, &size, "\"");
1219
/* If used, this is a link to more file names, we must then do
1220
the magic to include several files with the same field name */
1222
Curl_safefree(fileboundary);
1223
fileboundary = formboundary(data);
1225
result = CURLE_OUT_OF_MEMORY;
1229
result = AddFormDataf(&form, &size,
1230
"\r\nContent-Type: multipart/mixed,"
1241
/* If 'showfilename' is set, that is a faked name passed on to us
1242
to use to in the formpost. If that is not set, the actually used
1243
local file name should be added. */
1246
/* if multiple-file */
1247
result = AddFormDataf(&form, &size,
1248
"\r\n--%s\r\nContent-Disposition: "
1253
result = formdata_add_filename(file, &form, &size);
1257
else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER|
1258
HTTPPOST_CALLBACK)) {
1259
/* it should be noted that for the HTTPPOST_FILENAME and
1260
HTTPPOST_CALLBACK cases the ->showfilename struct member is always
1261
assigned at this point */
1262
if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) {
1263
result = formdata_add_filename(post, &form, &size);
1270
if(file->contenttype) {
1271
/* we have a specified type */
1272
result = AddFormDataf(&form, &size,
1273
"\r\nContent-Type: %s",
1279
curList = file->contentheader;
1281
/* Process the additional headers specified for this form */
1282
result = AddFormDataf( &form, &size, "\r\n%s", curList->data );
1285
curList = curList->next;
1290
result = AddFormDataf(&form, &size, "\r\n\r\n");
1294
if((post->flags & HTTPPOST_FILENAME) ||
1295
(post->flags & HTTPPOST_READFILE)) {
1296
/* we should include the contents from the specified file */
1299
fileread = strequal("-", file->contents)?
1300
stdin:fopen(file->contents, "rb"); /* binary read for win32 */
1303
* VMS: This only allows for stream files on VMS. Stream files are
1304
* OK, as are FIXED & VAR files WITHOUT implied CC For implied CC,
1305
* every record needs to have a \n appended & 1 added to SIZE
1309
if(fileread != stdin) {
1310
/* close the file */
1312
/* add the file name only - for later reading from this */
1313
result = AddFormData(&form, FORM_FILE, file->contents, 0, &size);
1316
/* When uploading from stdin, we can't know the size of the file,
1317
* thus must read the full file as before. We *could* use chunked
1318
* transfer-encoding, but that only works for HTTP 1.1 and we
1319
* can't be sure we work with such a server.
1323
while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
1324
result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
1332
failf(data, "couldn't open file \"%s\"", file->contents);
1334
result = CURLE_READ_ERROR;
1337
else if(post->flags & HTTPPOST_BUFFER)
1338
/* include contents of buffer */
1339
result = AddFormData(&form, FORM_CONTENT, post->buffer,
1340
post->bufferlength, &size);
1341
else if(post->flags & HTTPPOST_CALLBACK)
1342
/* the contents should be read with the callback and the size
1343
is set with the contentslength */
1344
result = AddFormData(&form, FORM_CALLBACK, post->userp,
1345
post->contentslength, &size);
1347
/* include the contents we got */
1348
result = AddFormData(&form, FORM_CONTENT, post->contents,
1349
post->contentslength, &size);
1352
} while(file && !result); /* for each specified file for this field */
1358
/* this was a multiple-file inclusion, make a termination file
1360
result = AddFormDataf(&form, &size,
1367
} while((post = post->next) != NULL); /* for each field */
1369
/* end-boundary for everything */
1370
if(CURLE_OK == result)
1371
result = AddFormDataf(&form, &size,
1376
Curl_formclean(&firstform);
1377
Curl_safefree(fileboundary);
1378
Curl_safefree(boundary);
1384
Curl_safefree(fileboundary);
1385
Curl_safefree(boundary);
1387
*finalform = firstform;
1393
* Curl_FormInit() inits the struct 'form' points to with the 'formdata'
1394
* and resets the 'sent' counter.
1396
int Curl_FormInit(struct Form *form, struct FormData *formdata )
1399
return 1; /* error */
1401
form->data = formdata;
1404
form->fread_func = ZERO_NULL;
1410
# define fopen_read fopen
1415
* For upload to work as expected on VMS, different optional
1416
* parameters must be added to the fopen command based on
1417
* record format of the file.
1420
# define fopen_read vmsfopenread
1421
static FILE * vmsfopenread(const char *file, const char *mode) {
1422
struct_stat statbuf;
1425
result = stat(file, &statbuf);
1427
switch (statbuf.st_fab_rfm) {
1431
return fopen(file, "r");
1434
return fopen(file, "r", "rfm=stmlf", "ctx=stm");
1442
* The read callback that this function may use can return a value larger than
1443
* 'size' (which then this function returns) that indicates a problem and it
1444
* must be properly dealt with
1446
static size_t readfromfile(struct Form *form, char *buffer,
1450
bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE;
1453
if(form->fread_func == ZERO_NULL)
1456
nread = form->fread_func(buffer, 1, size, form->data->line);
1460
/* this file hasn't yet been opened */
1461
form->fp = fopen_read(form->data->line, "rb"); /* b is for binary */
1463
return (size_t)-1; /* failure */
1465
nread = fread(buffer, 1, size, form->fp);
1468
/* this is the last chunk from the file, move on */
1473
form->data = form->data->next;
1480
* Curl_FormReader() is the fread() emulation function that will be used to
1481
* deliver the formdata to the transfer loop and then sent away to the peer.
1483
size_t Curl_FormReader(char *buffer,
1492
form=(struct Form *)mydata;
1494
wantedsize = size * nitems;
1497
return 0; /* nothing, error, empty */
1499
if((form->data->type == FORM_FILE) ||
1500
(form->data->type == FORM_CALLBACK)) {
1501
gotsize = readfromfile(form, buffer, wantedsize);
1504
/* If positive or -1, return. If zero, continue! */
1509
if((form->data->length - form->sent ) > wantedsize - gotsize) {
1511
memcpy(buffer + gotsize , form->data->line + form->sent,
1512
wantedsize - gotsize);
1514
form->sent += wantedsize-gotsize;
1519
memcpy(buffer+gotsize,
1520
form->data->line + form->sent,
1521
(form->data->length - form->sent) );
1522
gotsize += form->data->length - form->sent;
1526
form->data = form->data->next; /* advance */
1528
} while(form->data && (form->data->type < FORM_CALLBACK));
1529
/* If we got an empty line and we have more data, we proceed to the next
1530
line immediately to avoid returning zero before we've reached the end. */
1536
* Curl_formpostheader() returns the first line of the formpost, the
1537
* request-header part (which is not part of the request-body like the rest of
1540
char *Curl_formpostheader(void *formp, size_t *len)
1543
struct Form *form=(struct Form *)formp;
1546
return 0; /* nothing, ERROR! */
1548
header = form->data->line;
1549
*len = form->data->length;
1551
form->data = form->data->next; /* advance */
1557
* formboundary() creates a suitable boundary string and returns an allocated
1560
static char *formboundary(struct SessionHandle *data)
1562
/* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
1564
return aprintf("------------------------%08x%08x",
1565
Curl_rand(data), Curl_rand(data));
1568
#else /* CURL_DISABLE_HTTP */
1569
CURLFORMcode curl_formadd(struct curl_httppost **httppost,
1570
struct curl_httppost **last_post,
1575
return CURL_FORMADD_DISABLED;
1578
int curl_formget(struct curl_httppost *form, void *arg,
1579
curl_formget_callback append)
1584
return CURL_FORMADD_DISABLED;
1587
void curl_formfree(struct curl_httppost *form)
1590
/* does nothing HTTP is disabled */
1594
#endif /* !defined(CURL_DISABLE_HTTP) */