📄 formdata.c
字号:
/* CMC: Added support for buffer uploads */ char * buffer, long bufferlength, char *contenttype, long flags, struct curl_slist* contentHeader, char *showfilename, struct curl_httppost *parent_post, struct curl_httppost **httppost, struct curl_httppost **last_post){ struct curl_httppost *post; post = (struct curl_httppost *)malloc(sizeof(struct curl_httppost)); if(post) { memset(post, 0, sizeof(struct curl_httppost)); post->name = name; post->namelength = name?(namelength?namelength:(long)strlen(name)):0; post->contents = value; post->contentslength = contentslength; /* CMC: Added support for buffer uploads */ post->buffer = buffer; post->bufferlength = bufferlength; post->contenttype = contenttype; post->contentheader = contentHeader; post->showfilename = showfilename; post->flags = flags; } else return NULL; if (parent_post) { /* now, point our 'more' to the original 'more' */ post->more = parent_post->more; /* then move the original 'more' to point to ourselves */ parent_post->more = post; } else { /* make the previous point to this */ if(*last_post) (*last_post)->next = post; else (*httppost) = post; (*last_post) = post; } return post;}/*************************************************************************** * * AddFormInfo() * * Adds a FormInfo structure to the list presented by parent_form_info. * * Returns newly allocated FormInfo on success and NULL if malloc failed/ * parent_form_info is NULL. * ***************************************************************************/static FormInfo * AddFormInfo(char *value, char *contenttype, FormInfo *parent_form_info){ FormInfo *form_info; form_info = (FormInfo *)malloc(sizeof(FormInfo)); if(form_info) { memset(form_info, 0, sizeof(FormInfo)); if (value) form_info->value = value; if (contenttype) form_info->contenttype = contenttype; form_info->flags = HTTPPOST_FILENAME; } else return NULL; if (parent_form_info) { /* now, point our 'more' to the original 'more' */ form_info->more = parent_form_info->more; /* then move the original 'more' to point to ourselves */ parent_form_info->more = form_info; } else return NULL; return form_info;}/*************************************************************************** * * ContentTypeForFilename() * * Provides content type for filename if one of the known types (else * (either the prevtype or the default is returned). * * Returns some valid contenttype for filename. * ***************************************************************************/static const char * ContentTypeForFilename (const char *filename, const char *prevtype){ const char *contenttype = NULL; unsigned int i; /* * No type was specified, we scan through a few well-known * extensions and pick the first we match! */ struct ContentType { const char *extension; const char *type; }; static struct ContentType ctts[]={ {".gif", "image/gif"}, {".jpg", "image/jpeg"}, {".jpeg", "image/jpeg"}, {".txt", "text/plain"}, {".html", "text/html"} }; if(prevtype) /* default to the previously set/used! */ contenttype = prevtype; else /* It seems RFC1867 defines no Content-Type to default to text/plain so we don't actually need to set this: */ contenttype = HTTPPOST_CONTENTTYPE_DEFAULT; for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) { if(strlen(filename) >= strlen(ctts[i].extension)) { if(strequal(filename + strlen(filename) - strlen(ctts[i].extension), ctts[i].extension)) { contenttype = ctts[i].type; break; } } } /* we have a contenttype by now */ return contenttype;}/*************************************************************************** * * AllocAndCopy() * * Copies the data currently available under *buffer using newly allocated * buffer (that becomes *buffer). Uses buffer_length if not null, else * uses strlen to determine the length of the buffer to be copied * * Returns 0 on success and 1 if the malloc failed. * ***************************************************************************/static int AllocAndCopy (char **buffer, int buffer_length){ const char *src = *buffer; int length, add = 0; if (buffer_length) length = buffer_length; else { length = strlen(*buffer); add = 1; } *buffer = (char*)malloc(length+add); if (!*buffer) return 1; memcpy(*buffer, src, length); /* if length unknown do null termination */ if (add) (*buffer)[length] = '\0'; return 0;}/*************************************************************************** * * FormAdd() * * Stores a 'name=value' formpost parameter and builds the appropriate * linked list. * * Has two principal functionalities: using files and byte arrays as * post parts. Byte arrays are either copied or just the pointer is stored * (as the user requests) while for files only the filename and not the * content is stored. * * While you may have only one byte array for each name, multiple filenames * are allowed (and because of this feature CURLFORM_END is needed after * using CURLFORM_FILE). * * Examples: * * Simple name/value pair with copied contents: * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", * CURLFORM_COPYCONTENTS, "value", CURLFORM_END); * * name/value pair where only the content pointer is remembered: * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", * CURLFORM_PTRCONTENTS, ptr, CURLFORM_CONTENTSLENGTH, 10, CURLFORM_END); * (if CURLFORM_CONTENTSLENGTH is missing strlen () is used) * * storing a filename (CONTENTTYPE is optional!): * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", * CURLFORM_FILE, "filename1", CURLFORM_CONTENTTYPE, "plain/text", * CURLFORM_END); * * storing multiple filenames: * curl_formadd (&post, &last, CURLFORM_COPYNAME, "name", * CURLFORM_FILE, "filename1", CURLFORM_FILE, "filename2", CURLFORM_END); * * Returns: * CURL_FORMADD_OK on success * CURL_FORMADD_MEMORY if the FormInfo allocation fails * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form * CURL_FORMADD_NULL if a null pointer was given for a char * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or an error) * CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated * CURL_FORMADD_MEMORY if some allocation for string copying failed. * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array * ***************************************************************************/staticCURLFORMcode FormAdd(struct curl_httppost **httppost, struct curl_httppost **last_post, va_list params){ FormInfo *first_form, *current_form, *form; CURLFORMcode return_value = CURL_FORMADD_OK; const char *prevtype = NULL; struct curl_httppost *post = NULL; CURLformoption option; struct curl_forms *forms = NULL; char *array_value=NULL; /* value read from an array */ /* This is a state variable, that if TRUE means that we're parsing an array that we got passed to us. If FALSE we're parsing the input va_list arguments. */ bool array_state = FALSE; /* * We need to allocate the first struct to fill in. */ first_form = (FormInfo *)malloc(sizeof(struct FormInfo)); if(first_form) { memset(first_form, 0, sizeof(FormInfo)); current_form = first_form; } else return CURL_FORMADD_MEMORY; /* * Loop through all the options set. */ while (1) { /* break if we have an error to report */ if (return_value != CURL_FORMADD_OK) break; /* first see if we have more parts of the array param */ if ( array_state ) { /* get the upcoming option from the given array */ option = forms->option; array_value = (char *)forms->value; forms++; /* advance this to next entry */ if (CURLFORM_END == option) { /* end of array state */ array_state = FALSE; continue; } } else { /* This is not array-state, get next option */ option = va_arg(params, CURLformoption); if (CURLFORM_END == option) break; } switch (option) { case CURLFORM_ARRAY: if(array_state) /* we don't support an array from within an array */ return_value = CURL_FORMADD_ILLEGAL_ARRAY; else { forms = va_arg(params, struct curl_forms *); if (forms) array_state = TRUE; else return_value = CURL_FORMADD_NULL; } break; /* * Set the Name property. */ case CURLFORM_PTRNAME: current_form->flags |= HTTPPOST_PTRNAME; /* fall through */ case CURLFORM_COPYNAME: if (current_form->name) return_value = CURL_FORMADD_OPTION_TWICE; else { char *name = array_state? array_value:va_arg(params, char *); if (name) current_form->name = name; /* store for the moment */ else return_value = CURL_FORMADD_NULL; } break; case CURLFORM_NAMELENGTH: if (current_form->namelength) return_value = CURL_FORMADD_OPTION_TWICE; else current_form->namelength = array_state?(long)array_value:va_arg(params, long); break; /* * Set the contents property. */ case CURLFORM_PTRCONTENTS: current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */ case CURLFORM_COPYCONTENTS: if (current_form->value) return_value = CURL_FORMADD_OPTION_TWICE; else { char *value = array_state?array_value:va_arg(params, char *); if (value) current_form->value = value; /* store for the moment */ else return_value = CURL_FORMADD_NULL; } break; case CURLFORM_CONTENTSLENGTH: if (current_form->contentslength) return_value = CURL_FORMADD_OPTION_TWICE; else current_form->contentslength = array_state?(long)array_value:va_arg(params, long); break; /* Get contents from a given file name */ case CURLFORM_FILECONTENT: if (current_form->flags != 0) return_value = CURL_FORMADD_OPTION_TWICE; else { char *filename = array_state? array_value:va_arg(params, char *); if (filename) { current_form->value = strdup(filename); current_form->flags |= HTTPPOST_READFILE; } else return_value = CURL_FORMADD_NULL; } break; /* We upload a file */ case CURLFORM_FILE: { char *filename = array_state?array_value: va_arg(params, char *); if (current_form->value) { if (current_form->flags & HTTPPOST_FILENAME) { if (filename) { if (!(current_form = AddFormInfo(strdup(filename), NULL, current_form))) return_value = CURL_FORMADD_MEMORY; } else return_value = CURL_FORMADD_NULL; } else return_value = CURL_FORMADD_OPTION_TWICE; } else { if (filename) current_form->value = strdup(filename); else return_value = CURL_FORMADD_NULL; current_form->flags |= HTTPPOST_FILENAME; } break; } /* CMC: Added support for buffer uploads */ case CURLFORM_BUFFER: { char *filename = array_state?array_value: va_arg(params, char *); if (current_form->value) { if (current_form->flags & HTTPPOST_BUFFER) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -