1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2014, 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 Curl_safefree(filebasename);
1115 return CURLE_OUT_OF_MEMORY;
1117 p0 = filename_escaped;
1120 if(*p1 == '\\' || *p1 == '"')
1125 filename = filename_escaped;
1127 result = AddFormDataf(form, size,
1128 "; filename=\"%s\"",
1130 Curl_safefree(filename_escaped);
1131 Curl_safefree(filebasename);
1136 * Curl_getformdata() converts a linked list of "meta data" into a complete
1137 * (possibly huge) multipart formdata. The input list is in 'post', while the
1138 * output resulting linked lists gets stored in '*finalform'. *sizep will get
1139 * the total size of the whole POST.
1140 * A multipart/form_data content-type is built, unless a custom content-type
1141 * is passed in 'custom_content_type'.
1143 * This function will not do a failf() for the potential memory failures but
1144 * should for all other errors it spots. Just note that this function MAY get
1145 * a NULL pointer in the 'data' argument.
1148 CURLcode Curl_getformdata(struct SessionHandle *data,
1149 struct FormData **finalform,
1150 struct curl_httppost *post,
1151 const char *custom_content_type,
1154 struct FormData *form = NULL;
1155 struct FormData *firstform;
1156 struct curl_httppost *file;
1157 CURLcode result = CURLE_OK;
1159 curl_off_t size = 0; /* support potentially ENORMOUS formposts */
1161 char *fileboundary = NULL;
1162 struct curl_slist* curList;
1164 *finalform = NULL; /* default form is empty */
1167 return result; /* no input => no output! */
1169 boundary = formboundary(data);
1171 return CURLE_OUT_OF_MEMORY;
1173 /* Make the first line of the output */
1174 result = AddFormDataf(&form, NULL,
1175 "%s; boundary=%s\r\n",
1176 custom_content_type?custom_content_type:
1177 "Content-Type: multipart/form-data",
1181 Curl_safefree(boundary);
1184 /* we DO NOT include that line in the total size of the POST, since it'll be
1185 part of the header! */
1192 result = AddFormDataf(&form, &size, "\r\n");
1198 result = AddFormDataf(&form, &size, "--%s\r\n", boundary);
1202 /* Maybe later this should be disabled when a custom_content_type is
1203 passed, since Content-Disposition is not meaningful for all multipart
1206 result = AddFormDataf(&form, &size,
1207 "Content-Disposition: form-data; name=\"");
1211 result = AddFormData(&form, FORM_DATA, post->name, post->namelength,
1216 result = AddFormDataf(&form, &size, "\"");
1221 /* If used, this is a link to more file names, we must then do
1222 the magic to include several files with the same field name */
1224 Curl_safefree(fileboundary);
1225 fileboundary = formboundary(data);
1227 result = CURLE_OUT_OF_MEMORY;
1231 result = AddFormDataf(&form, &size,
1232 "\r\nContent-Type: multipart/mixed;"
1243 /* If 'showfilename' is set, that is a faked name passed on to us
1244 to use to in the formpost. If that is not set, the actually used
1245 local file name should be added. */
1248 /* if multiple-file */
1249 result = AddFormDataf(&form, &size,
1250 "\r\n--%s\r\nContent-Disposition: "
1255 result = formdata_add_filename(file, &form, &size);
1259 else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER|
1260 HTTPPOST_CALLBACK)) {
1261 /* it should be noted that for the HTTPPOST_FILENAME and
1262 HTTPPOST_CALLBACK cases the ->showfilename struct member is always
1263 assigned at this point */
1264 if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) {
1265 result = formdata_add_filename(post, &form, &size);
1272 if(file->contenttype) {
1273 /* we have a specified type */
1274 result = AddFormDataf(&form, &size,
1275 "\r\nContent-Type: %s",
1281 curList = file->contentheader;
1283 /* Process the additional headers specified for this form */
1284 result = AddFormDataf( &form, &size, "\r\n%s", curList->data );
1287 curList = curList->next;
1292 result = AddFormDataf(&form, &size, "\r\n\r\n");
1296 if((post->flags & HTTPPOST_FILENAME) ||
1297 (post->flags & HTTPPOST_READFILE)) {
1298 /* we should include the contents from the specified file */
1301 fileread = strequal("-", file->contents)?
1302 stdin:fopen(file->contents, "rb"); /* binary read for win32 */
1305 * VMS: This only allows for stream files on VMS. Stream files are
1306 * OK, as are FIXED & VAR files WITHOUT implied CC For implied CC,
1307 * every record needs to have a \n appended & 1 added to SIZE
1311 if(fileread != stdin) {
1312 /* close the file */
1314 /* add the file name only - for later reading from this */
1315 result = AddFormData(&form, FORM_FILE, file->contents, 0, &size);
1318 /* When uploading from stdin, we can't know the size of the file,
1319 * thus must read the full file as before. We *could* use chunked
1320 * transfer-encoding, but that only works for HTTP 1.1 and we
1321 * can't be sure we work with such a server.
1325 while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
1326 result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
1334 failf(data, "couldn't open file \"%s\"", file->contents);
1336 result = CURLE_READ_ERROR;
1339 else if(post->flags & HTTPPOST_BUFFER)
1340 /* include contents of buffer */
1341 result = AddFormData(&form, FORM_CONTENT, post->buffer,
1342 post->bufferlength, &size);
1343 else if(post->flags & HTTPPOST_CALLBACK)
1344 /* the contents should be read with the callback and the size
1345 is set with the contentslength */
1346 result = AddFormData(&form, FORM_CALLBACK, post->userp,
1347 post->contentslength, &size);
1349 /* include the contents we got */
1350 result = AddFormData(&form, FORM_CONTENT, post->contents,
1351 post->contentslength, &size);
1354 } while(file && !result); /* for each specified file for this field */
1360 /* this was a multiple-file inclusion, make a termination file
1362 result = AddFormDataf(&form, &size,
1369 } while((post = post->next) != NULL); /* for each field */
1371 /* end-boundary for everything */
1372 if(CURLE_OK == result)
1373 result = AddFormDataf(&form, &size,
1378 Curl_formclean(&firstform);
1379 Curl_safefree(fileboundary);
1380 Curl_safefree(boundary);
1386 Curl_safefree(fileboundary);
1387 Curl_safefree(boundary);
1389 *finalform = firstform;
1395 * Curl_FormInit() inits the struct 'form' points to with the 'formdata'
1396 * and resets the 'sent' counter.
1398 int Curl_FormInit(struct Form *form, struct FormData *formdata )
1401 return 1; /* error */
1403 form->data = formdata;
1406 form->fread_func = ZERO_NULL;
1412 # define fopen_read fopen
1417 * For upload to work as expected on VMS, different optional
1418 * parameters must be added to the fopen command based on
1419 * record format of the file.
1422 # define fopen_read vmsfopenread
1423 static FILE * vmsfopenread(const char *file, const char *mode) {
1424 struct_stat statbuf;
1427 result = stat(file, &statbuf);
1429 switch (statbuf.st_fab_rfm) {
1433 return fopen(file, "r");
1436 return fopen(file, "r", "rfm=stmlf", "ctx=stm");
1444 * The read callback that this function may use can return a value larger than
1445 * 'size' (which then this function returns) that indicates a problem and it
1446 * must be properly dealt with
1448 static size_t readfromfile(struct Form *form, char *buffer,
1452 bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE;
1455 if(form->fread_func == ZERO_NULL)
1458 nread = form->fread_func(buffer, 1, size, form->data->line);
1462 /* this file hasn't yet been opened */
1463 form->fp = fopen_read(form->data->line, "rb"); /* b is for binary */
1465 return (size_t)-1; /* failure */
1467 nread = fread(buffer, 1, size, form->fp);
1470 /* this is the last chunk from the file, move on */
1475 form->data = form->data->next;
1482 * Curl_FormReader() is the fread() emulation function that will be used to
1483 * deliver the formdata to the transfer loop and then sent away to the peer.
1485 size_t Curl_FormReader(char *buffer,
1494 form=(struct Form *)mydata;
1496 wantedsize = size * nitems;
1499 return 0; /* nothing, error, empty */
1501 if((form->data->type == FORM_FILE) ||
1502 (form->data->type == FORM_CALLBACK)) {
1503 gotsize = readfromfile(form, buffer, wantedsize);
1506 /* If positive or -1, return. If zero, continue! */
1511 if((form->data->length - form->sent ) > wantedsize - gotsize) {
1513 memcpy(buffer + gotsize , form->data->line + form->sent,
1514 wantedsize - gotsize);
1516 form->sent += wantedsize-gotsize;
1521 memcpy(buffer+gotsize,
1522 form->data->line + form->sent,
1523 (form->data->length - form->sent) );
1524 gotsize += form->data->length - form->sent;
1528 form->data = form->data->next; /* advance */
1530 } while(form->data && (form->data->type < FORM_CALLBACK));
1531 /* If we got an empty line and we have more data, we proceed to the next
1532 line immediately to avoid returning zero before we've reached the end. */
1538 * Curl_formpostheader() returns the first line of the formpost, the
1539 * request-header part (which is not part of the request-body like the rest of
1542 char *Curl_formpostheader(void *formp, size_t *len)
1545 struct Form *form=(struct Form *)formp;
1548 return 0; /* nothing, ERROR! */
1550 header = form->data->line;
1551 *len = form->data->length;
1553 form->data = form->data->next; /* advance */
1559 * formboundary() creates a suitable boundary string and returns an allocated
1562 static char *formboundary(struct SessionHandle *data)
1564 /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
1566 return aprintf("------------------------%08x%08x",
1567 Curl_rand(data), Curl_rand(data));
1570 #else /* CURL_DISABLE_HTTP */
1571 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
1572 struct curl_httppost **last_post,
1577 return CURL_FORMADD_DISABLED;
1580 int curl_formget(struct curl_httppost *form, void *arg,
1581 curl_formget_callback append)
1586 return CURL_FORMADD_DISABLED;
1589 void curl_formfree(struct curl_httppost *form)
1592 /* does nothing HTTP is disabled */
1596 #endif /* !defined(CURL_DISABLE_HTTP) */