1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2022, 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.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 * SPDX-License-Identifier: curl
23 ***************************************************************************/
25 #include "curl_setup.h"
27 #include <curl/curl.h>
30 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)
32 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
36 #include "urldata.h" /* for struct Curl_easy */
38 #include "vtls/vtls.h"
44 /* The last 3 #include files should be in this order */
45 #include "curl_printf.h"
46 #include "curl_memory.h"
50 #define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
51 #define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
52 #define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
53 #define HTTPPOST_READFILE CURL_HTTPPOST_READFILE
54 #define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER
55 #define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK
56 #define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER
58 /***************************************************************************
62 * Adds a HttpPost structure to the list, if parent_post is given becomes
63 * a subpost of parent_post instead of a direct list element.
65 * Returns newly allocated HttpPost on success and NULL if malloc failed.
67 ***************************************************************************/
68 static struct curl_httppost *
69 AddHttpPost(char *name, size_t namelength,
70 char *value, curl_off_t contentslength,
71 char *buffer, size_t bufferlength,
74 struct curl_slist *contentHeader,
75 char *showfilename, char *userp,
76 struct curl_httppost *parent_post,
77 struct curl_httppost **httppost,
78 struct curl_httppost **last_post)
80 struct curl_httppost *post;
81 if(!namelength && name)
82 namelength = strlen(name);
83 if((bufferlength > LONG_MAX) || (namelength > LONG_MAX))
84 /* avoid overflow in typecasts below */
86 post = calloc(1, sizeof(struct curl_httppost));
89 post->namelength = (long)namelength;
90 post->contents = value;
91 post->contentlen = contentslength;
92 post->buffer = buffer;
93 post->bufferlength = (long)bufferlength;
94 post->contenttype = contenttype;
95 post->contentheader = contentHeader;
96 post->showfilename = showfilename;
98 post->flags = flags | CURL_HTTPPOST_LARGE;
104 /* now, point our 'more' to the original 'more' */
105 post->more = parent_post->more;
107 /* then move the original 'more' to point to ourselves */
108 parent_post->more = post;
111 /* make the previous point to this */
113 (*last_post)->next = post;
122 /***************************************************************************
126 * Adds a FormInfo structure to the list presented by parent_form_info.
128 * Returns newly allocated FormInfo on success and NULL if malloc failed/
129 * parent_form_info is NULL.
131 ***************************************************************************/
132 static struct FormInfo *AddFormInfo(char *value,
134 struct FormInfo *parent_form_info)
136 struct FormInfo *form_info;
137 form_info = calloc(1, sizeof(struct FormInfo));
140 form_info->value = value;
142 form_info->contenttype = contenttype;
143 form_info->flags = HTTPPOST_FILENAME;
148 if(parent_form_info) {
149 /* now, point our 'more' to the original 'more' */
150 form_info->more = parent_form_info->more;
152 /* then move the original 'more' to point to ourselves */
153 parent_form_info->more = form_info;
159 /***************************************************************************
163 * Stores a formpost parameter and builds the appropriate linked list.
165 * Has two principal functionalities: using files and byte arrays as
166 * post parts. Byte arrays are either copied or just the pointer is stored
167 * (as the user requests) while for files only the filename and not the
170 * While you may have only one byte array for each name, multiple filenames
171 * are allowed (and because of this feature CURLFORM_END is needed after
172 * using CURLFORM_FILE).
176 * Simple name/value pair with copied contents:
177 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
178 * CURLFORM_COPYCONTENTS, "value", CURLFORM_END);
180 * name/value pair where only the content pointer is remembered:
181 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
182 * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END);
183 * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used)
185 * storing a filename (CONTENTTYPE is optional!):
186 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
187 * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text",
190 * storing multiple filenames:
191 * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name",
192 * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END);
195 * CURL_FORMADD_OK on success
196 * CURL_FORMADD_MEMORY if the FormInfo allocation fails
197 * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form
198 * CURL_FORMADD_NULL if a null pointer was given for a char
199 * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
200 * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
201 * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
202 * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated
203 * CURL_FORMADD_MEMORY if some allocation for string copying failed.
204 * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
206 ***************************************************************************/
209 CURLFORMcode FormAdd(struct curl_httppost **httppost,
210 struct curl_httppost **last_post,
213 struct FormInfo *first_form, *current_form, *form = NULL;
214 CURLFORMcode return_value = CURL_FORMADD_OK;
215 const char *prevtype = NULL;
216 struct curl_httppost *post = NULL;
217 CURLformoption option;
218 struct curl_forms *forms = NULL;
219 char *array_value = NULL; /* value read from an array */
221 /* This is a state variable, that if TRUE means that we're parsing an
222 array that we got passed to us. If FALSE we're parsing the input
223 va_list arguments. */
224 bool array_state = FALSE;
227 * We need to allocate the first struct to fill in.
229 first_form = calloc(1, sizeof(struct FormInfo));
231 return CURL_FORMADD_MEMORY;
233 current_form = first_form;
236 * Loop through all the options set. Break if we have an error to report.
238 while(return_value == CURL_FORMADD_OK) {
240 /* first see if we have more parts of the array param */
241 if(array_state && forms) {
242 /* get the upcoming option from the given array */
243 option = forms->option;
244 array_value = (char *)forms->value;
246 forms++; /* advance this to next entry */
247 if(CURLFORM_END == option) {
248 /* end of array state */
254 /* This is not array-state, get next option. This gets an 'int' with
255 va_arg() because CURLformoption might be a smaller type than int and
256 might cause compiler warnings and wrong behavior. */
257 option = (CURLformoption)va_arg(params, int);
258 if(CURLFORM_END == option)
265 /* we don't support an array from within an array */
266 return_value = CURL_FORMADD_ILLEGAL_ARRAY;
268 forms = va_arg(params, struct curl_forms *);
272 return_value = CURL_FORMADD_NULL;
277 * Set the Name property.
279 case CURLFORM_PTRNAME:
280 current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
283 case CURLFORM_COPYNAME:
284 if(current_form->name)
285 return_value = CURL_FORMADD_OPTION_TWICE;
287 char *name = array_state?
288 array_value:va_arg(params, char *);
290 current_form->name = name; /* store for the moment */
292 return_value = CURL_FORMADD_NULL;
295 case CURLFORM_NAMELENGTH:
296 if(current_form->namelength)
297 return_value = CURL_FORMADD_OPTION_TWICE;
299 current_form->namelength =
300 array_state?(size_t)array_value:(size_t)va_arg(params, long);
304 * Set the contents property.
306 case CURLFORM_PTRCONTENTS:
307 current_form->flags |= HTTPPOST_PTRCONTENTS;
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 */
526 struct FormInfo *ptr;
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 null-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 */
655 struct FormInfo *ptr;
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 struct 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);
733 if(nread > sizeof(buffer) || append(arg, buffer, nread) != nread) {
734 result = CURLE_READ_ERROR;
735 if(nread == CURL_READFUNC_ABORT)
736 result = CURLE_ABORTED_BY_CALLBACK;
740 Curl_mime_cleanpart(&toppart);
745 * curl_formfree() is an external function to free up a whole form post
748 void curl_formfree(struct curl_httppost *form)
750 struct curl_httppost *next;
753 /* no form to free, just get out of this */
757 next = form->next; /* the following form line */
759 /* recurse to sub-contents */
760 curl_formfree(form->more);
762 if(!(form->flags & HTTPPOST_PTRNAME))
763 free(form->name); /* free the name */
765 (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK))
767 free(form->contents); /* free the contents */
768 free(form->contenttype); /* free the content type */
769 free(form->showfilename); /* free the faked file name */
770 free(form); /* free the struct */
772 } while(form); /* continue */
776 /* Set mime part name, taking care of non null-terminated name string. */
777 static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
783 return curl_mime_name(part, name);
784 zname = malloc(len + 1);
786 return CURLE_OUT_OF_MEMORY;
787 memcpy(zname, name, len);
789 res = curl_mime_name(part, zname);
795 * Curl_getformdata() converts a linked list of "meta data" into a mime
796 * structure. The input list is in 'post', while the output is stored in
797 * mime part at '*finalform'.
799 * This function will not do a failf() for the potential memory failures but
800 * should for all other errors it spots. Just note that this function MAY get
801 * a NULL pointer in the 'data' argument.
804 CURLcode Curl_getformdata(struct Curl_easy *data,
805 curl_mimepart *finalform,
806 struct curl_httppost *post,
807 curl_read_callback fread_func)
809 CURLcode result = CURLE_OK;
810 curl_mime *form = NULL;
812 struct curl_httppost *file;
814 Curl_mime_cleanpart(finalform); /* default form is empty */
817 return result; /* no input => no output! */
819 form = curl_mime_init(data);
821 result = CURLE_OUT_OF_MEMORY;
824 result = curl_mime_subparts(finalform, form);
826 /* Process each top part. */
827 for(; !result && post; post = post->next) {
828 /* If we have more than a file here, create a mime subpart and fill it. */
829 curl_mime *multipart = form;
831 part = curl_mime_addpart(form);
833 result = CURLE_OUT_OF_MEMORY;
835 result = setname(part, post->name, post->namelength);
837 multipart = curl_mime_init(data);
839 result = CURLE_OUT_OF_MEMORY;
842 result = curl_mime_subparts(part, multipart);
845 /* Generate all the part contents. */
846 for(file = post; !result && file; file = file->more) {
847 /* Create the part. */
848 part = curl_mime_addpart(multipart);
850 result = CURLE_OUT_OF_MEMORY;
852 /* Set the headers. */
854 result = curl_mime_headers(part, file->contentheader, 0);
856 /* Set the content type. */
857 if(!result && file->contenttype)
858 result = curl_mime_type(part, file->contenttype);
860 /* Set field name. */
861 if(!result && !post->more)
862 result = setname(part, post->name, post->namelength);
864 /* Process contents. */
866 curl_off_t clen = post->contentslength;
868 if(post->flags & CURL_HTTPPOST_LARGE)
869 clen = post->contentlen;
871 if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) {
872 if(!strcmp(file->contents, "-")) {
873 /* There are a few cases where the code below won't work; in
874 particular, freopen(stdin) by the caller is not guaranteed
875 to result as expected. This feature has been kept for backward
876 compatibility: use of "-" pseudo file name should be avoided. */
877 result = curl_mime_data_cb(part, (curl_off_t) -1,
878 (curl_read_callback) fread,
879 CURLX_FUNCTION_CAST(curl_seek_callback,
881 NULL, (void *) stdin);
884 result = curl_mime_filedata(part, file->contents);
885 if(!result && (post->flags & HTTPPOST_READFILE))
886 result = curl_mime_filename(part, NULL);
888 else if(post->flags & HTTPPOST_BUFFER)
889 result = curl_mime_data(part, post->buffer,
890 post->bufferlength? post->bufferlength: -1);
891 else if(post->flags & HTTPPOST_CALLBACK) {
892 /* the contents should be read with the callback and the size is set
893 with the contentslength */
896 result = curl_mime_data_cb(part, clen,
897 fread_func, NULL, NULL, post->userp);
902 uclen = CURL_ZERO_TERMINATED;
904 uclen = (size_t)clen;
905 result = curl_mime_data(part, post->contents, uclen);
909 /* Set fake file name. */
910 if(!result && post->showfilename)
911 if(post->more || (post->flags & (HTTPPOST_FILENAME | HTTPPOST_BUFFER |
913 result = curl_mime_filename(part, post->showfilename);
918 Curl_mime_cleanpart(finalform);
925 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
926 struct curl_httppost **last_post,
931 return CURL_FORMADD_DISABLED;
934 int curl_formget(struct curl_httppost *form, void *arg,
935 curl_formget_callback append)
940 return CURL_FORMADD_DISABLED;
943 void curl_formfree(struct curl_httppost *form)
946 /* does nothing HTTP is disabled */
949 #endif /* if disabled */