1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2015, 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 #ifndef CURL_DISABLE_HTTP
29 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
33 #include "urldata.h" /* for struct SessionHandle */
35 #include "vtls/vtls.h"
39 #include "curl_printf.h"
41 /* The last #include files should be: */
42 #include "curl_memory.h"
46 static char *Curl_basename(char *path);
47 #define basename(x) Curl_basename((x))
50 static size_t readfromfile(struct Form *form, char *buffer, size_t size);
51 static char *formboundary(struct SessionHandle *data);
53 /* What kind of Content-Type to use on un-specified files with unrecognized
55 #define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
57 #define FORM_FILE_SEPARATOR ','
58 #define FORM_TYPE_SEPARATOR ';'
60 /***************************************************************************
64 * Adds a HttpPost structure to the list, if parent_post is given becomes
65 * a subpost of parent_post instead of a direct list element.
67 * Returns newly allocated HttpPost on success and NULL if malloc failed.
69 ***************************************************************************/
70 static struct curl_httppost *
71 AddHttpPost(char *name, size_t namelength,
72 char *value, size_t contentslength,
73 char *buffer, size_t bufferlength,
76 struct curl_slist* contentHeader,
77 char *showfilename, char *userp,
78 struct curl_httppost *parent_post,
79 struct curl_httppost **httppost,
80 struct curl_httppost **last_post)
82 struct curl_httppost *post;
83 post = calloc(1, sizeof(struct curl_httppost));
86 post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
87 post->contents = value;
88 post->contentslength = (long)contentslength;
89 post->buffer = buffer;
90 post->bufferlength = (long)bufferlength;
91 post->contenttype = contenttype;
92 post->contentheader = contentHeader;
93 post->showfilename = showfilename;
101 /* now, point our 'more' to the original 'more' */
102 post->more = parent_post->more;
104 /* then move the original 'more' to point to ourselves */
105 parent_post->more = post;
108 /* make the previous point to this */
110 (*last_post)->next = post;
119 /***************************************************************************
123 * Adds a FormInfo structure to the list presented by parent_form_info.
125 * Returns newly allocated FormInfo on success and NULL if malloc failed/
126 * parent_form_info is NULL.
128 ***************************************************************************/
129 static FormInfo * AddFormInfo(char *value,
131 FormInfo *parent_form_info)
134 form_info = calloc(1, sizeof(struct FormInfo));
137 form_info->value = value;
139 form_info->contenttype = contenttype;
140 form_info->flags = HTTPPOST_FILENAME;
145 if(parent_form_info) {
146 /* now, point our 'more' to the original 'more' */
147 form_info->more = parent_form_info->more;
149 /* then move the original 'more' to point to ourselves */
150 parent_form_info->more = form_info;
156 /***************************************************************************
158 * ContentTypeForFilename()
160 * Provides content type for filename if one of the known types (else
161 * (either the prevtype or the default is returned).
163 * Returns some valid contenttype for filename.
165 ***************************************************************************/
166 static const char *ContentTypeForFilename(const char *filename,
167 const char *prevtype)
169 const char *contenttype = NULL;
172 * No type was specified, we scan through a few well-known
173 * extensions and pick the first we match!
176 const char *extension;
179 static const struct ContentType ctts[]={
180 {".gif", "image/gif"},
181 {".jpg", "image/jpeg"},
182 {".jpeg", "image/jpeg"},
183 {".txt", "text/plain"},
184 {".html", "text/html"},
185 {".xml", "application/xml"}
189 /* default to the previously set/used! */
190 contenttype = prevtype;
192 contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
194 if(filename) { /* in case a NULL was passed in */
195 for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
196 if(strlen(filename) >= strlen(ctts[i].extension)) {
197 if(strequal(filename +
198 strlen(filename) - strlen(ctts[i].extension),
199 ctts[i].extension)) {
200 contenttype = ctts[i].type;
206 /* we have a contenttype by now */
210 /***************************************************************************
214 * Stores a formpost parameter and builds the appropriate linked list.
216 * Has two principal functionalities: using files and byte arrays as
217 * post parts. Byte arrays are either copied or just the pointer is stored
218 * (as the user requests) while for files only the filename and not the
221 * While you may have only one byte array for each name, multiple filenames
222 * are allowed (and because of this feature CURLFORM_END is needed after
223 * using CURLFORM_FILE).
227 * Simple name/value pair with copied contents:
228 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
229 * CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
231 * name/value pair where only the content pointer is remembered:
232 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
233 * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END);
234 * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
236 * storing a filename (CONTENTTYPE is optional!):
237 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
238 * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text",
241 * storing multiple filenames:
242 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
243 * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
246 * CURL_FORMADD_OK on success
247 * CURL_FORMADD_MEMORY if the FormInfo allocation fails
248 * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
249 * CURL_FORMADD_NULL if a null pointer was given for a char
250 * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
251 * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
252 * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
253 * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated
254 * CURL_FORMADD_MEMORY if some allocation for string copying failed.
255 * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
257 ***************************************************************************/
260 CURLFORMcode FormAdd(struct curl_httppost **httppost,
261 struct curl_httppost **last_post,
264 FormInfo *first_form, *current_form, *form = NULL;
265 CURLFORMcode return_value = CURL_FORMADD_OK;
266 const char *prevtype = NULL;
267 struct curl_httppost *post = NULL;
268 CURLformoption option;
269 struct curl_forms *forms = NULL;
270 char *array_value=NULL; /* value read from an array */
272 /* This is a state variable, that if TRUE means that we're parsing an
273 array that we got passed to us. If FALSE we're parsing the input
274 va_list arguments. */
275 bool array_state = FALSE;
278 * We need to allocate the first struct to fill in.
280 first_form = calloc(1, sizeof(struct FormInfo));
282 return CURL_FORMADD_MEMORY;
284 current_form = first_form;
287 * Loop through all the options set. Break if we have an error to report.
289 while(return_value == CURL_FORMADD_OK) {
291 /* first see if we have more parts of the array param */
292 if(array_state && forms) {
293 /* get the upcoming option from the given array */
294 option = forms->option;
295 array_value = (char *)forms->value;
297 forms++; /* advance this to next entry */
298 if(CURLFORM_END == option) {
299 /* end of array state */
305 /* This is not array-state, get next option */
306 option = va_arg(params, CURLformoption);
307 if(CURLFORM_END == option)
314 /* we don't support an array from within an array */
315 return_value = CURL_FORMADD_ILLEGAL_ARRAY;
317 forms = va_arg(params, struct curl_forms *);
321 return_value = CURL_FORMADD_NULL;
326 * Set the Name property.
328 case CURLFORM_PTRNAME:
329 #ifdef CURL_DOES_CONVERSIONS
330 /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy
331 * the data in all cases so that we'll have safe memory for the eventual
335 current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
337 case CURLFORM_COPYNAME:
338 if(current_form->name)
339 return_value = CURL_FORMADD_OPTION_TWICE;
341 char *name = array_state?
342 array_value:va_arg(params, char *);
344 current_form->name = name; /* store for the moment */
346 return_value = CURL_FORMADD_NULL;
349 case CURLFORM_NAMELENGTH:
350 if(current_form->namelength)
351 return_value = CURL_FORMADD_OPTION_TWICE;
353 current_form->namelength =
354 array_state?(size_t)array_value:(size_t)va_arg(params, long);
358 * Set the contents property.
360 case CURLFORM_PTRCONTENTS:
361 current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
362 case CURLFORM_COPYCONTENTS:
363 if(current_form->value)
364 return_value = CURL_FORMADD_OPTION_TWICE;
367 array_state?array_value:va_arg(params, char *);
369 current_form->value = value; /* store for the moment */
371 return_value = CURL_FORMADD_NULL;
374 case CURLFORM_CONTENTSLENGTH:
375 if(current_form->contentslength)
376 return_value = CURL_FORMADD_OPTION_TWICE;
378 current_form->contentslength =
379 array_state?(size_t)array_value:(size_t)va_arg(params, long);
382 /* Get contents from a given file name */
383 case CURLFORM_FILECONTENT:
384 if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
385 return_value = CURL_FORMADD_OPTION_TWICE;
387 const char *filename = array_state?
388 array_value:va_arg(params, char *);
390 current_form->value = strdup(filename);
391 if(!current_form->value)
392 return_value = CURL_FORMADD_MEMORY;
394 current_form->flags |= HTTPPOST_READFILE;
395 current_form->value_alloc = TRUE;
399 return_value = CURL_FORMADD_NULL;
403 /* We upload a file */
406 const char *filename = array_state?array_value:
407 va_arg(params, char *);
409 if(current_form->value) {
410 if(current_form->flags & HTTPPOST_FILENAME) {
412 char *fname = strdup(filename);
414 return_value = CURL_FORMADD_MEMORY;
416 form = AddFormInfo(fname, NULL, current_form);
419 return_value = CURL_FORMADD_MEMORY;
422 form->value_alloc = TRUE;
429 return_value = CURL_FORMADD_NULL;
432 return_value = CURL_FORMADD_OPTION_TWICE;
436 current_form->value = strdup(filename);
437 if(!current_form->value)
438 return_value = CURL_FORMADD_MEMORY;
440 current_form->flags |= HTTPPOST_FILENAME;
441 current_form->value_alloc = TRUE;
445 return_value = CURL_FORMADD_NULL;
450 case CURLFORM_BUFFERPTR:
451 current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
452 if(current_form->buffer)
453 return_value = CURL_FORMADD_OPTION_TWICE;
456 array_state?array_value:va_arg(params, char *);
458 current_form->buffer = buffer; /* store for the moment */
459 current_form->value = buffer; /* make it non-NULL to be accepted
463 return_value = CURL_FORMADD_NULL;
467 case CURLFORM_BUFFERLENGTH:
468 if(current_form->bufferlength)
469 return_value = CURL_FORMADD_OPTION_TWICE;
471 current_form->bufferlength =
472 array_state?(size_t)array_value:(size_t)va_arg(params, long);
475 case CURLFORM_STREAM:
476 current_form->flags |= HTTPPOST_CALLBACK;
477 if(current_form->userp)
478 return_value = CURL_FORMADD_OPTION_TWICE;
481 array_state?array_value:va_arg(params, char *);
483 current_form->userp = userp;
484 current_form->value = userp; /* this isn't strictly true but we
485 derive a value from this later on
486 and we need this non-NULL to be
487 accepted as a fine form part */
490 return_value = CURL_FORMADD_NULL;
494 case CURLFORM_CONTENTTYPE:
496 const char *contenttype =
497 array_state?array_value:va_arg(params, char *);
498 if(current_form->contenttype) {
499 if(current_form->flags & HTTPPOST_FILENAME) {
501 char *type = strdup(contenttype);
503 return_value = CURL_FORMADD_MEMORY;
505 form = AddFormInfo(NULL, type, current_form);
508 return_value = CURL_FORMADD_MEMORY;
511 form->contenttype_alloc = TRUE;
518 return_value = CURL_FORMADD_NULL;
521 return_value = CURL_FORMADD_OPTION_TWICE;
525 current_form->contenttype = strdup(contenttype);
526 if(!current_form->contenttype)
527 return_value = CURL_FORMADD_MEMORY;
529 current_form->contenttype_alloc = TRUE;
532 return_value = CURL_FORMADD_NULL;
536 case CURLFORM_CONTENTHEADER:
538 /* this "cast increases required alignment of target type" but
539 we consider it OK anyway */
540 struct curl_slist* list = array_state?
541 (struct curl_slist*)array_value:
542 va_arg(params, struct curl_slist*);
544 if(current_form->contentheader)
545 return_value = CURL_FORMADD_OPTION_TWICE;
547 current_form->contentheader = list;
551 case CURLFORM_FILENAME:
552 case CURLFORM_BUFFER:
554 const char *filename = array_state?array_value:
555 va_arg(params, char *);
556 if(current_form->showfilename)
557 return_value = CURL_FORMADD_OPTION_TWICE;
559 current_form->showfilename = strdup(filename);
560 if(!current_form->showfilename)
561 return_value = CURL_FORMADD_MEMORY;
563 current_form->showfilename_alloc = TRUE;
568 return_value = CURL_FORMADD_UNKNOWN_OPTION;
573 if(CURL_FORMADD_OK != return_value) {
574 /* On error, free allocated fields for all nodes of the FormInfo linked
575 list without deallocating nodes. List nodes are deallocated later on */
577 for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
578 if(ptr->name_alloc) {
579 Curl_safefree(ptr->name);
580 ptr->name_alloc = FALSE;
582 if(ptr->value_alloc) {
583 Curl_safefree(ptr->value);
584 ptr->value_alloc = FALSE;
586 if(ptr->contenttype_alloc) {
587 Curl_safefree(ptr->contenttype);
588 ptr->contenttype_alloc = FALSE;
590 if(ptr->showfilename_alloc) {
591 Curl_safefree(ptr->showfilename);
592 ptr->showfilename_alloc = FALSE;
597 if(CURL_FORMADD_OK == return_value) {
598 /* go through the list, check for completeness and if everything is
599 * alright add the HttpPost item otherwise set return_value accordingly */
602 for(form = first_form;
605 if(((!form->name || !form->value) && !post) ||
606 ( (form->contentslength) &&
607 (form->flags & HTTPPOST_FILENAME) ) ||
608 ( (form->flags & HTTPPOST_FILENAME) &&
609 (form->flags & HTTPPOST_PTRCONTENTS) ) ||
612 (form->flags & HTTPPOST_BUFFER) &&
613 (form->flags & HTTPPOST_PTRBUFFER) ) ||
615 ( (form->flags & HTTPPOST_READFILE) &&
616 (form->flags & HTTPPOST_PTRCONTENTS) )
618 return_value = CURL_FORMADD_INCOMPLETE;
622 if(((form->flags & HTTPPOST_FILENAME) ||
623 (form->flags & HTTPPOST_BUFFER)) &&
624 !form->contenttype ) {
625 char *f = form->flags & HTTPPOST_BUFFER?
626 form->showfilename : form->value;
628 /* our contenttype is missing */
629 form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
630 if(!form->contenttype) {
631 return_value = CURL_FORMADD_MEMORY;
634 form->contenttype_alloc = TRUE;
636 if(!(form->flags & HTTPPOST_PTRNAME) &&
637 (form == first_form) ) {
638 /* Note that there's small risk that form->name is NULL here if the
639 app passed in a bad combo, so we better check for that first. */
641 /* copy name (without strdup; possibly contains null characters) */
642 form->name = Curl_memdup(form->name, form->namelength?
644 strlen(form->name)+1);
647 return_value = CURL_FORMADD_MEMORY;
650 form->name_alloc = TRUE;
652 if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
653 HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
654 HTTPPOST_CALLBACK)) && form->value) {
655 /* copy value (without strdup; possibly contains null characters) */
656 form->value = Curl_memdup(form->value, form->contentslength?
657 form->contentslength:
658 strlen(form->value)+1);
660 return_value = CURL_FORMADD_MEMORY;
663 form->value_alloc = TRUE;
665 post = AddHttpPost(form->name, form->namelength,
666 form->value, form->contentslength,
667 form->buffer, form->bufferlength,
668 form->contenttype, form->flags,
669 form->contentheader, form->showfilename,
675 return_value = CURL_FORMADD_MEMORY;
679 if(form->contenttype)
680 prevtype = form->contenttype;
683 if(CURL_FORMADD_OK != return_value) {
684 /* On error, free allocated fields for nodes of the FormInfo linked
685 list which are not already owned by the httppost linked list
686 without deallocating nodes. List nodes are deallocated later on */
688 for(ptr = form; ptr != NULL; ptr = ptr->more) {
689 if(ptr->name_alloc) {
690 Curl_safefree(ptr->name);
691 ptr->name_alloc = FALSE;
693 if(ptr->value_alloc) {
694 Curl_safefree(ptr->value);
695 ptr->value_alloc = FALSE;
697 if(ptr->contenttype_alloc) {
698 Curl_safefree(ptr->contenttype);
699 ptr->contenttype_alloc = FALSE;
701 if(ptr->showfilename_alloc) {
702 Curl_safefree(ptr->showfilename);
703 ptr->showfilename_alloc = FALSE;
709 /* Always deallocate FormInfo linked list nodes without touching node
710 fields given that these have either been deallocated or are owned
711 now by the httppost linked list */
713 FormInfo *ptr = first_form->more;
722 * curl_formadd() is a public API to add a section to the multipart formpost.
727 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
728 struct curl_httppost **last_post,
733 va_start(arg, last_post);
734 result = FormAdd(httppost, last_post, arg);
742 * get_vms_file_size does what it takes to get the real size of the file
744 * For fixed files, find out the size of the EOF block and adjust.
746 * For all others, have to read the entire file in, discarding the contents.
747 * Most posted text files will be small, and binary files like zlib archives
748 * and CD/DVD images should be either a STREAM_LF format or a fixed format.
751 curl_off_t VmsRealFileSize(const char * name,
752 const struct_stat * stat_buf)
759 file = fopen(name, "r"); /* VMS */
765 while(ret_stat > 0) {
766 ret_stat = fread(buffer, 1, sizeof(buffer), file);
777 * VmsSpecialSize checks to see if the stat st_size can be trusted and
778 * if not to call a routine to get the correct size.
781 static curl_off_t VmsSpecialSize(const char * name,
782 const struct_stat * stat_buf)
784 switch(stat_buf->st_fab_rfm) {
787 return VmsRealFileSize(name, stat_buf);
790 return stat_buf->st_size;
797 #define filesize(name, stat_data) (stat_data.st_size)
799 /* Getting the expected file size needs help on VMS */
800 #define filesize(name, stat_data) VmsSpecialSize(name, &stat_data)
804 * AddFormData() adds a chunk of data to the FormData linked list.
806 * size is incremented by the chunk length, unless it is NULL
808 static CURLcode AddFormData(struct FormData **formp,
814 struct FormData *newform = malloc(sizeof(struct FormData));
816 return CURLE_OUT_OF_MEMORY;
817 newform->next = NULL;
819 if(type <= FORM_CONTENT) {
820 /* we make it easier for plain strings: */
822 length = strlen((char *)line);
824 newform->line = malloc(length+1);
827 return CURLE_OUT_OF_MEMORY;
829 memcpy(newform->line, line, length);
830 newform->length = length;
831 newform->line[length]=0; /* zero terminate for easier debugging */
834 /* For callbacks and files we don't have any actual data so we just keep a
835 pointer to whatever this points to */
836 newform->line = (char *)line;
838 newform->type = type;
841 (*formp)->next = newform;
848 if(type != FORM_FILE)
849 /* for static content as well as callback data we add the size given
853 /* Since this is a file to be uploaded here, add the size of the actual
855 if(!strequal("-", newform->line)) {
857 if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
858 *size += filesize(newform->line, file);
860 return CURLE_BAD_FUNCTION_ARGUMENT;
868 * AddFormDataf() adds printf()-style formatted data to the formdata chain.
871 static CURLcode AddFormDataf(struct FormData **formp,
873 const char *fmt, ...)
878 vsnprintf(s, sizeof(s), fmt, ap);
881 return AddFormData(formp, FORM_DATA, s, 0, size);
885 * Curl_formclean() is used from http.c, this cleans a built FormData linked
888 void Curl_formclean(struct FormData **form_ptr)
890 struct FormData *next, *form;
897 next=form->next; /* the following form line */
898 if(form->type <= FORM_CONTENT)
899 free(form->line); /* free the line */
900 free(form); /* free the struct */
902 } while((form = next) != NULL); /* continue */
909 * Serialize a curl_httppost struct.
910 * Returns 0 on success.
914 int curl_formget(struct curl_httppost *form, void *arg,
915 curl_formget_callback append)
919 struct FormData *data, *ptr;
921 result = Curl_getformdata(NULL, &data, form, NULL, &size);
925 for(ptr = data; ptr; ptr = ptr->next) {
926 if((ptr->type == FORM_FILE) || (ptr->type == FORM_CALLBACK)) {
931 Curl_FormInit(&temp, ptr);
934 nread = readfromfile(&temp, buffer, sizeof(buffer));
935 if((nread == (size_t) -1) ||
936 (nread > sizeof(buffer)) ||
937 (nread != append(arg, buffer, nread))) {
940 Curl_formclean(&data);
946 if(ptr->length != append(arg, ptr->line, ptr->length)) {
947 Curl_formclean(&data);
952 Curl_formclean(&data);
957 * curl_formfree() is an external function to free up a whole form post
960 void curl_formfree(struct curl_httppost *form)
962 struct curl_httppost *next;
965 /* no form to free, just get out of this */
969 next=form->next; /* the following form line */
971 /* recurse to sub-contents */
972 curl_formfree(form->more);
974 if(!(form->flags & HTTPPOST_PTRNAME))
975 free(form->name); /* free the name */
977 (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK))
979 free(form->contents); /* free the contents */
980 free(form->contenttype); /* free the content type */
981 free(form->showfilename); /* free the faked file name */
982 free(form); /* free the struct */
984 } while((form = next) != NULL); /* continue */
987 #ifndef HAVE_BASENAME
989 (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
992 The basename() function shall take the pathname pointed to by path and
993 return a pointer to the final component of the pathname, deleting any
994 trailing '/' characters.
996 If the string pointed to by path consists entirely of the '/' character,
997 basename() shall return a pointer to the string "/". If the string pointed
998 to by path is exactly "//", it is implementation-defined whether '/' or "//"
1001 If path is a null pointer or points to an empty string, basename() shall
1002 return a pointer to the string ".".
1004 The basename() function may modify the string pointed to by path, and may
1005 return a pointer to static storage that may then be overwritten by a
1006 subsequent call to basename().
1008 The basename() function need not be reentrant. A function that is not
1009 required to be reentrant is not required to be thread-safe.
1012 static char *Curl_basename(char *path)
1014 /* Ignore all the details above for now and make a quick and simple
1015 implementaion here */
1019 s1=strrchr(path, '/');
1020 s2=strrchr(path, '\\');
1023 path = (s1 > s2? s1 : s2)+1;
1034 static char *strippath(const char *fullfile)
1038 filename = strdup(fullfile); /* duplicate since basename() may ruin the
1039 buffer it works on */
1042 base = strdup(basename(filename));
1044 free(filename); /* free temporary buffer */
1046 return base; /* returns an allocated string or NULL ! */
1049 static CURLcode formdata_add_filename(const struct curl_httppost *file,
1050 struct FormData **form,
1053 CURLcode result = CURLE_OK;
1054 char *filename = file->showfilename;
1055 char *filebasename = NULL;
1056 char *filename_escaped = NULL;
1059 filebasename = strippath(file->contents);
1061 return CURLE_OUT_OF_MEMORY;
1062 filename = filebasename;
1065 if(strchr(filename, '\\') || strchr(filename, '"')) {
1068 /* filename need be escaped */
1069 filename_escaped = malloc(strlen(filename)*2+1);
1070 if(!filename_escaped) {
1072 return CURLE_OUT_OF_MEMORY;
1074 p0 = filename_escaped;
1077 if(*p1 == '\\' || *p1 == '"')
1082 filename = filename_escaped;
1084 result = AddFormDataf(form, size,
1085 "; filename=\"%s\"",
1087 free(filename_escaped);
1093 * Curl_getformdata() converts a linked list of "meta data" into a complete
1094 * (possibly huge) multipart formdata. The input list is in 'post', while the
1095 * output resulting linked lists gets stored in '*finalform'. *sizep will get
1096 * the total size of the whole POST.
1097 * A multipart/form_data content-type is built, unless a custom content-type
1098 * is passed in 'custom_content_type'.
1100 * This function will not do a failf() for the potential memory failures but
1101 * should for all other errors it spots. Just note that this function MAY get
1102 * a NULL pointer in the 'data' argument.
1105 CURLcode Curl_getformdata(struct SessionHandle *data,
1106 struct FormData **finalform,
1107 struct curl_httppost *post,
1108 const char *custom_content_type,
1111 struct FormData *form = NULL;
1112 struct FormData *firstform;
1113 struct curl_httppost *file;
1114 CURLcode result = CURLE_OK;
1116 curl_off_t size = 0; /* support potentially ENORMOUS formposts */
1118 char *fileboundary = NULL;
1119 struct curl_slist* curList;
1121 *finalform = NULL; /* default form is empty */
1124 return result; /* no input => no output! */
1126 boundary = formboundary(data);
1128 return CURLE_OUT_OF_MEMORY;
1130 /* Make the first line of the output */
1131 result = AddFormDataf(&form, NULL,
1132 "%s; boundary=%s\r\n",
1133 custom_content_type?custom_content_type:
1134 "Content-Type: multipart/form-data",
1141 /* we DO NOT include that line in the total size of the POST, since it'll be
1142 part of the header! */
1149 result = AddFormDataf(&form, &size, "\r\n");
1155 result = AddFormDataf(&form, &size, "--%s\r\n", boundary);
1159 /* Maybe later this should be disabled when a custom_content_type is
1160 passed, since Content-Disposition is not meaningful for all multipart
1163 result = AddFormDataf(&form, &size,
1164 "Content-Disposition: form-data; name=\"");
1168 result = AddFormData(&form, FORM_DATA, post->name, post->namelength,
1173 result = AddFormDataf(&form, &size, "\"");
1178 /* If used, this is a link to more file names, we must then do
1179 the magic to include several files with the same field name */
1182 fileboundary = formboundary(data);
1184 result = CURLE_OUT_OF_MEMORY;
1188 result = AddFormDataf(&form, &size,
1189 "\r\nContent-Type: multipart/mixed;"
1200 /* If 'showfilename' is set, that is a faked name passed on to us
1201 to use to in the formpost. If that is not set, the actually used
1202 local file name should be added. */
1205 /* if multiple-file */
1206 result = AddFormDataf(&form, &size,
1207 "\r\n--%s\r\nContent-Disposition: "
1212 result = formdata_add_filename(file, &form, &size);
1216 else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER|
1217 HTTPPOST_CALLBACK)) {
1218 /* it should be noted that for the HTTPPOST_FILENAME and
1219 HTTPPOST_CALLBACK cases the ->showfilename struct member is always
1220 assigned at this point */
1221 if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) {
1222 result = formdata_add_filename(post, &form, &size);
1229 if(file->contenttype) {
1230 /* we have a specified type */
1231 result = AddFormDataf(&form, &size,
1232 "\r\nContent-Type: %s",
1238 curList = file->contentheader;
1240 /* Process the additional headers specified for this form */
1241 result = AddFormDataf( &form, &size, "\r\n%s", curList->data );
1244 curList = curList->next;
1249 result = AddFormDataf(&form, &size, "\r\n\r\n");
1253 if((post->flags & HTTPPOST_FILENAME) ||
1254 (post->flags & HTTPPOST_READFILE)) {
1255 /* we should include the contents from the specified file */
1258 fileread = strequal("-", file->contents)?
1259 stdin:fopen(file->contents, "rb"); /* binary read for win32 */
1262 * VMS: This only allows for stream files on VMS. Stream files are
1263 * OK, as are FIXED & VAR files WITHOUT implied CC For implied CC,
1264 * every record needs to have a \n appended & 1 added to SIZE
1268 if(fileread != stdin) {
1269 /* close the file */
1271 /* add the file name only - for later reading from this */
1272 result = AddFormData(&form, FORM_FILE, file->contents, 0, &size);
1275 /* When uploading from stdin, we can't know the size of the file,
1276 * thus must read the full file as before. We *could* use chunked
1277 * transfer-encoding, but that only works for HTTP 1.1 and we
1278 * can't be sure we work with such a server.
1282 while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
1283 result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
1291 failf(data, "couldn't open file \"%s\"", file->contents);
1293 result = CURLE_READ_ERROR;
1296 else if(post->flags & HTTPPOST_BUFFER)
1297 /* include contents of buffer */
1298 result = AddFormData(&form, FORM_CONTENT, post->buffer,
1299 post->bufferlength, &size);
1300 else if(post->flags & HTTPPOST_CALLBACK)
1301 /* the contents should be read with the callback and the size
1302 is set with the contentslength */
1303 result = AddFormData(&form, FORM_CALLBACK, post->userp,
1304 post->contentslength, &size);
1306 /* include the contents we got */
1307 result = AddFormData(&form, FORM_CONTENT, post->contents,
1308 post->contentslength, &size);
1311 } while(file && !result); /* for each specified file for this field */
1317 /* this was a multiple-file inclusion, make a termination file
1319 result = AddFormDataf(&form, &size,
1326 } while((post = post->next) != NULL); /* for each field */
1328 /* end-boundary for everything */
1330 result = AddFormDataf(&form, &size, "\r\n--%s--\r\n", boundary);
1333 Curl_formclean(&firstform);
1344 *finalform = firstform;
1350 * Curl_FormInit() inits the struct 'form' points to with the 'formdata'
1351 * and resets the 'sent' counter.
1353 int Curl_FormInit(struct Form *form, struct FormData *formdata )
1356 return 1; /* error */
1358 form->data = formdata;
1361 form->fread_func = ZERO_NULL;
1367 # define fopen_read fopen
1372 * For upload to work as expected on VMS, different optional
1373 * parameters must be added to the fopen command based on
1374 * record format of the file.
1377 # define fopen_read vmsfopenread
1378 static FILE * vmsfopenread(const char *file, const char *mode) {
1379 struct_stat statbuf;
1382 result = stat(file, &statbuf);
1384 switch (statbuf.st_fab_rfm) {
1388 return fopen(file, "r"); /* VMS */
1391 return fopen(file, "r", "rfm=stmlf", "ctx=stm");
1399 * The read callback that this function may use can return a value larger than
1400 * 'size' (which then this function returns) that indicates a problem and it
1401 * must be properly dealt with
1403 static size_t readfromfile(struct Form *form, char *buffer,
1407 bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE;
1410 if(form->fread_func == ZERO_NULL)
1413 nread = form->fread_func(buffer, 1, size, form->data->line);
1417 /* this file hasn't yet been opened */
1418 form->fp = fopen_read(form->data->line, "rb"); /* b is for binary */
1420 return (size_t)-1; /* failure */
1422 nread = fread(buffer, 1, size, form->fp);
1425 /* this is the last chunk from the file, move on */
1430 form->data = form->data->next;
1437 * Curl_FormReader() is the fread() emulation function that will be used to
1438 * deliver the formdata to the transfer loop and then sent away to the peer.
1440 size_t Curl_FormReader(char *buffer,
1449 form=(struct Form *)mydata;
1451 wantedsize = size * nitems;
1454 return 0; /* nothing, error, empty */
1456 if((form->data->type == FORM_FILE) ||
1457 (form->data->type == FORM_CALLBACK)) {
1458 gotsize = readfromfile(form, buffer, wantedsize);
1461 /* If positive or -1, return. If zero, continue! */
1466 if((form->data->length - form->sent ) > wantedsize - gotsize) {
1468 memcpy(buffer + gotsize , form->data->line + form->sent,
1469 wantedsize - gotsize);
1471 form->sent += wantedsize-gotsize;
1476 memcpy(buffer+gotsize,
1477 form->data->line + form->sent,
1478 (form->data->length - form->sent) );
1479 gotsize += form->data->length - form->sent;
1483 form->data = form->data->next; /* advance */
1485 } while(form->data && (form->data->type < FORM_CALLBACK));
1486 /* If we got an empty line and we have more data, we proceed to the next
1487 line immediately to avoid returning zero before we've reached the end. */
1493 * Curl_formpostheader() returns the first line of the formpost, the
1494 * request-header part (which is not part of the request-body like the rest of
1497 char *Curl_formpostheader(void *formp, size_t *len)
1500 struct Form *form=(struct Form *)formp;
1503 return 0; /* nothing, ERROR! */
1505 header = form->data->line;
1506 *len = form->data->length;
1508 form->data = form->data->next; /* advance */
1514 * formboundary() creates a suitable boundary string and returns an allocated
1517 static char *formboundary(struct SessionHandle *data)
1519 /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
1521 return aprintf("------------------------%08x%08x",
1522 Curl_rand(data), Curl_rand(data));
1525 #else /* CURL_DISABLE_HTTP */
1526 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
1527 struct curl_httppost **last_post,
1532 return CURL_FORMADD_DISABLED;
1535 int curl_formget(struct curl_httppost *form, void *arg,
1536 curl_formget_callback append)
1541 return CURL_FORMADD_DISABLED;
1544 void curl_formfree(struct curl_httppost *form)
1547 /* does nothing HTTP is disabled */
1551 #endif /* !defined(CURL_DISABLE_HTTP) */