113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci 2513498266Sopenharmony_ci#include "curl_setup.h" 2613498266Sopenharmony_ci 2713498266Sopenharmony_ci#include <curl/curl.h> 2813498266Sopenharmony_ci 2913498266Sopenharmony_ci#include "formdata.h" 3013498266Sopenharmony_ci#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_FORM_API) 3113498266Sopenharmony_ci 3213498266Sopenharmony_ci#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME) 3313498266Sopenharmony_ci#include <libgen.h> 3413498266Sopenharmony_ci#endif 3513498266Sopenharmony_ci 3613498266Sopenharmony_ci#include "urldata.h" /* for struct Curl_easy */ 3713498266Sopenharmony_ci#include "mime.h" 3813498266Sopenharmony_ci#include "vtls/vtls.h" 3913498266Sopenharmony_ci#include "strcase.h" 4013498266Sopenharmony_ci#include "sendf.h" 4113498266Sopenharmony_ci#include "strdup.h" 4213498266Sopenharmony_ci#include "rand.h" 4313498266Sopenharmony_ci#include "warnless.h" 4413498266Sopenharmony_ci/* The last 3 #include files should be in this order */ 4513498266Sopenharmony_ci#include "curl_printf.h" 4613498266Sopenharmony_ci#include "curl_memory.h" 4713498266Sopenharmony_ci#include "memdebug.h" 4813498266Sopenharmony_ci 4913498266Sopenharmony_ci 5013498266Sopenharmony_ci#define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME 5113498266Sopenharmony_ci#define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME 5213498266Sopenharmony_ci#define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS 5313498266Sopenharmony_ci#define HTTPPOST_READFILE CURL_HTTPPOST_READFILE 5413498266Sopenharmony_ci#define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER 5513498266Sopenharmony_ci#define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK 5613498266Sopenharmony_ci#define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER 5713498266Sopenharmony_ci 5813498266Sopenharmony_ci/*************************************************************************** 5913498266Sopenharmony_ci * 6013498266Sopenharmony_ci * AddHttpPost() 6113498266Sopenharmony_ci * 6213498266Sopenharmony_ci * Adds an HttpPost structure to the list, if parent_post is given becomes 6313498266Sopenharmony_ci * a subpost of parent_post instead of a direct list element. 6413498266Sopenharmony_ci * 6513498266Sopenharmony_ci * Returns newly allocated HttpPost on success and NULL if malloc failed. 6613498266Sopenharmony_ci * 6713498266Sopenharmony_ci ***************************************************************************/ 6813498266Sopenharmony_cistatic struct curl_httppost * 6913498266Sopenharmony_ciAddHttpPost(char *name, size_t namelength, 7013498266Sopenharmony_ci char *value, curl_off_t contentslength, 7113498266Sopenharmony_ci char *buffer, size_t bufferlength, 7213498266Sopenharmony_ci char *contenttype, 7313498266Sopenharmony_ci long flags, 7413498266Sopenharmony_ci struct curl_slist *contentHeader, 7513498266Sopenharmony_ci char *showfilename, char *userp, 7613498266Sopenharmony_ci struct curl_httppost *parent_post, 7713498266Sopenharmony_ci struct curl_httppost **httppost, 7813498266Sopenharmony_ci struct curl_httppost **last_post) 7913498266Sopenharmony_ci{ 8013498266Sopenharmony_ci struct curl_httppost *post; 8113498266Sopenharmony_ci if(!namelength && name) 8213498266Sopenharmony_ci namelength = strlen(name); 8313498266Sopenharmony_ci if((bufferlength > LONG_MAX) || (namelength > LONG_MAX)) 8413498266Sopenharmony_ci /* avoid overflow in typecasts below */ 8513498266Sopenharmony_ci return NULL; 8613498266Sopenharmony_ci post = calloc(1, sizeof(struct curl_httppost)); 8713498266Sopenharmony_ci if(post) { 8813498266Sopenharmony_ci post->name = name; 8913498266Sopenharmony_ci post->namelength = (long)namelength; 9013498266Sopenharmony_ci post->contents = value; 9113498266Sopenharmony_ci post->contentlen = contentslength; 9213498266Sopenharmony_ci post->buffer = buffer; 9313498266Sopenharmony_ci post->bufferlength = (long)bufferlength; 9413498266Sopenharmony_ci post->contenttype = contenttype; 9513498266Sopenharmony_ci post->contentheader = contentHeader; 9613498266Sopenharmony_ci post->showfilename = showfilename; 9713498266Sopenharmony_ci post->userp = userp; 9813498266Sopenharmony_ci post->flags = flags | CURL_HTTPPOST_LARGE; 9913498266Sopenharmony_ci } 10013498266Sopenharmony_ci else 10113498266Sopenharmony_ci return NULL; 10213498266Sopenharmony_ci 10313498266Sopenharmony_ci if(parent_post) { 10413498266Sopenharmony_ci /* now, point our 'more' to the original 'more' */ 10513498266Sopenharmony_ci post->more = parent_post->more; 10613498266Sopenharmony_ci 10713498266Sopenharmony_ci /* then move the original 'more' to point to ourselves */ 10813498266Sopenharmony_ci parent_post->more = post; 10913498266Sopenharmony_ci } 11013498266Sopenharmony_ci else { 11113498266Sopenharmony_ci /* make the previous point to this */ 11213498266Sopenharmony_ci if(*last_post) 11313498266Sopenharmony_ci (*last_post)->next = post; 11413498266Sopenharmony_ci else 11513498266Sopenharmony_ci (*httppost) = post; 11613498266Sopenharmony_ci 11713498266Sopenharmony_ci (*last_post) = post; 11813498266Sopenharmony_ci } 11913498266Sopenharmony_ci return post; 12013498266Sopenharmony_ci} 12113498266Sopenharmony_ci 12213498266Sopenharmony_ci/*************************************************************************** 12313498266Sopenharmony_ci * 12413498266Sopenharmony_ci * AddFormInfo() 12513498266Sopenharmony_ci * 12613498266Sopenharmony_ci * Adds a FormInfo structure to the list presented by parent_form_info. 12713498266Sopenharmony_ci * 12813498266Sopenharmony_ci * Returns newly allocated FormInfo on success and NULL if malloc failed/ 12913498266Sopenharmony_ci * parent_form_info is NULL. 13013498266Sopenharmony_ci * 13113498266Sopenharmony_ci ***************************************************************************/ 13213498266Sopenharmony_cistatic struct FormInfo *AddFormInfo(char *value, 13313498266Sopenharmony_ci char *contenttype, 13413498266Sopenharmony_ci struct FormInfo *parent_form_info) 13513498266Sopenharmony_ci{ 13613498266Sopenharmony_ci struct FormInfo *form_info; 13713498266Sopenharmony_ci form_info = calloc(1, sizeof(struct FormInfo)); 13813498266Sopenharmony_ci if(!form_info) 13913498266Sopenharmony_ci return NULL; 14013498266Sopenharmony_ci if(value) 14113498266Sopenharmony_ci form_info->value = value; 14213498266Sopenharmony_ci if(contenttype) 14313498266Sopenharmony_ci form_info->contenttype = contenttype; 14413498266Sopenharmony_ci form_info->flags = HTTPPOST_FILENAME; 14513498266Sopenharmony_ci 14613498266Sopenharmony_ci if(parent_form_info) { 14713498266Sopenharmony_ci /* now, point our 'more' to the original 'more' */ 14813498266Sopenharmony_ci form_info->more = parent_form_info->more; 14913498266Sopenharmony_ci 15013498266Sopenharmony_ci /* then move the original 'more' to point to ourselves */ 15113498266Sopenharmony_ci parent_form_info->more = form_info; 15213498266Sopenharmony_ci } 15313498266Sopenharmony_ci 15413498266Sopenharmony_ci return form_info; 15513498266Sopenharmony_ci} 15613498266Sopenharmony_ci 15713498266Sopenharmony_ci/*************************************************************************** 15813498266Sopenharmony_ci * 15913498266Sopenharmony_ci * FormAdd() 16013498266Sopenharmony_ci * 16113498266Sopenharmony_ci * Stores a formpost parameter and builds the appropriate linked list. 16213498266Sopenharmony_ci * 16313498266Sopenharmony_ci * Has two principal functionalities: using files and byte arrays as 16413498266Sopenharmony_ci * post parts. Byte arrays are either copied or just the pointer is stored 16513498266Sopenharmony_ci * (as the user requests) while for files only the filename and not the 16613498266Sopenharmony_ci * content is stored. 16713498266Sopenharmony_ci * 16813498266Sopenharmony_ci * While you may have only one byte array for each name, multiple filenames 16913498266Sopenharmony_ci * are allowed (and because of this feature CURLFORM_END is needed after 17013498266Sopenharmony_ci * using CURLFORM_FILE). 17113498266Sopenharmony_ci * 17213498266Sopenharmony_ci * Examples: 17313498266Sopenharmony_ci * 17413498266Sopenharmony_ci * Simple name/value pair with copied contents: 17513498266Sopenharmony_ci * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", 17613498266Sopenharmony_ci * CURLFORM_COPYCONTENTS, "value", CURLFORM_END); 17713498266Sopenharmony_ci * 17813498266Sopenharmony_ci * name/value pair where only the content pointer is remembered: 17913498266Sopenharmony_ci * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", 18013498266Sopenharmony_ci * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END); 18113498266Sopenharmony_ci * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used) 18213498266Sopenharmony_ci * 18313498266Sopenharmony_ci * storing a filename (CONTENTTYPE is optional!): 18413498266Sopenharmony_ci * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", 18513498266Sopenharmony_ci * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text", 18613498266Sopenharmony_ci * CURLFORM_END); 18713498266Sopenharmony_ci * 18813498266Sopenharmony_ci * storing multiple filenames: 18913498266Sopenharmony_ci * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", 19013498266Sopenharmony_ci * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END); 19113498266Sopenharmony_ci * 19213498266Sopenharmony_ci * Returns: 19313498266Sopenharmony_ci * CURL_FORMADD_OK on success 19413498266Sopenharmony_ci * CURL_FORMADD_MEMORY if the FormInfo allocation fails 19513498266Sopenharmony_ci * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form 19613498266Sopenharmony_ci * CURL_FORMADD_NULL if a null pointer was given for a char 19713498266Sopenharmony_ci * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed 19813498266Sopenharmony_ci * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used 19913498266Sopenharmony_ci * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) 20013498266Sopenharmony_ci * CURL_FORMADD_MEMORY if an HttpPost struct cannot be allocated 20113498266Sopenharmony_ci * CURL_FORMADD_MEMORY if some allocation for string copying failed. 20213498266Sopenharmony_ci * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array 20313498266Sopenharmony_ci * 20413498266Sopenharmony_ci ***************************************************************************/ 20513498266Sopenharmony_ci 20613498266Sopenharmony_cistatic 20713498266Sopenharmony_ciCURLFORMcode FormAdd(struct curl_httppost **httppost, 20813498266Sopenharmony_ci struct curl_httppost **last_post, 20913498266Sopenharmony_ci va_list params) 21013498266Sopenharmony_ci{ 21113498266Sopenharmony_ci struct FormInfo *first_form, *current_form, *form = NULL; 21213498266Sopenharmony_ci CURLFORMcode return_value = CURL_FORMADD_OK; 21313498266Sopenharmony_ci const char *prevtype = NULL; 21413498266Sopenharmony_ci struct curl_httppost *post = NULL; 21513498266Sopenharmony_ci CURLformoption option; 21613498266Sopenharmony_ci struct curl_forms *forms = NULL; 21713498266Sopenharmony_ci char *array_value = NULL; /* value read from an array */ 21813498266Sopenharmony_ci 21913498266Sopenharmony_ci /* This is a state variable, that if TRUE means that we're parsing an 22013498266Sopenharmony_ci array that we got passed to us. If FALSE we're parsing the input 22113498266Sopenharmony_ci va_list arguments. */ 22213498266Sopenharmony_ci bool array_state = FALSE; 22313498266Sopenharmony_ci 22413498266Sopenharmony_ci /* 22513498266Sopenharmony_ci * We need to allocate the first struct to fill in. 22613498266Sopenharmony_ci */ 22713498266Sopenharmony_ci first_form = calloc(1, sizeof(struct FormInfo)); 22813498266Sopenharmony_ci if(!first_form) 22913498266Sopenharmony_ci return CURL_FORMADD_MEMORY; 23013498266Sopenharmony_ci 23113498266Sopenharmony_ci current_form = first_form; 23213498266Sopenharmony_ci 23313498266Sopenharmony_ci /* 23413498266Sopenharmony_ci * Loop through all the options set. Break if we have an error to report. 23513498266Sopenharmony_ci */ 23613498266Sopenharmony_ci while(return_value == CURL_FORMADD_OK) { 23713498266Sopenharmony_ci 23813498266Sopenharmony_ci /* first see if we have more parts of the array param */ 23913498266Sopenharmony_ci if(array_state && forms) { 24013498266Sopenharmony_ci /* get the upcoming option from the given array */ 24113498266Sopenharmony_ci option = forms->option; 24213498266Sopenharmony_ci array_value = (char *)forms->value; 24313498266Sopenharmony_ci 24413498266Sopenharmony_ci forms++; /* advance this to next entry */ 24513498266Sopenharmony_ci if(CURLFORM_END == option) { 24613498266Sopenharmony_ci /* end of array state */ 24713498266Sopenharmony_ci array_state = FALSE; 24813498266Sopenharmony_ci continue; 24913498266Sopenharmony_ci } 25013498266Sopenharmony_ci } 25113498266Sopenharmony_ci else { 25213498266Sopenharmony_ci /* This is not array-state, get next option. This gets an 'int' with 25313498266Sopenharmony_ci va_arg() because CURLformoption might be a smaller type than int and 25413498266Sopenharmony_ci might cause compiler warnings and wrong behavior. */ 25513498266Sopenharmony_ci option = (CURLformoption)va_arg(params, int); 25613498266Sopenharmony_ci if(CURLFORM_END == option) 25713498266Sopenharmony_ci break; 25813498266Sopenharmony_ci } 25913498266Sopenharmony_ci 26013498266Sopenharmony_ci switch(option) { 26113498266Sopenharmony_ci case CURLFORM_ARRAY: 26213498266Sopenharmony_ci if(array_state) 26313498266Sopenharmony_ci /* we don't support an array from within an array */ 26413498266Sopenharmony_ci return_value = CURL_FORMADD_ILLEGAL_ARRAY; 26513498266Sopenharmony_ci else { 26613498266Sopenharmony_ci forms = va_arg(params, struct curl_forms *); 26713498266Sopenharmony_ci if(forms) 26813498266Sopenharmony_ci array_state = TRUE; 26913498266Sopenharmony_ci else 27013498266Sopenharmony_ci return_value = CURL_FORMADD_NULL; 27113498266Sopenharmony_ci } 27213498266Sopenharmony_ci break; 27313498266Sopenharmony_ci 27413498266Sopenharmony_ci /* 27513498266Sopenharmony_ci * Set the Name property. 27613498266Sopenharmony_ci */ 27713498266Sopenharmony_ci case CURLFORM_PTRNAME: 27813498266Sopenharmony_ci current_form->flags |= HTTPPOST_PTRNAME; /* fall through */ 27913498266Sopenharmony_ci 28013498266Sopenharmony_ci FALLTHROUGH(); 28113498266Sopenharmony_ci case CURLFORM_COPYNAME: 28213498266Sopenharmony_ci if(current_form->name) 28313498266Sopenharmony_ci return_value = CURL_FORMADD_OPTION_TWICE; 28413498266Sopenharmony_ci else { 28513498266Sopenharmony_ci char *name = array_state? 28613498266Sopenharmony_ci array_value:va_arg(params, char *); 28713498266Sopenharmony_ci if(name) 28813498266Sopenharmony_ci current_form->name = name; /* store for the moment */ 28913498266Sopenharmony_ci else 29013498266Sopenharmony_ci return_value = CURL_FORMADD_NULL; 29113498266Sopenharmony_ci } 29213498266Sopenharmony_ci break; 29313498266Sopenharmony_ci case CURLFORM_NAMELENGTH: 29413498266Sopenharmony_ci if(current_form->namelength) 29513498266Sopenharmony_ci return_value = CURL_FORMADD_OPTION_TWICE; 29613498266Sopenharmony_ci else 29713498266Sopenharmony_ci current_form->namelength = 29813498266Sopenharmony_ci array_state?(size_t)array_value:(size_t)va_arg(params, long); 29913498266Sopenharmony_ci break; 30013498266Sopenharmony_ci 30113498266Sopenharmony_ci /* 30213498266Sopenharmony_ci * Set the contents property. 30313498266Sopenharmony_ci */ 30413498266Sopenharmony_ci case CURLFORM_PTRCONTENTS: 30513498266Sopenharmony_ci current_form->flags |= HTTPPOST_PTRCONTENTS; 30613498266Sopenharmony_ci FALLTHROUGH(); 30713498266Sopenharmony_ci case CURLFORM_COPYCONTENTS: 30813498266Sopenharmony_ci if(current_form->value) 30913498266Sopenharmony_ci return_value = CURL_FORMADD_OPTION_TWICE; 31013498266Sopenharmony_ci else { 31113498266Sopenharmony_ci char *value = 31213498266Sopenharmony_ci array_state?array_value:va_arg(params, char *); 31313498266Sopenharmony_ci if(value) 31413498266Sopenharmony_ci current_form->value = value; /* store for the moment */ 31513498266Sopenharmony_ci else 31613498266Sopenharmony_ci return_value = CURL_FORMADD_NULL; 31713498266Sopenharmony_ci } 31813498266Sopenharmony_ci break; 31913498266Sopenharmony_ci case CURLFORM_CONTENTSLENGTH: 32013498266Sopenharmony_ci current_form->contentslength = 32113498266Sopenharmony_ci array_state?(size_t)array_value:(size_t)va_arg(params, long); 32213498266Sopenharmony_ci break; 32313498266Sopenharmony_ci 32413498266Sopenharmony_ci case CURLFORM_CONTENTLEN: 32513498266Sopenharmony_ci current_form->flags |= CURL_HTTPPOST_LARGE; 32613498266Sopenharmony_ci current_form->contentslength = 32713498266Sopenharmony_ci array_state?(curl_off_t)(size_t)array_value:va_arg(params, curl_off_t); 32813498266Sopenharmony_ci break; 32913498266Sopenharmony_ci 33013498266Sopenharmony_ci /* Get contents from a given file name */ 33113498266Sopenharmony_ci case CURLFORM_FILECONTENT: 33213498266Sopenharmony_ci if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE)) 33313498266Sopenharmony_ci return_value = CURL_FORMADD_OPTION_TWICE; 33413498266Sopenharmony_ci else { 33513498266Sopenharmony_ci const char *filename = array_state? 33613498266Sopenharmony_ci array_value:va_arg(params, char *); 33713498266Sopenharmony_ci if(filename) { 33813498266Sopenharmony_ci current_form->value = strdup(filename); 33913498266Sopenharmony_ci if(!current_form->value) 34013498266Sopenharmony_ci return_value = CURL_FORMADD_MEMORY; 34113498266Sopenharmony_ci else { 34213498266Sopenharmony_ci current_form->flags |= HTTPPOST_READFILE; 34313498266Sopenharmony_ci current_form->value_alloc = TRUE; 34413498266Sopenharmony_ci } 34513498266Sopenharmony_ci } 34613498266Sopenharmony_ci else 34713498266Sopenharmony_ci return_value = CURL_FORMADD_NULL; 34813498266Sopenharmony_ci } 34913498266Sopenharmony_ci break; 35013498266Sopenharmony_ci 35113498266Sopenharmony_ci /* We upload a file */ 35213498266Sopenharmony_ci case CURLFORM_FILE: 35313498266Sopenharmony_ci { 35413498266Sopenharmony_ci const char *filename = array_state?array_value: 35513498266Sopenharmony_ci va_arg(params, char *); 35613498266Sopenharmony_ci 35713498266Sopenharmony_ci if(current_form->value) { 35813498266Sopenharmony_ci if(current_form->flags & HTTPPOST_FILENAME) { 35913498266Sopenharmony_ci if(filename) { 36013498266Sopenharmony_ci char *fname = strdup(filename); 36113498266Sopenharmony_ci if(!fname) 36213498266Sopenharmony_ci return_value = CURL_FORMADD_MEMORY; 36313498266Sopenharmony_ci else { 36413498266Sopenharmony_ci form = AddFormInfo(fname, NULL, current_form); 36513498266Sopenharmony_ci if(!form) { 36613498266Sopenharmony_ci free(fname); 36713498266Sopenharmony_ci return_value = CURL_FORMADD_MEMORY; 36813498266Sopenharmony_ci } 36913498266Sopenharmony_ci else { 37013498266Sopenharmony_ci form->value_alloc = TRUE; 37113498266Sopenharmony_ci current_form = form; 37213498266Sopenharmony_ci form = NULL; 37313498266Sopenharmony_ci } 37413498266Sopenharmony_ci } 37513498266Sopenharmony_ci } 37613498266Sopenharmony_ci else 37713498266Sopenharmony_ci return_value = CURL_FORMADD_NULL; 37813498266Sopenharmony_ci } 37913498266Sopenharmony_ci else 38013498266Sopenharmony_ci return_value = CURL_FORMADD_OPTION_TWICE; 38113498266Sopenharmony_ci } 38213498266Sopenharmony_ci else { 38313498266Sopenharmony_ci if(filename) { 38413498266Sopenharmony_ci current_form->value = strdup(filename); 38513498266Sopenharmony_ci if(!current_form->value) 38613498266Sopenharmony_ci return_value = CURL_FORMADD_MEMORY; 38713498266Sopenharmony_ci else { 38813498266Sopenharmony_ci current_form->flags |= HTTPPOST_FILENAME; 38913498266Sopenharmony_ci current_form->value_alloc = TRUE; 39013498266Sopenharmony_ci } 39113498266Sopenharmony_ci } 39213498266Sopenharmony_ci else 39313498266Sopenharmony_ci return_value = CURL_FORMADD_NULL; 39413498266Sopenharmony_ci } 39513498266Sopenharmony_ci break; 39613498266Sopenharmony_ci } 39713498266Sopenharmony_ci 39813498266Sopenharmony_ci case CURLFORM_BUFFERPTR: 39913498266Sopenharmony_ci current_form->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER; 40013498266Sopenharmony_ci if(current_form->buffer) 40113498266Sopenharmony_ci return_value = CURL_FORMADD_OPTION_TWICE; 40213498266Sopenharmony_ci else { 40313498266Sopenharmony_ci char *buffer = 40413498266Sopenharmony_ci array_state?array_value:va_arg(params, char *); 40513498266Sopenharmony_ci if(buffer) { 40613498266Sopenharmony_ci current_form->buffer = buffer; /* store for the moment */ 40713498266Sopenharmony_ci current_form->value = buffer; /* make it non-NULL to be accepted 40813498266Sopenharmony_ci as fine */ 40913498266Sopenharmony_ci } 41013498266Sopenharmony_ci else 41113498266Sopenharmony_ci return_value = CURL_FORMADD_NULL; 41213498266Sopenharmony_ci } 41313498266Sopenharmony_ci break; 41413498266Sopenharmony_ci 41513498266Sopenharmony_ci case CURLFORM_BUFFERLENGTH: 41613498266Sopenharmony_ci if(current_form->bufferlength) 41713498266Sopenharmony_ci return_value = CURL_FORMADD_OPTION_TWICE; 41813498266Sopenharmony_ci else 41913498266Sopenharmony_ci current_form->bufferlength = 42013498266Sopenharmony_ci array_state?(size_t)array_value:(size_t)va_arg(params, long); 42113498266Sopenharmony_ci break; 42213498266Sopenharmony_ci 42313498266Sopenharmony_ci case CURLFORM_STREAM: 42413498266Sopenharmony_ci current_form->flags |= HTTPPOST_CALLBACK; 42513498266Sopenharmony_ci if(current_form->userp) 42613498266Sopenharmony_ci return_value = CURL_FORMADD_OPTION_TWICE; 42713498266Sopenharmony_ci else { 42813498266Sopenharmony_ci char *userp = 42913498266Sopenharmony_ci array_state?array_value:va_arg(params, char *); 43013498266Sopenharmony_ci if(userp) { 43113498266Sopenharmony_ci current_form->userp = userp; 43213498266Sopenharmony_ci current_form->value = userp; /* this isn't strictly true but we 43313498266Sopenharmony_ci derive a value from this later on 43413498266Sopenharmony_ci and we need this non-NULL to be 43513498266Sopenharmony_ci accepted as a fine form part */ 43613498266Sopenharmony_ci } 43713498266Sopenharmony_ci else 43813498266Sopenharmony_ci return_value = CURL_FORMADD_NULL; 43913498266Sopenharmony_ci } 44013498266Sopenharmony_ci break; 44113498266Sopenharmony_ci 44213498266Sopenharmony_ci case CURLFORM_CONTENTTYPE: 44313498266Sopenharmony_ci { 44413498266Sopenharmony_ci const char *contenttype = 44513498266Sopenharmony_ci array_state?array_value:va_arg(params, char *); 44613498266Sopenharmony_ci if(current_form->contenttype) { 44713498266Sopenharmony_ci if(current_form->flags & HTTPPOST_FILENAME) { 44813498266Sopenharmony_ci if(contenttype) { 44913498266Sopenharmony_ci char *type = strdup(contenttype); 45013498266Sopenharmony_ci if(!type) 45113498266Sopenharmony_ci return_value = CURL_FORMADD_MEMORY; 45213498266Sopenharmony_ci else { 45313498266Sopenharmony_ci form = AddFormInfo(NULL, type, current_form); 45413498266Sopenharmony_ci if(!form) { 45513498266Sopenharmony_ci free(type); 45613498266Sopenharmony_ci return_value = CURL_FORMADD_MEMORY; 45713498266Sopenharmony_ci } 45813498266Sopenharmony_ci else { 45913498266Sopenharmony_ci form->contenttype_alloc = TRUE; 46013498266Sopenharmony_ci current_form = form; 46113498266Sopenharmony_ci form = NULL; 46213498266Sopenharmony_ci } 46313498266Sopenharmony_ci } 46413498266Sopenharmony_ci } 46513498266Sopenharmony_ci else 46613498266Sopenharmony_ci return_value = CURL_FORMADD_NULL; 46713498266Sopenharmony_ci } 46813498266Sopenharmony_ci else 46913498266Sopenharmony_ci return_value = CURL_FORMADD_OPTION_TWICE; 47013498266Sopenharmony_ci } 47113498266Sopenharmony_ci else { 47213498266Sopenharmony_ci if(contenttype) { 47313498266Sopenharmony_ci current_form->contenttype = strdup(contenttype); 47413498266Sopenharmony_ci if(!current_form->contenttype) 47513498266Sopenharmony_ci return_value = CURL_FORMADD_MEMORY; 47613498266Sopenharmony_ci else 47713498266Sopenharmony_ci current_form->contenttype_alloc = TRUE; 47813498266Sopenharmony_ci } 47913498266Sopenharmony_ci else 48013498266Sopenharmony_ci return_value = CURL_FORMADD_NULL; 48113498266Sopenharmony_ci } 48213498266Sopenharmony_ci break; 48313498266Sopenharmony_ci } 48413498266Sopenharmony_ci case CURLFORM_CONTENTHEADER: 48513498266Sopenharmony_ci { 48613498266Sopenharmony_ci /* this "cast increases required alignment of target type" but 48713498266Sopenharmony_ci we consider it OK anyway */ 48813498266Sopenharmony_ci struct curl_slist *list = array_state? 48913498266Sopenharmony_ci (struct curl_slist *)(void *)array_value: 49013498266Sopenharmony_ci va_arg(params, struct curl_slist *); 49113498266Sopenharmony_ci 49213498266Sopenharmony_ci if(current_form->contentheader) 49313498266Sopenharmony_ci return_value = CURL_FORMADD_OPTION_TWICE; 49413498266Sopenharmony_ci else 49513498266Sopenharmony_ci current_form->contentheader = list; 49613498266Sopenharmony_ci 49713498266Sopenharmony_ci break; 49813498266Sopenharmony_ci } 49913498266Sopenharmony_ci case CURLFORM_FILENAME: 50013498266Sopenharmony_ci case CURLFORM_BUFFER: 50113498266Sopenharmony_ci { 50213498266Sopenharmony_ci const char *filename = array_state?array_value: 50313498266Sopenharmony_ci va_arg(params, char *); 50413498266Sopenharmony_ci if(current_form->showfilename) 50513498266Sopenharmony_ci return_value = CURL_FORMADD_OPTION_TWICE; 50613498266Sopenharmony_ci else { 50713498266Sopenharmony_ci current_form->showfilename = strdup(filename); 50813498266Sopenharmony_ci if(!current_form->showfilename) 50913498266Sopenharmony_ci return_value = CURL_FORMADD_MEMORY; 51013498266Sopenharmony_ci else 51113498266Sopenharmony_ci current_form->showfilename_alloc = TRUE; 51213498266Sopenharmony_ci } 51313498266Sopenharmony_ci break; 51413498266Sopenharmony_ci } 51513498266Sopenharmony_ci default: 51613498266Sopenharmony_ci return_value = CURL_FORMADD_UNKNOWN_OPTION; 51713498266Sopenharmony_ci break; 51813498266Sopenharmony_ci } 51913498266Sopenharmony_ci } 52013498266Sopenharmony_ci 52113498266Sopenharmony_ci if(CURL_FORMADD_OK != return_value) { 52213498266Sopenharmony_ci /* On error, free allocated fields for all nodes of the FormInfo linked 52313498266Sopenharmony_ci list without deallocating nodes. List nodes are deallocated later on */ 52413498266Sopenharmony_ci struct FormInfo *ptr; 52513498266Sopenharmony_ci for(ptr = first_form; ptr != NULL; ptr = ptr->more) { 52613498266Sopenharmony_ci if(ptr->name_alloc) { 52713498266Sopenharmony_ci Curl_safefree(ptr->name); 52813498266Sopenharmony_ci ptr->name_alloc = FALSE; 52913498266Sopenharmony_ci } 53013498266Sopenharmony_ci if(ptr->value_alloc) { 53113498266Sopenharmony_ci Curl_safefree(ptr->value); 53213498266Sopenharmony_ci ptr->value_alloc = FALSE; 53313498266Sopenharmony_ci } 53413498266Sopenharmony_ci if(ptr->contenttype_alloc) { 53513498266Sopenharmony_ci Curl_safefree(ptr->contenttype); 53613498266Sopenharmony_ci ptr->contenttype_alloc = FALSE; 53713498266Sopenharmony_ci } 53813498266Sopenharmony_ci if(ptr->showfilename_alloc) { 53913498266Sopenharmony_ci Curl_safefree(ptr->showfilename); 54013498266Sopenharmony_ci ptr->showfilename_alloc = FALSE; 54113498266Sopenharmony_ci } 54213498266Sopenharmony_ci } 54313498266Sopenharmony_ci } 54413498266Sopenharmony_ci 54513498266Sopenharmony_ci if(CURL_FORMADD_OK == return_value) { 54613498266Sopenharmony_ci /* go through the list, check for completeness and if everything is 54713498266Sopenharmony_ci * alright add the HttpPost item otherwise set return_value accordingly */ 54813498266Sopenharmony_ci 54913498266Sopenharmony_ci post = NULL; 55013498266Sopenharmony_ci for(form = first_form; 55113498266Sopenharmony_ci form != NULL; 55213498266Sopenharmony_ci form = form->more) { 55313498266Sopenharmony_ci if(((!form->name || !form->value) && !post) || 55413498266Sopenharmony_ci ( (form->contentslength) && 55513498266Sopenharmony_ci (form->flags & HTTPPOST_FILENAME) ) || 55613498266Sopenharmony_ci ( (form->flags & HTTPPOST_FILENAME) && 55713498266Sopenharmony_ci (form->flags & HTTPPOST_PTRCONTENTS) ) || 55813498266Sopenharmony_ci 55913498266Sopenharmony_ci ( (!form->buffer) && 56013498266Sopenharmony_ci (form->flags & HTTPPOST_BUFFER) && 56113498266Sopenharmony_ci (form->flags & HTTPPOST_PTRBUFFER) ) || 56213498266Sopenharmony_ci 56313498266Sopenharmony_ci ( (form->flags & HTTPPOST_READFILE) && 56413498266Sopenharmony_ci (form->flags & HTTPPOST_PTRCONTENTS) ) 56513498266Sopenharmony_ci ) { 56613498266Sopenharmony_ci return_value = CURL_FORMADD_INCOMPLETE; 56713498266Sopenharmony_ci break; 56813498266Sopenharmony_ci } 56913498266Sopenharmony_ci if(((form->flags & HTTPPOST_FILENAME) || 57013498266Sopenharmony_ci (form->flags & HTTPPOST_BUFFER)) && 57113498266Sopenharmony_ci !form->contenttype) { 57213498266Sopenharmony_ci char *f = (form->flags & HTTPPOST_BUFFER)? 57313498266Sopenharmony_ci form->showfilename : form->value; 57413498266Sopenharmony_ci char const *type; 57513498266Sopenharmony_ci type = Curl_mime_contenttype(f); 57613498266Sopenharmony_ci if(!type) 57713498266Sopenharmony_ci type = prevtype; 57813498266Sopenharmony_ci if(!type) 57913498266Sopenharmony_ci type = FILE_CONTENTTYPE_DEFAULT; 58013498266Sopenharmony_ci 58113498266Sopenharmony_ci /* our contenttype is missing */ 58213498266Sopenharmony_ci form->contenttype = strdup(type); 58313498266Sopenharmony_ci if(!form->contenttype) { 58413498266Sopenharmony_ci return_value = CURL_FORMADD_MEMORY; 58513498266Sopenharmony_ci break; 58613498266Sopenharmony_ci } 58713498266Sopenharmony_ci form->contenttype_alloc = TRUE; 58813498266Sopenharmony_ci } 58913498266Sopenharmony_ci if(form->name && form->namelength) { 59013498266Sopenharmony_ci /* Name should not contain nul bytes. */ 59113498266Sopenharmony_ci size_t i; 59213498266Sopenharmony_ci for(i = 0; i < form->namelength; i++) 59313498266Sopenharmony_ci if(!form->name[i]) { 59413498266Sopenharmony_ci return_value = CURL_FORMADD_NULL; 59513498266Sopenharmony_ci break; 59613498266Sopenharmony_ci } 59713498266Sopenharmony_ci if(return_value != CURL_FORMADD_OK) 59813498266Sopenharmony_ci break; 59913498266Sopenharmony_ci } 60013498266Sopenharmony_ci if(!(form->flags & HTTPPOST_PTRNAME) && 60113498266Sopenharmony_ci (form == first_form) ) { 60213498266Sopenharmony_ci /* Note that there's small risk that form->name is NULL here if the 60313498266Sopenharmony_ci app passed in a bad combo, so we better check for that first. */ 60413498266Sopenharmony_ci if(form->name) { 60513498266Sopenharmony_ci /* copy name (without strdup; possibly not null-terminated) */ 60613498266Sopenharmony_ci form->name = Curl_memdup0(form->name, form->namelength? 60713498266Sopenharmony_ci form->namelength: 60813498266Sopenharmony_ci strlen(form->name)); 60913498266Sopenharmony_ci } 61013498266Sopenharmony_ci if(!form->name) { 61113498266Sopenharmony_ci return_value = CURL_FORMADD_MEMORY; 61213498266Sopenharmony_ci break; 61313498266Sopenharmony_ci } 61413498266Sopenharmony_ci form->name_alloc = TRUE; 61513498266Sopenharmony_ci } 61613498266Sopenharmony_ci if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE | 61713498266Sopenharmony_ci HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER | 61813498266Sopenharmony_ci HTTPPOST_CALLBACK)) && form->value) { 61913498266Sopenharmony_ci /* copy value (without strdup; possibly contains null characters) */ 62013498266Sopenharmony_ci size_t clen = (size_t) form->contentslength; 62113498266Sopenharmony_ci if(!clen) 62213498266Sopenharmony_ci clen = strlen(form->value) + 1; 62313498266Sopenharmony_ci 62413498266Sopenharmony_ci form->value = Curl_memdup(form->value, clen); 62513498266Sopenharmony_ci 62613498266Sopenharmony_ci if(!form->value) { 62713498266Sopenharmony_ci return_value = CURL_FORMADD_MEMORY; 62813498266Sopenharmony_ci break; 62913498266Sopenharmony_ci } 63013498266Sopenharmony_ci form->value_alloc = TRUE; 63113498266Sopenharmony_ci } 63213498266Sopenharmony_ci post = AddHttpPost(form->name, form->namelength, 63313498266Sopenharmony_ci form->value, form->contentslength, 63413498266Sopenharmony_ci form->buffer, form->bufferlength, 63513498266Sopenharmony_ci form->contenttype, form->flags, 63613498266Sopenharmony_ci form->contentheader, form->showfilename, 63713498266Sopenharmony_ci form->userp, 63813498266Sopenharmony_ci post, httppost, 63913498266Sopenharmony_ci last_post); 64013498266Sopenharmony_ci 64113498266Sopenharmony_ci if(!post) { 64213498266Sopenharmony_ci return_value = CURL_FORMADD_MEMORY; 64313498266Sopenharmony_ci break; 64413498266Sopenharmony_ci } 64513498266Sopenharmony_ci 64613498266Sopenharmony_ci if(form->contenttype) 64713498266Sopenharmony_ci prevtype = form->contenttype; 64813498266Sopenharmony_ci } 64913498266Sopenharmony_ci if(CURL_FORMADD_OK != return_value) { 65013498266Sopenharmony_ci /* On error, free allocated fields for nodes of the FormInfo linked 65113498266Sopenharmony_ci list which are not already owned by the httppost linked list 65213498266Sopenharmony_ci without deallocating nodes. List nodes are deallocated later on */ 65313498266Sopenharmony_ci struct FormInfo *ptr; 65413498266Sopenharmony_ci for(ptr = form; ptr != NULL; ptr = ptr->more) { 65513498266Sopenharmony_ci if(ptr->name_alloc) { 65613498266Sopenharmony_ci Curl_safefree(ptr->name); 65713498266Sopenharmony_ci ptr->name_alloc = FALSE; 65813498266Sopenharmony_ci } 65913498266Sopenharmony_ci if(ptr->value_alloc) { 66013498266Sopenharmony_ci Curl_safefree(ptr->value); 66113498266Sopenharmony_ci ptr->value_alloc = FALSE; 66213498266Sopenharmony_ci } 66313498266Sopenharmony_ci if(ptr->contenttype_alloc) { 66413498266Sopenharmony_ci Curl_safefree(ptr->contenttype); 66513498266Sopenharmony_ci ptr->contenttype_alloc = FALSE; 66613498266Sopenharmony_ci } 66713498266Sopenharmony_ci if(ptr->showfilename_alloc) { 66813498266Sopenharmony_ci Curl_safefree(ptr->showfilename); 66913498266Sopenharmony_ci ptr->showfilename_alloc = FALSE; 67013498266Sopenharmony_ci } 67113498266Sopenharmony_ci } 67213498266Sopenharmony_ci } 67313498266Sopenharmony_ci } 67413498266Sopenharmony_ci 67513498266Sopenharmony_ci /* Always deallocate FormInfo linked list nodes without touching node 67613498266Sopenharmony_ci fields given that these have either been deallocated or are owned 67713498266Sopenharmony_ci now by the httppost linked list */ 67813498266Sopenharmony_ci while(first_form) { 67913498266Sopenharmony_ci struct FormInfo *ptr = first_form->more; 68013498266Sopenharmony_ci free(first_form); 68113498266Sopenharmony_ci first_form = ptr; 68213498266Sopenharmony_ci } 68313498266Sopenharmony_ci 68413498266Sopenharmony_ci return return_value; 68513498266Sopenharmony_ci} 68613498266Sopenharmony_ci 68713498266Sopenharmony_ci/* 68813498266Sopenharmony_ci * curl_formadd() is a public API to add a section to the multipart formpost. 68913498266Sopenharmony_ci * 69013498266Sopenharmony_ci * @unittest: 1308 69113498266Sopenharmony_ci */ 69213498266Sopenharmony_ci 69313498266Sopenharmony_ciCURLFORMcode curl_formadd(struct curl_httppost **httppost, 69413498266Sopenharmony_ci struct curl_httppost **last_post, 69513498266Sopenharmony_ci ...) 69613498266Sopenharmony_ci{ 69713498266Sopenharmony_ci va_list arg; 69813498266Sopenharmony_ci CURLFORMcode result; 69913498266Sopenharmony_ci va_start(arg, last_post); 70013498266Sopenharmony_ci result = FormAdd(httppost, last_post, arg); 70113498266Sopenharmony_ci va_end(arg); 70213498266Sopenharmony_ci return result; 70313498266Sopenharmony_ci} 70413498266Sopenharmony_ci 70513498266Sopenharmony_ci/* 70613498266Sopenharmony_ci * curl_formget() 70713498266Sopenharmony_ci * Serialize a curl_httppost struct. 70813498266Sopenharmony_ci * Returns 0 on success. 70913498266Sopenharmony_ci * 71013498266Sopenharmony_ci * @unittest: 1308 71113498266Sopenharmony_ci */ 71213498266Sopenharmony_ciint curl_formget(struct curl_httppost *form, void *arg, 71313498266Sopenharmony_ci curl_formget_callback append) 71413498266Sopenharmony_ci{ 71513498266Sopenharmony_ci CURLcode result; 71613498266Sopenharmony_ci curl_mimepart toppart; 71713498266Sopenharmony_ci 71813498266Sopenharmony_ci Curl_mime_initpart(&toppart); /* default form is empty */ 71913498266Sopenharmony_ci result = Curl_getformdata(NULL, &toppart, form, NULL); 72013498266Sopenharmony_ci if(!result) 72113498266Sopenharmony_ci result = Curl_mime_prepare_headers(NULL, &toppart, "multipart/form-data", 72213498266Sopenharmony_ci NULL, MIMESTRATEGY_FORM); 72313498266Sopenharmony_ci 72413498266Sopenharmony_ci while(!result) { 72513498266Sopenharmony_ci char buffer[8192]; 72613498266Sopenharmony_ci size_t nread = Curl_mime_read(buffer, 1, sizeof(buffer), &toppart); 72713498266Sopenharmony_ci 72813498266Sopenharmony_ci if(!nread) 72913498266Sopenharmony_ci break; 73013498266Sopenharmony_ci 73113498266Sopenharmony_ci if(nread > sizeof(buffer) || append(arg, buffer, nread) != nread) { 73213498266Sopenharmony_ci result = CURLE_READ_ERROR; 73313498266Sopenharmony_ci if(nread == CURL_READFUNC_ABORT) 73413498266Sopenharmony_ci result = CURLE_ABORTED_BY_CALLBACK; 73513498266Sopenharmony_ci } 73613498266Sopenharmony_ci } 73713498266Sopenharmony_ci 73813498266Sopenharmony_ci Curl_mime_cleanpart(&toppart); 73913498266Sopenharmony_ci return (int) result; 74013498266Sopenharmony_ci} 74113498266Sopenharmony_ci 74213498266Sopenharmony_ci/* 74313498266Sopenharmony_ci * curl_formfree() is an external function to free up a whole form post 74413498266Sopenharmony_ci * chain 74513498266Sopenharmony_ci */ 74613498266Sopenharmony_civoid curl_formfree(struct curl_httppost *form) 74713498266Sopenharmony_ci{ 74813498266Sopenharmony_ci struct curl_httppost *next; 74913498266Sopenharmony_ci 75013498266Sopenharmony_ci if(!form) 75113498266Sopenharmony_ci /* no form to free, just get out of this */ 75213498266Sopenharmony_ci return; 75313498266Sopenharmony_ci 75413498266Sopenharmony_ci do { 75513498266Sopenharmony_ci next = form->next; /* the following form line */ 75613498266Sopenharmony_ci 75713498266Sopenharmony_ci /* recurse to sub-contents */ 75813498266Sopenharmony_ci curl_formfree(form->more); 75913498266Sopenharmony_ci 76013498266Sopenharmony_ci if(!(form->flags & HTTPPOST_PTRNAME)) 76113498266Sopenharmony_ci free(form->name); /* free the name */ 76213498266Sopenharmony_ci if(!(form->flags & 76313498266Sopenharmony_ci (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) 76413498266Sopenharmony_ci ) 76513498266Sopenharmony_ci free(form->contents); /* free the contents */ 76613498266Sopenharmony_ci free(form->contenttype); /* free the content type */ 76713498266Sopenharmony_ci free(form->showfilename); /* free the faked file name */ 76813498266Sopenharmony_ci free(form); /* free the struct */ 76913498266Sopenharmony_ci form = next; 77013498266Sopenharmony_ci } while(form); /* continue */ 77113498266Sopenharmony_ci} 77213498266Sopenharmony_ci 77313498266Sopenharmony_ci 77413498266Sopenharmony_ci/* Set mime part name, taking care of non null-terminated name string. */ 77513498266Sopenharmony_cistatic CURLcode setname(curl_mimepart *part, const char *name, size_t len) 77613498266Sopenharmony_ci{ 77713498266Sopenharmony_ci char *zname; 77813498266Sopenharmony_ci CURLcode res; 77913498266Sopenharmony_ci 78013498266Sopenharmony_ci if(!name || !len) 78113498266Sopenharmony_ci return curl_mime_name(part, name); 78213498266Sopenharmony_ci zname = Curl_memdup0(name, len); 78313498266Sopenharmony_ci if(!zname) 78413498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 78513498266Sopenharmony_ci res = curl_mime_name(part, zname); 78613498266Sopenharmony_ci free(zname); 78713498266Sopenharmony_ci return res; 78813498266Sopenharmony_ci} 78913498266Sopenharmony_ci 79013498266Sopenharmony_ci/* wrap call to fseeko so it matches the calling convention of callback */ 79113498266Sopenharmony_cistatic int fseeko_wrapper(void *stream, curl_off_t offset, int whence) 79213498266Sopenharmony_ci{ 79313498266Sopenharmony_ci#if defined(HAVE_FSEEKO) && defined(HAVE_DECL_FSEEKO) 79413498266Sopenharmony_ci return fseeko(stream, (off_t)offset, whence); 79513498266Sopenharmony_ci#elif defined(HAVE__FSEEKI64) 79613498266Sopenharmony_ci return _fseeki64(stream, (__int64)offset, whence); 79713498266Sopenharmony_ci#else 79813498266Sopenharmony_ci if(offset > LONG_MAX) 79913498266Sopenharmony_ci return -1; 80013498266Sopenharmony_ci return fseek(stream, (long)offset, whence); 80113498266Sopenharmony_ci#endif 80213498266Sopenharmony_ci} 80313498266Sopenharmony_ci 80413498266Sopenharmony_ci/* 80513498266Sopenharmony_ci * Curl_getformdata() converts a linked list of "meta data" into a mime 80613498266Sopenharmony_ci * structure. The input list is in 'post', while the output is stored in 80713498266Sopenharmony_ci * mime part at '*finalform'. 80813498266Sopenharmony_ci * 80913498266Sopenharmony_ci * This function will not do a failf() for the potential memory failures but 81013498266Sopenharmony_ci * should for all other errors it spots. Just note that this function MAY get 81113498266Sopenharmony_ci * a NULL pointer in the 'data' argument. 81213498266Sopenharmony_ci */ 81313498266Sopenharmony_ci 81413498266Sopenharmony_ciCURLcode Curl_getformdata(struct Curl_easy *data, 81513498266Sopenharmony_ci curl_mimepart *finalform, 81613498266Sopenharmony_ci struct curl_httppost *post, 81713498266Sopenharmony_ci curl_read_callback fread_func) 81813498266Sopenharmony_ci{ 81913498266Sopenharmony_ci CURLcode result = CURLE_OK; 82013498266Sopenharmony_ci curl_mime *form = NULL; 82113498266Sopenharmony_ci curl_mimepart *part; 82213498266Sopenharmony_ci struct curl_httppost *file; 82313498266Sopenharmony_ci 82413498266Sopenharmony_ci Curl_mime_cleanpart(finalform); /* default form is empty */ 82513498266Sopenharmony_ci 82613498266Sopenharmony_ci if(!post) 82713498266Sopenharmony_ci return result; /* no input => no output! */ 82813498266Sopenharmony_ci 82913498266Sopenharmony_ci form = curl_mime_init(data); 83013498266Sopenharmony_ci if(!form) 83113498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 83213498266Sopenharmony_ci 83313498266Sopenharmony_ci if(!result) 83413498266Sopenharmony_ci result = curl_mime_subparts(finalform, form); 83513498266Sopenharmony_ci 83613498266Sopenharmony_ci /* Process each top part. */ 83713498266Sopenharmony_ci for(; !result && post; post = post->next) { 83813498266Sopenharmony_ci /* If we have more than a file here, create a mime subpart and fill it. */ 83913498266Sopenharmony_ci curl_mime *multipart = form; 84013498266Sopenharmony_ci if(post->more) { 84113498266Sopenharmony_ci part = curl_mime_addpart(form); 84213498266Sopenharmony_ci if(!part) 84313498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 84413498266Sopenharmony_ci if(!result) 84513498266Sopenharmony_ci result = setname(part, post->name, post->namelength); 84613498266Sopenharmony_ci if(!result) { 84713498266Sopenharmony_ci multipart = curl_mime_init(data); 84813498266Sopenharmony_ci if(!multipart) 84913498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 85013498266Sopenharmony_ci } 85113498266Sopenharmony_ci if(!result) 85213498266Sopenharmony_ci result = curl_mime_subparts(part, multipart); 85313498266Sopenharmony_ci } 85413498266Sopenharmony_ci 85513498266Sopenharmony_ci /* Generate all the part contents. */ 85613498266Sopenharmony_ci for(file = post; !result && file; file = file->more) { 85713498266Sopenharmony_ci /* Create the part. */ 85813498266Sopenharmony_ci part = curl_mime_addpart(multipart); 85913498266Sopenharmony_ci if(!part) 86013498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 86113498266Sopenharmony_ci 86213498266Sopenharmony_ci /* Set the headers. */ 86313498266Sopenharmony_ci if(!result) 86413498266Sopenharmony_ci result = curl_mime_headers(part, file->contentheader, 0); 86513498266Sopenharmony_ci 86613498266Sopenharmony_ci /* Set the content type. */ 86713498266Sopenharmony_ci if(!result && file->contenttype) 86813498266Sopenharmony_ci result = curl_mime_type(part, file->contenttype); 86913498266Sopenharmony_ci 87013498266Sopenharmony_ci /* Set field name. */ 87113498266Sopenharmony_ci if(!result && !post->more) 87213498266Sopenharmony_ci result = setname(part, post->name, post->namelength); 87313498266Sopenharmony_ci 87413498266Sopenharmony_ci /* Process contents. */ 87513498266Sopenharmony_ci if(!result) { 87613498266Sopenharmony_ci curl_off_t clen = post->contentslength; 87713498266Sopenharmony_ci 87813498266Sopenharmony_ci if(post->flags & CURL_HTTPPOST_LARGE) 87913498266Sopenharmony_ci clen = post->contentlen; 88013498266Sopenharmony_ci 88113498266Sopenharmony_ci if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) { 88213498266Sopenharmony_ci if(!strcmp(file->contents, "-")) { 88313498266Sopenharmony_ci /* There are a few cases where the code below won't work; in 88413498266Sopenharmony_ci particular, freopen(stdin) by the caller is not guaranteed 88513498266Sopenharmony_ci to result as expected. This feature has been kept for backward 88613498266Sopenharmony_ci compatibility: use of "-" pseudo file name should be avoided. */ 88713498266Sopenharmony_ci result = curl_mime_data_cb(part, (curl_off_t) -1, 88813498266Sopenharmony_ci (curl_read_callback) fread, 88913498266Sopenharmony_ci fseeko_wrapper, 89013498266Sopenharmony_ci NULL, (void *) stdin); 89113498266Sopenharmony_ci } 89213498266Sopenharmony_ci else 89313498266Sopenharmony_ci result = curl_mime_filedata(part, file->contents); 89413498266Sopenharmony_ci if(!result && (post->flags & HTTPPOST_READFILE)) 89513498266Sopenharmony_ci result = curl_mime_filename(part, NULL); 89613498266Sopenharmony_ci } 89713498266Sopenharmony_ci else if(post->flags & HTTPPOST_BUFFER) 89813498266Sopenharmony_ci result = curl_mime_data(part, post->buffer, 89913498266Sopenharmony_ci post->bufferlength? post->bufferlength: -1); 90013498266Sopenharmony_ci else if(post->flags & HTTPPOST_CALLBACK) { 90113498266Sopenharmony_ci /* the contents should be read with the callback and the size is set 90213498266Sopenharmony_ci with the contentslength */ 90313498266Sopenharmony_ci if(!clen) 90413498266Sopenharmony_ci clen = -1; 90513498266Sopenharmony_ci result = curl_mime_data_cb(part, clen, 90613498266Sopenharmony_ci fread_func, NULL, NULL, post->userp); 90713498266Sopenharmony_ci } 90813498266Sopenharmony_ci else { 90913498266Sopenharmony_ci size_t uclen; 91013498266Sopenharmony_ci if(!clen) 91113498266Sopenharmony_ci uclen = CURL_ZERO_TERMINATED; 91213498266Sopenharmony_ci else 91313498266Sopenharmony_ci uclen = (size_t)clen; 91413498266Sopenharmony_ci result = curl_mime_data(part, post->contents, uclen); 91513498266Sopenharmony_ci } 91613498266Sopenharmony_ci } 91713498266Sopenharmony_ci 91813498266Sopenharmony_ci /* Set fake file name. */ 91913498266Sopenharmony_ci if(!result && post->showfilename) 92013498266Sopenharmony_ci if(post->more || (post->flags & (HTTPPOST_FILENAME | HTTPPOST_BUFFER | 92113498266Sopenharmony_ci HTTPPOST_CALLBACK))) 92213498266Sopenharmony_ci result = curl_mime_filename(part, post->showfilename); 92313498266Sopenharmony_ci } 92413498266Sopenharmony_ci } 92513498266Sopenharmony_ci 92613498266Sopenharmony_ci if(result) 92713498266Sopenharmony_ci Curl_mime_cleanpart(finalform); 92813498266Sopenharmony_ci 92913498266Sopenharmony_ci return result; 93013498266Sopenharmony_ci} 93113498266Sopenharmony_ci 93213498266Sopenharmony_ci#else 93313498266Sopenharmony_ci/* if disabled */ 93413498266Sopenharmony_ciCURLFORMcode curl_formadd(struct curl_httppost **httppost, 93513498266Sopenharmony_ci struct curl_httppost **last_post, 93613498266Sopenharmony_ci ...) 93713498266Sopenharmony_ci{ 93813498266Sopenharmony_ci (void)httppost; 93913498266Sopenharmony_ci (void)last_post; 94013498266Sopenharmony_ci return CURL_FORMADD_DISABLED; 94113498266Sopenharmony_ci} 94213498266Sopenharmony_ci 94313498266Sopenharmony_ciint curl_formget(struct curl_httppost *form, void *arg, 94413498266Sopenharmony_ci curl_formget_callback append) 94513498266Sopenharmony_ci{ 94613498266Sopenharmony_ci (void) form; 94713498266Sopenharmony_ci (void) arg; 94813498266Sopenharmony_ci (void) append; 94913498266Sopenharmony_ci return CURL_FORMADD_DISABLED; 95013498266Sopenharmony_ci} 95113498266Sopenharmony_ci 95213498266Sopenharmony_civoid curl_formfree(struct curl_httppost *form) 95313498266Sopenharmony_ci{ 95413498266Sopenharmony_ci (void)form; 95513498266Sopenharmony_ci /* Nothing to do. */ 95613498266Sopenharmony_ci} 95713498266Sopenharmony_ci 95813498266Sopenharmony_ci#endif /* if disabled */ 959