1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2018, 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 */
36 #include "non-ascii.h"
37 #include "vtls/vtls.h"
42 /* The last 3 #include files should be in this order */
43 #include "curl_printf.h"
44 #include "curl_memory.h"
48 /* What kind of Content-Type to use on un-specified files with unrecognized
50 #define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
52 #define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
53 #define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
54 #define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
55 #define HTTPPOST_READFILE CURL_HTTPPOST_READFILE
56 #define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER
57 #define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK
58 #define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER
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, curl_off_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->contentlen = contentslength;
89 post->buffer = buffer;
90 post->bufferlength = (long)bufferlength;
91 post->contenttype = contenttype;
92 post->contentheader = contentHeader;
93 post->showfilename = showfilename;
95 post->flags = flags | CURL_HTTPPOST_LARGE;
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 /***************************************************************************
160 * Stores a formpost parameter and builds the appropriate linked list.
162 * Has two principal functionalities: using files and byte arrays as
163 * post parts. Byte arrays are either copied or just the pointer is stored
164 * (as the user requests) while for files only the filename and not the
167 * While you may have only one byte array for each name, multiple filenames
168 * are allowed (and because of this feature CURLFORM_END is needed after
169 * using CURLFORM_FILE).
173 * Simple name/value pair with copied contents:
174 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
175 * CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
177 * name/value pair where only the content pointer is remembered:
178 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
179 * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END);
180 * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
182 * storing a filename (CONTENTTYPE is optional!):
183 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
184 * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text",
187 * storing multiple filenames:
188 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
189 * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
192 * CURL_FORMADD_OK on success
193 * CURL_FORMADD_MEMORY if the FormInfo allocation fails
194 * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
195 * CURL_FORMADD_NULL if a null pointer was given for a char
196 * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
197 * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
198 * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
199 * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated
200 * CURL_FORMADD_MEMORY if some allocation for string copying failed.
201 * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
203 ***************************************************************************/
206 CURLFORMcode FormAdd(struct curl_httppost **httppost,
207 struct curl_httppost **last_post,
210 FormInfo *first_form, *current_form, *form = NULL;
211 CURLFORMcode return_value = CURL_FORMADD_OK;
212 const char *prevtype = NULL;
213 struct curl_httppost *post = NULL;
214 CURLformoption option;
215 struct curl_forms *forms = NULL;
216 char *array_value = NULL; /* value read from an array */
218 /* This is a state variable, that if TRUE means that we're parsing an
219 array that we got passed to us. If FALSE we're parsing the input
220 va_list arguments. */
221 bool array_state = FALSE;
224 * We need to allocate the first struct to fill in.
226 first_form = calloc(1, sizeof(struct FormInfo));
228 return CURL_FORMADD_MEMORY;
230 current_form = first_form;
233 * Loop through all the options set. Break if we have an error to report.
235 while(return_value == CURL_FORMADD_OK) {
237 /* first see if we have more parts of the array param */
238 if(array_state && forms) {
239 /* get the upcoming option from the given array */
240 option = forms->option;
241 array_value = (char *)forms->value;
243 forms++; /* advance this to next entry */
244 if(CURLFORM_END == option) {
245 /* end of array state */
251 /* This is not array-state, get next option */
252 option = va_arg(params, CURLformoption);
253 if(CURLFORM_END == option)
260 /* we don't support an array from within an array */
261 return_value = CURL_FORMADD_ILLEGAL_ARRAY;
263 forms = va_arg(params, struct curl_forms *);
267 return_value = CURL_FORMADD_NULL;
272 * Set the Name property.
274 case CURLFORM_PTRNAME:
275 #ifdef CURL_DOES_CONVERSIONS
276 /* Treat CURLFORM_PTR like CURLFORM_COPYNAME so that libcurl will copy
277 * the data in all cases so that we'll have safe memory for the eventual
281 current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
284 case CURLFORM_COPYNAME:
285 if(current_form->name)
286 return_value = CURL_FORMADD_OPTION_TWICE;
288 char *name = array_state?
289 array_value:va_arg(params, char *);
291 current_form->name = name; /* store for the moment */
293 return_value = CURL_FORMADD_NULL;
296 case CURLFORM_NAMELENGTH:
297 if(current_form->namelength)
298 return_value = CURL_FORMADD_OPTION_TWICE;
300 current_form->namelength =
301 array_state?(size_t)array_value:(size_t)va_arg(params, long);
305 * Set the contents property.
307 case CURLFORM_PTRCONTENTS:
308 current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
309 case CURLFORM_COPYCONTENTS:
310 if(current_form->value)
311 return_value = CURL_FORMADD_OPTION_TWICE;
314 array_state?array_value:va_arg(params, char *);
316 current_form->value = value; /* store for the moment */
318 return_value = CURL_FORMADD_NULL;
321 case CURLFORM_CONTENTSLENGTH:
322 current_form->contentslength =
323 array_state?(size_t)array_value:(size_t)va_arg(params, long);
326 case CURLFORM_CONTENTLEN:
327 current_form->flags |= CURL_HTTPPOST_LARGE;
328 current_form->contentslength =
329 array_state?(curl_off_t)(size_t)array_value:va_arg(params, curl_off_t);
332 /* Get contents from a given file name */
333 case CURLFORM_FILECONTENT:
334 if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
335 return_value = CURL_FORMADD_OPTION_TWICE;
337 const char *filename = array_state?
338 array_value:va_arg(params, char *);
340 current_form->value = strdup(filename);
341 if(!current_form->value)
342 return_value = CURL_FORMADD_MEMORY;
344 current_form->flags |= HTTPPOST_READFILE;
345 current_form->value_alloc = TRUE;
349 return_value = CURL_FORMADD_NULL;
353 /* We upload a file */
356 const char *filename = array_state?array_value:
357 va_arg(params, char *);
359 if(current_form->value) {
360 if(current_form->flags & HTTPPOST_FILENAME) {
362 char *fname = strdup(filename);
364 return_value = CURL_FORMADD_MEMORY;
366 form = AddFormInfo(fname, NULL, current_form);
369 return_value = CURL_FORMADD_MEMORY;
372 form->value_alloc = TRUE;
379 return_value = CURL_FORMADD_NULL;
382 return_value = CURL_FORMADD_OPTION_TWICE;
386 current_form->value = strdup(filename);
387 if(!current_form->value)
388 return_value = CURL_FORMADD_MEMORY;
390 current_form->flags |= HTTPPOST_FILENAME;
391 current_form->value_alloc = TRUE;
395 return_value = CURL_FORMADD_NULL;
400 case CURLFORM_BUFFERPTR:
401 current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER;
402 if(current_form->buffer)
403 return_value = CURL_FORMADD_OPTION_TWICE;
406 array_state?array_value:va_arg(params, char *);
408 current_form->buffer = buffer; /* store for the moment */
409 current_form->value = buffer; /* make it non-NULL to be accepted
413 return_value = CURL_FORMADD_NULL;
417 case CURLFORM_BUFFERLENGTH:
418 if(current_form->bufferlength)
419 return_value = CURL_FORMADD_OPTION_TWICE;
421 current_form->bufferlength =
422 array_state?(size_t)array_value:(size_t)va_arg(params, long);
425 case CURLFORM_STREAM:
426 current_form->flags |= HTTPPOST_CALLBACK;
427 if(current_form->userp)
428 return_value = CURL_FORMADD_OPTION_TWICE;
431 array_state?array_value:va_arg(params, char *);
433 current_form->userp = userp;
434 current_form->value = userp; /* this isn't strictly true but we
435 derive a value from this later on
436 and we need this non-NULL to be
437 accepted as a fine form part */
440 return_value = CURL_FORMADD_NULL;
444 case CURLFORM_CONTENTTYPE:
446 const char *contenttype =
447 array_state?array_value:va_arg(params, char *);
448 if(current_form->contenttype) {
449 if(current_form->flags & HTTPPOST_FILENAME) {
451 char *type = strdup(contenttype);
453 return_value = CURL_FORMADD_MEMORY;
455 form = AddFormInfo(NULL, type, current_form);
458 return_value = CURL_FORMADD_MEMORY;
461 form->contenttype_alloc = TRUE;
468 return_value = CURL_FORMADD_NULL;
471 return_value = CURL_FORMADD_OPTION_TWICE;
475 current_form->contenttype = strdup(contenttype);
476 if(!current_form->contenttype)
477 return_value = CURL_FORMADD_MEMORY;
479 current_form->contenttype_alloc = TRUE;
482 return_value = CURL_FORMADD_NULL;
486 case CURLFORM_CONTENTHEADER:
488 /* this "cast increases required alignment of target type" but
489 we consider it OK anyway */
490 struct curl_slist *list = array_state?
491 (struct curl_slist *)(void *)array_value:
492 va_arg(params, struct curl_slist *);
494 if(current_form->contentheader)
495 return_value = CURL_FORMADD_OPTION_TWICE;
497 current_form->contentheader = list;
501 case CURLFORM_FILENAME:
502 case CURLFORM_BUFFER:
504 const char *filename = array_state?array_value:
505 va_arg(params, char *);
506 if(current_form->showfilename)
507 return_value = CURL_FORMADD_OPTION_TWICE;
509 current_form->showfilename = strdup(filename);
510 if(!current_form->showfilename)
511 return_value = CURL_FORMADD_MEMORY;
513 current_form->showfilename_alloc = TRUE;
518 return_value = CURL_FORMADD_UNKNOWN_OPTION;
523 if(CURL_FORMADD_OK != return_value) {
524 /* On error, free allocated fields for all nodes of the FormInfo linked
525 list without deallocating nodes. List nodes are deallocated later on */
527 for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
528 if(ptr->name_alloc) {
529 Curl_safefree(ptr->name);
530 ptr->name_alloc = FALSE;
532 if(ptr->value_alloc) {
533 Curl_safefree(ptr->value);
534 ptr->value_alloc = FALSE;
536 if(ptr->contenttype_alloc) {
537 Curl_safefree(ptr->contenttype);
538 ptr->contenttype_alloc = FALSE;
540 if(ptr->showfilename_alloc) {
541 Curl_safefree(ptr->showfilename);
542 ptr->showfilename_alloc = FALSE;
547 if(CURL_FORMADD_OK == return_value) {
548 /* go through the list, check for completeness and if everything is
549 * alright add the HttpPost item otherwise set return_value accordingly */
552 for(form = first_form;
555 if(((!form->name || !form->value) && !post) ||
556 ( (form->contentslength) &&
557 (form->flags & HTTPPOST_FILENAME) ) ||
558 ( (form->flags & HTTPPOST_FILENAME) &&
559 (form->flags & HTTPPOST_PTRCONTENTS) ) ||
562 (form->flags & HTTPPOST_BUFFER) &&
563 (form->flags & HTTPPOST_PTRBUFFER) ) ||
565 ( (form->flags & HTTPPOST_READFILE) &&
566 (form->flags & HTTPPOST_PTRCONTENTS) )
568 return_value = CURL_FORMADD_INCOMPLETE;
571 if(((form->flags & HTTPPOST_FILENAME) ||
572 (form->flags & HTTPPOST_BUFFER)) &&
573 !form->contenttype) {
574 char *f = form->flags & HTTPPOST_BUFFER?
575 form->showfilename : form->value;
577 type = Curl_mime_contenttype(f);
581 type = FILE_CONTENTTYPE_DEFAULT;
583 /* our contenttype is missing */
584 form->contenttype = strdup(type);
585 if(!form->contenttype) {
586 return_value = CURL_FORMADD_MEMORY;
589 form->contenttype_alloc = TRUE;
591 if(form->name && form->namelength) {
592 /* Name should not contain nul bytes. */
594 for(i = 0; i < form->namelength; i++)
596 return_value = CURL_FORMADD_NULL;
599 if(return_value != CURL_FORMADD_OK)
602 if(!(form->flags & HTTPPOST_PTRNAME) &&
603 (form == first_form) ) {
604 /* Note that there's small risk that form->name is NULL here if the
605 app passed in a bad combo, so we better check for that first. */
607 /* copy name (without strdup; possibly not nul-terminated) */
608 form->name = Curl_memdup(form->name, form->namelength?
610 strlen(form->name) + 1);
613 return_value = CURL_FORMADD_MEMORY;
616 form->name_alloc = TRUE;
618 if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE |
619 HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
620 HTTPPOST_CALLBACK)) && form->value) {
621 /* copy value (without strdup; possibly contains null characters) */
622 size_t clen = (size_t) form->contentslength;
624 clen = strlen(form->value) + 1;
626 form->value = Curl_memdup(form->value, clen);
629 return_value = CURL_FORMADD_MEMORY;
632 form->value_alloc = TRUE;
634 post = AddHttpPost(form->name, form->namelength,
635 form->value, form->contentslength,
636 form->buffer, form->bufferlength,
637 form->contenttype, form->flags,
638 form->contentheader, form->showfilename,
644 return_value = CURL_FORMADD_MEMORY;
648 if(form->contenttype)
649 prevtype = form->contenttype;
651 if(CURL_FORMADD_OK != return_value) {
652 /* On error, free allocated fields for nodes of the FormInfo linked
653 list which are not already owned by the httppost linked list
654 without deallocating nodes. List nodes are deallocated later on */
656 for(ptr = form; ptr != NULL; ptr = ptr->more) {
657 if(ptr->name_alloc) {
658 Curl_safefree(ptr->name);
659 ptr->name_alloc = FALSE;
661 if(ptr->value_alloc) {
662 Curl_safefree(ptr->value);
663 ptr->value_alloc = FALSE;
665 if(ptr->contenttype_alloc) {
666 Curl_safefree(ptr->contenttype);
667 ptr->contenttype_alloc = FALSE;
669 if(ptr->showfilename_alloc) {
670 Curl_safefree(ptr->showfilename);
671 ptr->showfilename_alloc = FALSE;
677 /* Always deallocate FormInfo linked list nodes without touching node
678 fields given that these have either been deallocated or are owned
679 now by the httppost linked list */
681 FormInfo *ptr = first_form->more;
690 * curl_formadd() is a public API to add a section to the multipart formpost.
695 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
696 struct curl_httppost **last_post,
701 va_start(arg, last_post);
702 result = FormAdd(httppost, last_post, arg);
709 * Serialize a curl_httppost struct.
710 * Returns 0 on success.
714 int curl_formget(struct curl_httppost *form, void *arg,
715 curl_formget_callback append)
718 curl_mimepart toppart;
720 Curl_mime_initpart(&toppart, NULL); /* default form is empty */
721 result = Curl_getformdata(NULL, &toppart, form, NULL);
723 result = Curl_mime_prepare_headers(&toppart, "multipart/form-data",
724 NULL, MIMESTRATEGY_FORM);
728 size_t nread = Curl_mime_read(buffer, 1, sizeof buffer, &toppart);
735 if(append(arg, buffer, nread) != nread)
736 result = CURLE_READ_ERROR;
738 case CURL_READFUNC_ABORT:
739 case CURL_READFUNC_PAUSE:
744 Curl_mime_cleanpart(&toppart);
749 * curl_formfree() is an external function to free up a whole form post
752 void curl_formfree(struct curl_httppost *form)
754 struct curl_httppost *next;
757 /* no form to free, just get out of this */
761 next = form->next; /* the following form line */
763 /* recurse to sub-contents */
764 curl_formfree(form->more);
766 if(!(form->flags & HTTPPOST_PTRNAME))
767 free(form->name); /* free the name */
769 (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK))
771 free(form->contents); /* free the contents */
772 free(form->contenttype); /* free the content type */
773 free(form->showfilename); /* free the faked file name */
774 free(form); /* free the struct */
776 } while(form); /* continue */
780 /* Set mime part name, taking care of non nul-terminated name string. */
781 static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
787 return curl_mime_name(part, name);
788 zname = malloc(len + 1);
790 return CURLE_OUT_OF_MEMORY;
791 memcpy(zname, name, len);
793 res = curl_mime_name(part, zname);
799 * Curl_getformdata() converts a linked list of "meta data" into a mime
800 * structure. The input list is in 'post', while the output is stored in
801 * mime part at '*finalform'.
803 * This function will not do a failf() for the potential memory failures but
804 * should for all other errors it spots. Just note that this function MAY get
805 * a NULL pointer in the 'data' argument.
808 CURLcode Curl_getformdata(struct Curl_easy *data,
809 curl_mimepart *finalform,
810 struct curl_httppost *post,
811 curl_read_callback fread_func)
813 CURLcode result = CURLE_OK;
814 curl_mime *form = NULL;
815 curl_mime *multipart;
817 struct curl_httppost *file;
819 Curl_mime_cleanpart(finalform); /* default form is empty */
822 return result; /* no input => no output! */
824 form = curl_mime_init(data);
826 result = CURLE_OUT_OF_MEMORY;
829 result = curl_mime_subparts(finalform, form);
831 /* Process each top part. */
832 for(; !result && post; post = post->next) {
833 /* If we have more than a file here, create a mime subpart and fill it. */
836 part = curl_mime_addpart(form);
838 result = CURLE_OUT_OF_MEMORY;
840 result = setname(part, post->name, post->namelength);
842 multipart = curl_mime_init(data);
844 result = CURLE_OUT_OF_MEMORY;
847 result = curl_mime_subparts(part, multipart);
850 /* Generate all the part contents. */
851 for(file = post; !result && file; file = file->more) {
852 /* Create the part. */
853 part = curl_mime_addpart(multipart);
855 result = CURLE_OUT_OF_MEMORY;
857 /* Set the headers. */
859 result = curl_mime_headers(part, file->contentheader, 0);
861 /* Set the content type. */
862 if(!result && file->contenttype)
863 result = curl_mime_type(part, file->contenttype);
865 /* Set field name. */
866 if(!result && !post->more)
867 result = setname(part, post->name, post->namelength);
869 /* Process contents. */
871 curl_off_t clen = post->contentslength;
873 if(post->flags & CURL_HTTPPOST_LARGE)
874 clen = post->contentlen;
878 if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) {
879 if(!strcmp(file->contents, "-")) {
880 /* There are a few cases where the code below won't work; in
881 particular, freopen(stdin) by the caller is not guaranteed
882 to result as expected. This feature has been kept for backward
883 compatibility: use of "-" pseudo file name should be avoided. */
884 result = curl_mime_data_cb(part, (curl_off_t) -1,
885 (curl_read_callback) fread,
886 (curl_seek_callback) fseek,
887 NULL, (void *) stdin);
890 result = curl_mime_filedata(part, file->contents);
891 if(!result && (post->flags & HTTPPOST_READFILE))
892 result = curl_mime_filename(part, NULL);
894 else if(post->flags & HTTPPOST_BUFFER)
895 result = curl_mime_data(part, post->buffer,
896 post->bufferlength? post->bufferlength: -1);
897 else if(post->flags & HTTPPOST_CALLBACK)
898 /* the contents should be read with the callback and the size is set
899 with the contentslength */
900 result = curl_mime_data_cb(part, clen,
901 fread_func, NULL, NULL, post->userp);
903 result = curl_mime_data(part, post->contents, (ssize_t) clen);
904 #ifdef CURL_DOES_CONVERSIONS
905 /* Convert textual contents now. */
906 if(!result && data && part->datasize)
907 result = Curl_convert_to_network(data, part->data, part->datasize);
912 /* Set fake file name. */
913 if(!result && post->showfilename)
914 if(post->more || (post->flags & (HTTPPOST_FILENAME | HTTPPOST_BUFFER |
916 result = curl_mime_filename(part, post->showfilename);
921 Curl_mime_cleanpart(finalform);
926 #else /* CURL_DISABLE_HTTP */
927 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
928 struct curl_httppost **last_post,
933 return CURL_FORMADD_DISABLED;
936 int curl_formget(struct curl_httppost *form, void *arg,
937 curl_formget_callback append)
942 return CURL_FORMADD_DISABLED;
945 void curl_formfree(struct curl_httppost *form)
948 /* does nothing HTTP is disabled */
952 #endif /* !defined(CURL_DISABLE_HTTP) */