📄 formdata.c
字号:
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_BUFFER; } break; } /* CMC: Added support for buffer uploads */ case CURLFORM_BUFFERPTR: current_form->flags |= HTTPPOST_PTRBUFFER; if (current_form->buffer) return_value = CURL_FORMADD_OPTION_TWICE; else { char *buffer = array_state?array_value:va_arg(params, char *); if (buffer) current_form->buffer = buffer; /* store for the moment */ else return_value = CURL_FORMADD_NULL; } break; /* CMC: Added support for buffer uploads */ case CURLFORM_BUFFERLENGTH: if (current_form->bufferlength) return_value = CURL_FORMADD_OPTION_TWICE; else current_form->bufferlength = array_state?(long)array_value:va_arg(params, long); break; case CURLFORM_CONTENTTYPE: { char *contenttype = array_state?array_value:va_arg(params, char *); if (current_form->contenttype) { if (current_form->flags & HTTPPOST_FILENAME) { if (contenttype) { if (!(current_form = AddFormInfo(NULL, strdup(contenttype), current_form))) return_value = CURL_FORMADD_MEMORY; } else return_value = CURL_FORMADD_NULL; } else return_value = CURL_FORMADD_OPTION_TWICE; } else { if (contenttype) current_form->contenttype = strdup(contenttype); else return_value = CURL_FORMADD_NULL; } break; } case CURLFORM_CONTENTHEADER: { /* this "cast increases required alignment of target type" but we consider it OK anyway */ struct curl_slist* list = array_state? (struct curl_slist*)array_value: va_arg(params, struct curl_slist*); if( current_form->contentheader ) return_value = CURL_FORMADD_OPTION_TWICE; else current_form->contentheader = list; break; } case CURLFORM_FILENAME: { char *filename = array_state?array_value: va_arg(params, char *); if( current_form->showfilename ) return_value = CURL_FORMADD_OPTION_TWICE; else current_form->showfilename = strdup(filename); break; } default: return_value = CURL_FORMADD_UNKNOWN_OPTION; } } if(CURL_FORMADD_OK == return_value) { /* go through the list, check for copleteness and if everything is * alright add the HttpPost item otherwise set return_value accordingly */ post = NULL; for(form = first_form; form != NULL; form = form->more) { if ( ((!form->name || !form->value) && !post) || ( (form->contentslength) && (form->flags & HTTPPOST_FILENAME) ) || ( (form->flags & HTTPPOST_FILENAME) && (form->flags & HTTPPOST_PTRCONTENTS) ) || /* CMC: Added support for buffer uploads */ ( (!form->buffer) && (form->flags & HTTPPOST_BUFFER) && (form->flags & HTTPPOST_PTRBUFFER) ) || ( (form->flags & HTTPPOST_READFILE) && (form->flags & HTTPPOST_PTRCONTENTS) ) ) { return_value = CURL_FORMADD_INCOMPLETE; break; } else { if ( ((form->flags & HTTPPOST_FILENAME) || (form->flags & HTTPPOST_BUFFER)) && !form->contenttype ) { /* our contenttype is missing */ form->contenttype = strdup(ContentTypeForFilename(form->value, prevtype)); } if ( !(form->flags & HTTPPOST_PTRNAME) && (form == first_form) ) { /* copy name (without strdup; possibly contains null characters) */ if (AllocAndCopy(&form->name, form->namelength)) { return_value = CURL_FORMADD_MEMORY; break; } } if ( !(form->flags & HTTPPOST_FILENAME) && !(form->flags & HTTPPOST_READFILE) && !(form->flags & HTTPPOST_PTRCONTENTS) && /* CMC: Added support for buffer uploads */ !(form->flags & HTTPPOST_PTRBUFFER) ) { /* copy value (without strdup; possibly contains null characters) */ if (AllocAndCopy(&form->value, form->contentslength)) { return_value = CURL_FORMADD_MEMORY; break; } } post = AddHttpPost(form->name, form->namelength, form->value, form->contentslength, /* CMC: Added support for buffer uploads */ form->buffer, form->bufferlength, form->contenttype, form->flags, form->contentheader, form->showfilename, post, httppost, last_post); if(!post) return_value = CURL_FORMADD_MEMORY; if (form->contenttype) prevtype = form->contenttype; } } } /* always delete the allocated memory before returning */ form = first_form; while (form != NULL) { FormInfo *delete_form; delete_form = form; form = form->more; free (delete_form); } return return_value;}CURLFORMcode curl_formadd(struct curl_httppost **httppost, struct curl_httppost **last_post, ...){ va_list arg; CURLFORMcode result; va_start(arg, last_post); result = FormAdd(httppost, last_post, arg); va_end(arg); return result;}static int AddFormData(struct FormData **formp, const void *line, long length){ struct FormData *newform = (struct FormData *) malloc(sizeof(struct FormData)); newform->next = NULL; /* we make it easier for plain strings: */ if(!length) length = strlen((char *)line); newform->line = (char *)malloc(length+1); memcpy(newform->line, line, length); newform->length = length; newform->line[length]=0; /* zero terminate for easier debugging */ if(*formp) { (*formp)->next = newform; *formp = newform; } else *formp = newform; return length;}static int AddFormDataf(struct FormData **formp, const char *fmt, ...){ char s[4096]; va_list ap; va_start(ap, fmt); vsprintf(s, fmt, ap); va_end(ap); return AddFormData(formp, s, 0);}char *Curl_FormBoundary(void){ char *retstring; static int randomizer=0; /* this is just so that two boundaries within the same form won't be identical */ int i; static char table16[]="abcdef0123456789"; retstring = (char *)malloc(BOUNDARY_LENGTH+1); if(!retstring) return NULL; /* failed */ srand(time(NULL)+randomizer++); /* seed */ strcpy(retstring, "----------------------------"); for(i=strlen(retstring); i<BOUNDARY_LENGTH; i++) retstring[i] = table16[rand()%16]; /* 28 dashes and 12 hexadecimal digits makes 12^16 (184884258895036416) combinations */ retstring[BOUNDARY_LENGTH]=0; /* zero terminate */ return retstring;}/* Used from http.c, this cleans a built FormData linked list */ void Curl_formclean(struct FormData *form){ struct FormData *next; do { next=form->next; /* the following form line */ free(form->line); /* free the line */ free(form); /* free the struct */ } while((form=next)); /* continue */}/* external function to free up a whole form post chain */void curl_formfree(struct curl_httppost *form){ struct curl_httppost *next; if(!form) /* no form to free, just get out of this */ return; do { next=form->next; /* the following form line */ /* recurse to sub-contents */ if(form->more) curl_formfree(form->more); if( !(form->flags & HTTPPOST_PTRNAME) && form->name) free(form->name); /* free the name */ if( !(form->flags & HTTPPOST_PTRCONTENTS) && form->contents) free(form->contents); /* free the contents */ if(form->contenttype) free(form->contenttype); /* free the content type */ if(form->showfilename) free(form->showfilename); /* free the faked file name */ free(form); /* free the struct */ } while((form=next)); /* continue */}CURLcode Curl_getFormData(struct FormData **finalform, struct curl_httppost *post, int *sizep){ struct FormData *form = NULL; struct FormData *firstform; struct curl_httppost *file; CURLcode result = CURLE_OK; int size =0; char *boundary; char *fileboundary=NULL; struct curl_slist* curList; *finalform=NULL; /* default form is empty */ if(!post) return result; /* no input => no output! */ boundary = Curl_FormBoundary(); /* Make the first line of the output */ AddFormDataf(&form, "Content-Type: multipart/form-data;" " boundary=%s\r\n", boundary); /* we DO NOT count that line since that'll be part of the header! */ firstform = form; do { if(size) size += AddFormDataf(&form, "\r\n"); /* boundary */ size += AddFormDataf(&form, "--%s\r\n", boundary); size += AddFormData(&form, "Content-Disposition: form-data; name=\"", 0); size += AddFormData(&form, post->name, post->namelength); size += AddFormData(&form, "\"", 0); if(post->more) { /* If used, this is a link to more file names, we must then do the magic to include several files with the same field name */ fileboundary = Curl_FormBoundary(); size += AddFormDataf(&form, "\r\nContent-Type: multipart/mixed," " boundary=%s\r\n", fileboundary); } file = post; do { /* If 'showfilename' is set, that is a faked name passed on to us to use to in the formpost. If that is not set, the actually used local file name should be added. */ if(post->more) { /* if multiple-file */ size += AddFormDataf(&form, "\r\n--%s\r\nContent-Disposition: " "attachment; filename=\"%s\"", fileboundary, (file->showfilename?file->showfilename: file->contents)); } else if((post->flags & HTTPPOST_FILENAME) || /* CMC: Added support for buffer uploads */ (post->flags & HTTPPOST_BUFFER)) { size += AddFormDataf(&form, "; filename=\"%s\"", (post->showfilename?post->showfilename: post->contents)); } if(file->contenttype) { /* we have a specified type */ size += AddFormDataf(&form, "\r\nContent-Type: %s",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -