1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2016, 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 https://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 #ifndef CURL_DISABLE_HTTP
29 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
33 #include "urldata.h" /* for struct Curl_easy */
35 #include "vtls/vtls.h"
39 /* The last 3 #include files should be in this order */
40 #include "curl_printf.h"
41 #include "curl_memory.h"
45 static char *Curl_basename(char *path);
46 #define basename(x) Curl_basename((x))
49 static size_t readfromfile(struct Form *form, char *buffer, size_t size);
50 static char *formboundary(struct Curl_easy *data);
52 /* What kind of Content-Type to use on un-specified files with unrecognized
54 #define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
56 #define FORM_FILE_SEPARATOR ','
57 #define FORM_TYPE_SEPARATOR ';'
59 #define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
60 #define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
61 #define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
62 #define HTTPPOST_READFILE CURL_HTTPPOST_READFILE
63 #define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER
64 #define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK
65 #define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER
67 /***************************************************************************
71 * Adds a HttpPost structure to the list, if parent_post is given becomes
72 * a subpost of parent_post instead of a direct list element.
74 * Returns newly allocated HttpPost on success and NULL if malloc failed.
76 ***************************************************************************/
77 static struct curl_httppost *
78 AddHttpPost(char *name, size_t namelength,
79 char *value, curl_off_t contentslength,
80 char *buffer, size_t bufferlength,
83 struct curl_slist* contentHeader,
84 char *showfilename, char *userp,
85 struct curl_httppost *parent_post,
86 struct curl_httppost **httppost,
87 struct curl_httppost **last_post)
89 struct curl_httppost *post;
90 post = calloc(1, sizeof(struct curl_httppost));
93 post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
94 post->contents = value;
95 post->contentlen = contentslength;
96 post->buffer = buffer;
97 post->bufferlength = (long)bufferlength;
98 post->contenttype = contenttype;
99 post->contentheader = contentHeader;
100 post->showfilename = showfilename;
102 post->flags = flags | CURL_HTTPPOST_LARGE;
108 /* now, point our 'more' to the original 'more' */
109 post->more = parent_post->more;
111 /* then move the original 'more' to point to ourselves */
112 parent_post->more = post;
115 /* make the previous point to this */
117 (*last_post)->next = post;
126 /***************************************************************************
130 * Adds a FormInfo structure to the list presented by parent_form_info.
132 * Returns newly allocated FormInfo on success and NULL if malloc failed/
133 * parent_form_info is NULL.
135 ***************************************************************************/
136 static FormInfo * AddFormInfo(char *value,
138 FormInfo *parent_form_info)
141 form_info = calloc(1, sizeof(struct FormInfo));
144 form_info->value = value;
146 form_info->contenttype = contenttype;
147 form_info->flags = HTTPPOST_FILENAME;
152 if(parent_form_info) {
153 /* now, point our 'more' to the original 'more' */
154 form_info->more = parent_form_info->more;
156 /* then move the original 'more' to point to ourselves */
157 parent_form_info->more = form_info;
163 /***************************************************************************
165 * ContentTypeForFilename()
167 * Provides content type for filename if one of the known types (else
168 * (either the prevtype or the default is returned).
170 * Returns some valid contenttype for filename.
172 ***************************************************************************/
173 static const char *ContentTypeForFilename(const char *filename,
174 const char *prevtype)
176 const char *contenttype = NULL;
179 * No type was specified, we scan through a few well-known
180 * extensions and pick the first we match!
183 const char *extension;
186 static const struct ContentType ctts[]={
187 {".gif", "image/gif"},
188 {".jpg", "image/jpeg"},
189 {".jpeg", "image/jpeg"},
190 {".txt", "text/plain"},
191 {".html", "text/html"},
192 {".xml", "application/xml"}
196 /* default to the previously set/used! */
197 contenttype = prevtype;
199 contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
201 if(filename) { /* in case a NULL was passed in */
202 for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
203 if(strlen(filename) >= strlen(ctts[i].extension)) {
204 if(strequal(filename +
205 strlen(filename) - strlen(ctts[i].extension),
206 ctts[i].extension)) {
207 contenttype = ctts[i].type;
213 /* we have a contenttype by now */
217 /***************************************************************************
221 * Stores a formpost parameter and builds the appropriate linked list.
223 * Has two principal functionalities: using files and byte arrays as
224 * post parts. Byte arrays are either copied or just the pointer is stored
225 * (as the user requests) while for files only the filename and not the
228 * While you may have only one byte array for each name, multiple filenames
229 * are allowed (and because of this feature CURLFORM_END is needed after
230 * using CURLFORM_FILE).
234 * Simple name/value pair with copied contents:
235 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
236 * CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
238 * name/value pair where only the content pointer is remembered:
239 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
240 * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END);
241 * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
243 * storing a filename (CONTENTTYPE is optional!):
244 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
245 * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text",
248 * storing multiple filenames:
249 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
250 * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
253 * CURL_FORMADD_OK on success
254 * CURL_FORMADD_MEMORY if the FormInfo allocation fails
255 * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
256 * CURL_FORMADD_NULL if a null pointer was given for a char
257 * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
258 * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
259 * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
260 * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated
261 * CURL_FORMADD_MEMORY if some allocation for string copying failed.
262 * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
264 ***************************************************************************/
267 CURLFORMcode FormAdd(struct curl_httppost **httppost,
268 struct curl_httppost **last_post,
271 FormInfo *first_form, *current_form, *form = NULL;
272 CURLFORMcode return_value = CURL_FORMADD_OK;
273 const char *prevtype = NULL;
274 struct curl_httppost *post = NULL;
275 CURLformoption option;
276 struct curl_forms *forms = NULL;
277 char *array_value=NULL; /* value read from an array */
279 /* This is a state variable, that if TRUE means that we're parsing an
280 array that we got passed to us. If FALSE we're parsing the input
281 va_list arguments. */
282 bool array_state = FALSE;
285 * We need to allocate the first struct to fill in.
287 first_form = calloc(1, sizeof(struct FormInfo));
289 return CURL_FORMADD_MEMORY;
291 current_form = first_form;
294 * Loop through all the options set. Break if we have an error to report.
296 while(return_value == CURL_FORMADD_OK) {
298 /* first see if we have more parts of the array param */
299 if(array_state && forms) {
300 /* get the upcoming option from the given array */
301 option = forms->option;
302 array_value = (char *)forms->value;
304 forms++; /* advance this to next entry */
305 if(CURLFORM_END == option) {
306 /* end of array state */
312 /* This is not array-state, get next option */
313 option = va_arg(params, CURLformoption);
314 if(CURLFORM_END == option)
321 /* we don't support an array from within an array */
322 return_value = CURL_FORMADD_ILLEGAL_ARRAY;
324 forms = va_arg(params, struct curl_forms *);
328 return_value = CURL_FORMADD_NULL;
333 * Set the Name property.
335 case CURLFORM_PTRNAME:
336 #ifdef CURL_DOES_CONVERSIONS
337 /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy
338 * the data in all cases so that we'll have safe memory for the eventual
342 current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
344 case CURLFORM_COPYNAME:
345 if(current_form->name)
346 return_value = CURL_FORMADD_OPTION_TWICE;
348 char *name = array_state?
349 array_value:va_arg(params, char *);
351 current_form->name = name; /* store for the moment */
353 return_value = CURL_FORMADD_NULL;
356 case CURLFORM_NAMELENGTH:
357 if(current_form->namelength)
358 return_value = CURL_FORMADD_OPTION_TWICE;
360 current_form->namelength =
361 array_state?(size_t)array_value:(size_t)va_arg(params, long);
365 * Set the contents property.
367 case CURLFORM_PTRCONTENTS:
368 current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
369 case CURLFORM_COPYCONTENTS:
370 if(current_form->value)
371 return_value = CURL_FORMADD_OPTION_TWICE;
374 array_state?array_value:va_arg(params, char *);
376 current_form->value = value; /* store for the moment */
378 return_value = CURL_FORMADD_NULL;
381 case CURLFORM_CONTENTSLENGTH:
382 current_form->contentslength =
383 array_state?(size_t)array_value:(size_t)va_arg(params, long);
386 case CURLFORM_CONTENTLEN:
387 current_form->flags |= CURL_HTTPPOST_LARGE;
388 current_form->contentslength =
389 array_state?(curl_off_t)(size_t)array_value:va_arg(params, curl_off_t);
392 /* Get contents from a given file name */
393 case CURLFORM_FILECONTENT:
394 if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
395 return_value = CURL_FORMADD_OPTION_TWICE;
397 const char *filename = array_state?
398 array_value:va_arg(params, char *);
400 current_form->value = strdup(filename);
401 if(!current_form->value)
402 return_value = CURL_FORMADD_MEMORY;
404 current_form->flags |= HTTPPOST_READFILE;
405 current_form->value_alloc = TRUE;
409 return_value = CURL_FORMADD_NULL;
413 /* We upload a file */
416 const char *filename = array_state?array_value:
417 va_arg(params, char *);
419 if(current_form->value) {
420 if(current_form->flags & HTTPPOST_FILENAME) {
422 char *fname = strdup(filename);
424 return_value = CURL_FORMADD_MEMORY;
426 form = AddFormInfo(fname, NULL, current_form);
429 return_value = CURL_FORMADD_MEMORY;
432 form->value_alloc = TRUE;
439 return_value = CURL_FORMADD_NULL;
442 return_value = CURL_FORMADD_OPTION_TWICE;
446 current_form->value = strdup(filename);
447 if(!current_form->value)
448 return_value = CURL_FORMADD_MEMORY;
450 current_form->flags |= HTTPPOST_FILENAME;
451 current_form->value_alloc = TRUE;
455 return_value = CURL_FORMADD_NULL;
460 case CURLFORM_BUFFERPTR:
461 current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
462 if(current_form->buffer)
463 return_value = CURL_FORMADD_OPTION_TWICE;
466 array_state?array_value:va_arg(params, char *);
468 current_form->buffer = buffer; /* store for the moment */
469 current_form->value = buffer; /* make it non-NULL to be accepted
473 return_value = CURL_FORMADD_NULL;
477 case CURLFORM_BUFFERLENGTH:
478 if(current_form->bufferlength)
479 return_value = CURL_FORMADD_OPTION_TWICE;
481 current_form->bufferlength =
482 array_state?(size_t)array_value:(size_t)va_arg(params, long);
485 case CURLFORM_STREAM:
486 current_form->flags |= HTTPPOST_CALLBACK;
487 if(current_form->userp)
488 return_value = CURL_FORMADD_OPTION_TWICE;
491 array_state?array_value:va_arg(params, char *);
493 current_form->userp = userp;
494 current_form->value = userp; /* this isn't strictly true but we
495 derive a value from this later on
496 and we need this non-NULL to be
497 accepted as a fine form part */
500 return_value = CURL_FORMADD_NULL;
504 case CURLFORM_CONTENTTYPE:
506 const char *contenttype =
507 array_state?array_value:va_arg(params, char *);
508 if(current_form->contenttype) {
509 if(current_form->flags & HTTPPOST_FILENAME) {
511 char *type = strdup(contenttype);
513 return_value = CURL_FORMADD_MEMORY;
515 form = AddFormInfo(NULL, type, current_form);
518 return_value = CURL_FORMADD_MEMORY;
521 form->contenttype_alloc = TRUE;
528 return_value = CURL_FORMADD_NULL;
531 return_value = CURL_FORMADD_OPTION_TWICE;
535 current_form->contenttype = strdup(contenttype);
536 if(!current_form->contenttype)
537 return_value = CURL_FORMADD_MEMORY;
539 current_form->contenttype_alloc = TRUE;
542 return_value = CURL_FORMADD_NULL;
546 case CURLFORM_CONTENTHEADER:
548 /* this "cast increases required alignment of target type" but
549 we consider it OK anyway */
550 struct curl_slist* list = array_state?
551 (struct curl_slist*)(void*)array_value:
552 va_arg(params, struct curl_slist*);
554 if(current_form->contentheader)
555 return_value = CURL_FORMADD_OPTION_TWICE;
557 current_form->contentheader = list;
561 case CURLFORM_FILENAME:
562 case CURLFORM_BUFFER:
564 const char *filename = array_state?array_value:
565 va_arg(params, char *);
566 if(current_form->showfilename)
567 return_value = CURL_FORMADD_OPTION_TWICE;
569 current_form->showfilename = strdup(filename);
570 if(!current_form->showfilename)
571 return_value = CURL_FORMADD_MEMORY;
573 current_form->showfilename_alloc = TRUE;
578 return_value = CURL_FORMADD_UNKNOWN_OPTION;
583 if(CURL_FORMADD_OK != return_value) {
584 /* On error, free allocated fields for all nodes of the FormInfo linked
585 list without deallocating nodes. List nodes are deallocated later on */
587 for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
588 if(ptr->name_alloc) {
589 Curl_safefree(ptr->name);
590 ptr->name_alloc = FALSE;
592 if(ptr->value_alloc) {
593 Curl_safefree(ptr->value);
594 ptr->value_alloc = FALSE;
596 if(ptr->contenttype_alloc) {
597 Curl_safefree(ptr->contenttype);
598 ptr->contenttype_alloc = FALSE;
600 if(ptr->showfilename_alloc) {
601 Curl_safefree(ptr->showfilename);
602 ptr->showfilename_alloc = FALSE;
607 if(CURL_FORMADD_OK == return_value) {
608 /* go through the list, check for completeness and if everything is
609 * alright add the HttpPost item otherwise set return_value accordingly */
612 for(form = first_form;
615 if(((!form->name || !form->value) && !post) ||
616 ( (form->contentslength) &&
617 (form->flags & HTTPPOST_FILENAME) ) ||
618 ( (form->flags & HTTPPOST_FILENAME) &&
619 (form->flags & HTTPPOST_PTRCONTENTS) ) ||
622 (form->flags & HTTPPOST_BUFFER) &&
623 (form->flags & HTTPPOST_PTRBUFFER) ) ||
625 ( (form->flags & HTTPPOST_READFILE) &&
626 (form->flags & HTTPPOST_PTRCONTENTS) )
628 return_value = CURL_FORMADD_INCOMPLETE;
632 if(((form->flags & HTTPPOST_FILENAME) ||
633 (form->flags & HTTPPOST_BUFFER)) &&
634 !form->contenttype) {
635 char *f = form->flags & HTTPPOST_BUFFER?
636 form->showfilename : form->value;
638 /* our contenttype is missing */
639 form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
640 if(!form->contenttype) {
641 return_value = CURL_FORMADD_MEMORY;
644 form->contenttype_alloc = TRUE;
646 if(!(form->flags & HTTPPOST_PTRNAME) &&
647 (form == first_form) ) {
648 /* Note that there's small risk that form->name is NULL here if the
649 app passed in a bad combo, so we better check for that first. */
651 /* copy name (without strdup; possibly contains null characters) */
652 form->name = Curl_memdup(form->name, form->namelength?
654 strlen(form->name)+1);
657 return_value = CURL_FORMADD_MEMORY;
660 form->name_alloc = TRUE;
662 if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
663 HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
664 HTTPPOST_CALLBACK)) && form->value) {
665 /* copy value (without strdup; possibly contains null characters) */
666 size_t clen = (size_t) form->contentslength;
668 clen = strlen(form->value)+1;
670 form->value = Curl_memdup(form->value, clen);
673 return_value = CURL_FORMADD_MEMORY;
676 form->value_alloc = TRUE;
678 post = AddHttpPost(form->name, form->namelength,
679 form->value, form->contentslength,
680 form->buffer, form->bufferlength,
681 form->contenttype, form->flags,
682 form->contentheader, form->showfilename,
688 return_value = CURL_FORMADD_MEMORY;
692 if(form->contenttype)
693 prevtype = form->contenttype;
696 if(CURL_FORMADD_OK != return_value) {
697 /* On error, free allocated fields for nodes of the FormInfo linked
698 list which are not already owned by the httppost linked list
699 without deallocating nodes. List nodes are deallocated later on */
701 for(ptr = form; ptr != NULL; ptr = ptr->more) {
702 if(ptr->name_alloc) {
703 Curl_safefree(ptr->name);
704 ptr->name_alloc = FALSE;
706 if(ptr->value_alloc) {
707 Curl_safefree(ptr->value);
708 ptr->value_alloc = FALSE;
710 if(ptr->contenttype_alloc) {
711 Curl_safefree(ptr->contenttype);
712 ptr->contenttype_alloc = FALSE;
714 if(ptr->showfilename_alloc) {
715 Curl_safefree(ptr->showfilename);
716 ptr->showfilename_alloc = FALSE;
722 /* Always deallocate FormInfo linked list nodes without touching node
723 fields given that these have either been deallocated or are owned
724 now by the httppost linked list */
726 FormInfo *ptr = first_form->more;
735 * curl_formadd() is a public API to add a section to the multipart formpost.
740 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
741 struct curl_httppost **last_post,
746 va_start(arg, last_post);
747 result = FormAdd(httppost, last_post, arg);
755 * get_vms_file_size does what it takes to get the real size of the file
757 * For fixed files, find out the size of the EOF block and adjust.
759 * For all others, have to read the entire file in, discarding the contents.
760 * Most posted text files will be small, and binary files like zlib archives
761 * and CD/DVD images should be either a STREAM_LF format or a fixed format.
764 curl_off_t VmsRealFileSize(const char * name,
765 const struct_stat * stat_buf)
772 file = fopen(name, FOPEN_READTEXT); /* VMS */
778 while(ret_stat > 0) {
779 ret_stat = fread(buffer, 1, sizeof(buffer), file);
790 * VmsSpecialSize checks to see if the stat st_size can be trusted and
791 * if not to call a routine to get the correct size.
794 static curl_off_t VmsSpecialSize(const char * name,
795 const struct_stat * stat_buf)
797 switch(stat_buf->st_fab_rfm) {
800 return VmsRealFileSize(name, stat_buf);
803 return stat_buf->st_size;
810 #define filesize(name, stat_data) (stat_data.st_size)
812 /* Getting the expected file size needs help on VMS */
813 #define filesize(name, stat_data) VmsSpecialSize(name, &stat_data)
817 * AddFormData() adds a chunk of data to the FormData linked list.
819 * size is incremented by the chunk length, unless it is NULL
821 static CURLcode AddFormData(struct FormData **formp,
827 struct FormData *newform;
829 CURLcode result = CURLE_OK;
830 if(length < 0 || (size && *size < 0))
831 return CURLE_BAD_FUNCTION_ARGUMENT;
833 newform = malloc(sizeof(struct FormData));
835 return CURLE_OUT_OF_MEMORY;
836 newform->next = NULL;
838 if(type <= FORM_CONTENT) {
839 /* we make it easier for plain strings: */
841 length = strlen((char *)line);
842 #if (SIZEOF_SIZE_T < CURL_SIZEOF_CURL_OFF_T)
843 else if(length >= (curl_off_t)(size_t)-1) {
844 result = CURLE_BAD_FUNCTION_ARGUMENT;
849 newform->line = malloc((size_t)length+1);
851 result = CURLE_OUT_OF_MEMORY;
854 alloc2 = newform->line;
855 memcpy(newform->line, line, (size_t)length);
856 newform->length = (size_t)length;
857 newform->line[(size_t)length]=0; /* zero terminate for easier debugging */
860 /* For callbacks and files we don't have any actual data so we just keep a
861 pointer to whatever this points to */
862 newform->line = (char *)line;
864 newform->type = type;
867 (*formp)->next = newform;
874 if(type != FORM_FILE)
875 /* for static content as well as callback data we add the size given
879 /* Since this is a file to be uploaded here, add the size of the actual
881 if(!strequal("-", newform->line)) {
883 if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
884 *size += filesize(newform->line, file);
886 result = CURLE_BAD_FUNCTION_ARGUMENT;
902 * AddFormDataf() adds printf()-style formatted data to the formdata chain.
905 static CURLcode AddFormDataf(struct FormData **formp,
907 const char *fmt, ...)
912 vsnprintf(s, sizeof(s), fmt, ap);
915 return AddFormData(formp, FORM_DATA, s, 0, size);
919 * Curl_formclean() is used from http.c, this cleans a built FormData linked
922 void Curl_formclean(struct FormData **form_ptr)
924 struct FormData *next, *form;
931 next=form->next; /* the following form line */
932 if(form->type <= FORM_CONTENT)
933 free(form->line); /* free the line */
934 free(form); /* free the struct */
936 } while((form = next) != NULL); /* continue */
943 * Serialize a curl_httppost struct.
944 * Returns 0 on success.
948 int curl_formget(struct curl_httppost *form, void *arg,
949 curl_formget_callback append)
953 struct FormData *data, *ptr;
955 result = Curl_getformdata(NULL, &data, form, NULL, &size);
959 for(ptr = data; ptr; ptr = ptr->next) {
960 if((ptr->type == FORM_FILE) || (ptr->type == FORM_CALLBACK)) {
965 Curl_FormInit(&temp, ptr);
968 nread = readfromfile(&temp, buffer, sizeof(buffer));
969 if((nread == (size_t) -1) ||
970 (nread > sizeof(buffer)) ||
971 (nread != append(arg, buffer, nread))) {
974 Curl_formclean(&data);
980 if(ptr->length != append(arg, ptr->line, ptr->length)) {
981 Curl_formclean(&data);
986 Curl_formclean(&data);
991 * curl_formfree() is an external function to free up a whole form post
994 void curl_formfree(struct curl_httppost *form)
996 struct curl_httppost *next;
999 /* no form to free, just get out of this */
1003 next=form->next; /* the following form line */
1005 /* recurse to sub-contents */
1006 curl_formfree(form->more);
1008 if(!(form->flags & HTTPPOST_PTRNAME))
1009 free(form->name); /* free the name */
1011 (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK))
1013 free(form->contents); /* free the contents */
1014 free(form->contenttype); /* free the content type */
1015 free(form->showfilename); /* free the faked file name */
1016 free(form); /* free the struct */
1018 } while((form = next) != NULL); /* continue */
1021 #ifndef HAVE_BASENAME
1023 (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
1026 The basename() function shall take the pathname pointed to by path and
1027 return a pointer to the final component of the pathname, deleting any
1028 trailing '/' characters.
1030 If the string pointed to by path consists entirely of the '/' character,
1031 basename() shall return a pointer to the string "/". If the string pointed
1032 to by path is exactly "//", it is implementation-defined whether '/' or "//"
1035 If path is a null pointer or points to an empty string, basename() shall
1036 return a pointer to the string ".".
1038 The basename() function may modify the string pointed to by path, and may
1039 return a pointer to static storage that may then be overwritten by a
1040 subsequent call to basename().
1042 The basename() function need not be reentrant. A function that is not
1043 required to be reentrant is not required to be thread-safe.
1046 static char *Curl_basename(char *path)
1048 /* Ignore all the details above for now and make a quick and simple
1049 implementaion here */
1053 s1=strrchr(path, '/');
1054 s2=strrchr(path, '\\');
1057 path = (s1 > s2? s1 : s2)+1;
1068 static char *strippath(const char *fullfile)
1072 filename = strdup(fullfile); /* duplicate since basename() may ruin the
1073 buffer it works on */
1076 base = strdup(basename(filename));
1078 free(filename); /* free temporary buffer */
1080 return base; /* returns an allocated string or NULL ! */
1083 static CURLcode formdata_add_filename(const struct curl_httppost *file,
1084 struct FormData **form,
1087 CURLcode result = CURLE_OK;
1088 char *filename = file->showfilename;
1089 char *filebasename = NULL;
1090 char *filename_escaped = NULL;
1093 filebasename = strippath(file->contents);
1095 return CURLE_OUT_OF_MEMORY;
1096 filename = filebasename;
1099 if(strchr(filename, '\\') || strchr(filename, '"')) {
1102 /* filename need be escaped */
1103 filename_escaped = malloc(strlen(filename)*2+1);
1104 if(!filename_escaped) {
1106 return CURLE_OUT_OF_MEMORY;
1108 p0 = filename_escaped;
1111 if(*p1 == '\\' || *p1 == '"')
1116 filename = filename_escaped;
1118 result = AddFormDataf(form, size,
1119 "; filename=\"%s\"",
1121 free(filename_escaped);
1127 * Curl_getformdata() converts a linked list of "meta data" into a complete
1128 * (possibly huge) multipart formdata. The input list is in 'post', while the
1129 * output resulting linked lists gets stored in '*finalform'. *sizep will get
1130 * the total size of the whole POST.
1131 * A multipart/form_data content-type is built, unless a custom content-type
1132 * is passed in 'custom_content_type'.
1134 * This function will not do a failf() for the potential memory failures but
1135 * should for all other errors it spots. Just note that this function MAY get
1136 * a NULL pointer in the 'data' argument.
1139 CURLcode Curl_getformdata(struct Curl_easy *data,
1140 struct FormData **finalform,
1141 struct curl_httppost *post,
1142 const char *custom_content_type,
1145 struct FormData *form = NULL;
1146 struct FormData *firstform;
1147 struct curl_httppost *file;
1148 CURLcode result = CURLE_OK;
1150 curl_off_t size = 0; /* support potentially ENORMOUS formposts */
1152 char *fileboundary = NULL;
1153 struct curl_slist* curList;
1155 *finalform = NULL; /* default form is empty */
1158 return result; /* no input => no output! */
1160 boundary = formboundary(data);
1162 return CURLE_OUT_OF_MEMORY;
1164 /* Make the first line of the output */
1165 result = AddFormDataf(&form, NULL,
1166 "%s; boundary=%s\r\n",
1167 custom_content_type?custom_content_type:
1168 "Content-Type: multipart/form-data",
1175 /* we DO NOT include that line in the total size of the POST, since it'll be
1176 part of the header! */
1183 result = AddFormDataf(&form, &size, "\r\n");
1189 result = AddFormDataf(&form, &size, "--%s\r\n", boundary);
1193 /* Maybe later this should be disabled when a custom_content_type is
1194 passed, since Content-Disposition is not meaningful for all multipart
1197 result = AddFormDataf(&form, &size,
1198 "Content-Disposition: form-data; name=\"");
1202 result = AddFormData(&form, FORM_DATA, post->name, post->namelength,
1207 result = AddFormDataf(&form, &size, "\"");
1212 /* If used, this is a link to more file names, we must then do
1213 the magic to include several files with the same field name */
1216 fileboundary = formboundary(data);
1218 result = CURLE_OUT_OF_MEMORY;
1222 result = AddFormDataf(&form, &size,
1223 "\r\nContent-Type: multipart/mixed;"
1234 /* If 'showfilename' is set, that is a faked name passed on to us
1235 to use to in the formpost. If that is not set, the actually used
1236 local file name should be added. */
1239 /* if multiple-file */
1240 result = AddFormDataf(&form, &size,
1241 "\r\n--%s\r\nContent-Disposition: "
1246 result = formdata_add_filename(file, &form, &size);
1250 else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER|
1251 HTTPPOST_CALLBACK)) {
1252 /* it should be noted that for the HTTPPOST_FILENAME and
1253 HTTPPOST_CALLBACK cases the ->showfilename struct member is always
1254 assigned at this point */
1255 if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) {
1256 result = formdata_add_filename(post, &form, &size);
1263 if(file->contenttype) {
1264 /* we have a specified type */
1265 result = AddFormDataf(&form, &size,
1266 "\r\nContent-Type: %s",
1272 curList = file->contentheader;
1274 /* Process the additional headers specified for this form */
1275 result = AddFormDataf(&form, &size, "\r\n%s", curList->data);
1278 curList = curList->next;
1283 result = AddFormDataf(&form, &size, "\r\n\r\n");
1287 if((post->flags & HTTPPOST_FILENAME) ||
1288 (post->flags & HTTPPOST_READFILE)) {
1289 /* we should include the contents from the specified file */
1292 fileread = strequal("-", file->contents)?
1293 stdin:fopen(file->contents, "rb"); /* binary read for win32 */
1296 * VMS: This only allows for stream files on VMS. Stream files are
1297 * OK, as are FIXED & VAR files WITHOUT implied CC For implied CC,
1298 * every record needs to have a \n appended & 1 added to SIZE
1302 if(fileread != stdin) {
1303 /* close the file */
1305 /* add the file name only - for later reading from this */
1306 result = AddFormData(&form, FORM_FILE, file->contents, 0, &size);
1309 /* When uploading from stdin, we can't know the size of the file,
1310 * thus must read the full file as before. We *could* use chunked
1311 * transfer-encoding, but that only works for HTTP 1.1 and we
1312 * can't be sure we work with such a server.
1316 while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
1317 result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
1325 failf(data, "couldn't open file \"%s\"", file->contents);
1327 result = CURLE_READ_ERROR;
1330 else if(post->flags & HTTPPOST_BUFFER)
1331 /* include contents of buffer */
1332 result = AddFormData(&form, FORM_CONTENT, post->buffer,
1333 post->bufferlength, &size);
1334 else if(post->flags & HTTPPOST_CALLBACK)
1335 /* the contents should be read with the callback and the size is set
1336 with the contentslength */
1337 result = AddFormData(&form, FORM_CALLBACK, post->userp,
1338 post->flags&CURL_HTTPPOST_LARGE?
1339 post->contentlen:post->contentslength, &size);
1341 /* include the contents we got */
1342 result = AddFormData(&form, FORM_CONTENT, post->contents,
1343 post->flags&CURL_HTTPPOST_LARGE?
1344 post->contentlen:post->contentslength, &size);
1346 } while(file && !result); /* for each specified file for this field */
1352 /* this was a multiple-file inclusion, make a termination file
1354 result = AddFormDataf(&form, &size,
1361 } while((post = post->next) != NULL); /* for each field */
1363 /* end-boundary for everything */
1365 result = AddFormDataf(&form, &size, "\r\n--%s--\r\n", boundary);
1368 Curl_formclean(&firstform);
1379 *finalform = firstform;
1385 * Curl_FormInit() inits the struct 'form' points to with the 'formdata'
1386 * and resets the 'sent' counter.
1388 int Curl_FormInit(struct Form *form, struct FormData *formdata)
1391 return 1; /* error */
1393 form->data = formdata;
1396 form->fread_func = ZERO_NULL;
1402 # define fopen_read fopen
1407 * For upload to work as expected on VMS, different optional
1408 * parameters must be added to the fopen command based on
1409 * record format of the file.
1412 # define fopen_read vmsfopenread
1413 static FILE * vmsfopenread(const char *file, const char *mode) {
1414 struct_stat statbuf;
1417 result = stat(file, &statbuf);
1419 switch (statbuf.st_fab_rfm) {
1423 return fopen(file, FOPEN_READTEXT); /* VMS */
1426 return fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm");
1434 * The read callback that this function may use can return a value larger than
1435 * 'size' (which then this function returns) that indicates a problem and it
1436 * must be properly dealt with
1438 static size_t readfromfile(struct Form *form, char *buffer,
1442 bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE;
1445 if(form->fread_func == ZERO_NULL)
1448 nread = form->fread_func(buffer, 1, size, form->data->line);
1452 /* this file hasn't yet been opened */
1453 form->fp = fopen_read(form->data->line, "rb"); /* b is for binary */
1455 return (size_t)-1; /* failure */
1457 nread = fread(buffer, 1, size, form->fp);
1460 /* this is the last chunk from the file, move on */
1465 form->data = form->data->next;
1472 * Curl_FormReader() is the fread() emulation function that will be used to
1473 * deliver the formdata to the transfer loop and then sent away to the peer.
1475 size_t Curl_FormReader(char *buffer,
1484 form=(struct Form *)mydata;
1486 wantedsize = size * nitems;
1489 return 0; /* nothing, error, empty */
1491 if((form->data->type == FORM_FILE) ||
1492 (form->data->type == FORM_CALLBACK)) {
1493 gotsize = readfromfile(form, buffer, wantedsize);
1496 /* If positive or -1, return. If zero, continue! */
1501 if((form->data->length - form->sent) > wantedsize - gotsize) {
1503 memcpy(buffer + gotsize, form->data->line + form->sent,
1504 wantedsize - gotsize);
1506 form->sent += wantedsize-gotsize;
1511 memcpy(buffer+gotsize,
1512 form->data->line + form->sent,
1513 (form->data->length - form->sent) );
1514 gotsize += form->data->length - form->sent;
1518 form->data = form->data->next; /* advance */
1520 } while(form->data && (form->data->type < FORM_CALLBACK));
1521 /* If we got an empty line and we have more data, we proceed to the next
1522 line immediately to avoid returning zero before we've reached the end. */
1528 * Curl_formpostheader() returns the first line of the formpost, the
1529 * request-header part (which is not part of the request-body like the rest of
1532 char *Curl_formpostheader(void *formp, size_t *len)
1535 struct Form *form=(struct Form *)formp;
1538 return 0; /* nothing, ERROR! */
1540 header = form->data->line;
1541 *len = form->data->length;
1543 form->data = form->data->next; /* advance */
1549 * formboundary() creates a suitable boundary string and returns an allocated
1552 static char *formboundary(struct Curl_easy *data)
1554 /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
1556 return aprintf("------------------------%08x%08x",
1557 Curl_rand(data), Curl_rand(data));
1560 #else /* CURL_DISABLE_HTTP */
1561 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
1562 struct curl_httppost **last_post,
1567 return CURL_FORMADD_DISABLED;
1570 int curl_formget(struct curl_httppost *form, void *arg,
1571 curl_formget_callback append)
1576 return CURL_FORMADD_DISABLED;
1579 void curl_formfree(struct curl_httppost *form)
1582 /* does nothing HTTP is disabled */
1586 #endif /* !defined(CURL_DISABLE_HTTP) */