📄 formdata.c
字号:
/*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2003, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * * $Id: formdata.c,v 1.49 2003/06/26 11:22:12 bagder Exp $ ***************************************************************************//* Debug the form generator stand-alone by compiling this source file with: gcc -DHAVE_CONFIG_H -I../ -g -D_FORM_DEBUG -o formdata -I../include formdata.c strequal.c run the 'formdata' executable the output should end with: All Tests seem to have worked ... and the following parts should be there:Content-Disposition: form-data; name="simple_COPYCONTENTS"value for simple COPYCONTENTSContent-Disposition: form-data; name="COPYCONTENTS_+_CONTENTTYPE"Content-Type: image/gifvalue for COPYCONTENTS + CONTENTTYPEContent-Disposition: form-data; name="PRNAME_+_NAMELENGTH_+_COPYNAME_+_CONTENTSLENGTH"vlue for PTRNAME + NAMELENGTH + COPYNAME + CONTENTSLENGTH(or you might see P^@RNAME and v^@lue at the start)Content-Disposition: form-data; name="simple_PTRCONTENTS"value for simple PTRCONTENTSContent-Disposition: form-data; name="PTRCONTENTS_+_CONTENTSLENGTH"vlue for PTRCONTENTS + CONTENTSLENGTH(or you might see v^@lue at the start)Content-Disposition: form-data; name="PTRCONTENTS_+_CONTENTSLENGTH_+_CONTENTTYPE"Content-Type: text/plainvlue for PTRCOTNENTS + CONTENTSLENGTH + CONTENTTYPE(or you might see v^@lue at the start)Content-Disposition: form-data; name="FILE1_+_CONTENTTYPE"; filename="inet_ntoa_r.h"Content-Type: text/html...Content-Disposition: form-data; name="FILE1_+_FILE2"Content-Type: multipart/mixed, boundary=curlz1s0dkticx49MV1KGcYP5cvfSsz...Content-Disposition: attachment; filename="inet_ntoa_r.h"Content-Type: text/plain...Content-Disposition: attachment; filename="Makefile.b32.resp"Content-Type: text/plain...Content-Disposition: form-data; name="FILE1_+_FILE2_+_FILE3"Content-Type: multipart/mixed, boundary=curlirkYPmPwu6FrJ1vJ1u1BmtIufh1...Content-Disposition: attachment; filename="inet_ntoa_r.h"Content-Type: text/plain...Content-Disposition: attachment; filename="Makefile.b32.resp"Content-Type: text/plain...Content-Disposition: attachment; filename="inet_ntoa_r.h"Content-Type: text/plain...Content-Disposition: form-data; name="ARRAY: FILE1_+_FILE2_+_FILE3"Content-Type: multipart/mixed, boundary=curlirkYPmPwu6FrJ1vJ1u1BmtIufh1...Content-Disposition: attachment; filename="inet_ntoa_r.h"Content-Type: text/plain...Content-Disposition: attachment; filename="Makefile.b32.resp"Content-Type: text/plain...Content-Disposition: attachment; filename="inet_ntoa_r.h"Content-Type: text/plain...Content-Disposition: form-data; name="FILECONTENT"... For the old FormParse used by curl_formparse use: gcc -DHAVE_CONFIG_H -I../ -g -D_OLD_FORM_DEBUG -o formdata -I../include formdata.c strequal.c run the 'formdata' executable and make sure the output is ok! try './formdata "name=Daniel" "poo=noo" "foo=bar"' and similarly */#include "setup.h"#ifndef CURL_DISABLE_HTTP#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <time.h>#include <curl/curl.h>#include "formdata.h"#include "strequal.h"/* The last #include file should be: */#ifdef CURLDEBUG#include "memdebug.h"#endif/* Length of the random boundary string. */#define BOUNDARY_LENGTH 40/* What kind of Content-Type to use on un-specified files with unrecognized extensions. */#define HTTPPOST_CONTENTTYPE_DEFAULT "text/plain"/* This is a silly duplicate of the function in main.c to enable this source to compile stand-alone for better debugging */static void GetStr(char **string, const char *value){ if(*string) free(*string); *string = strdup(value);}/*************************************************************************** * * FormParse() * * Reads a 'name=value' paramter and builds the appropriate linked list. * * Specify files to upload with 'name=@filename'. Supports specified * given Content-Type of the files. Such as ';type=<content-type>'. * * You may specify more than one file for a single name (field). Specify * multiple files by writing it like: * * 'name=@filename,filename2,filename3' * * If you want content-types specified for each too, write them like: * * 'name=@filename;type=image/gif,filename2,filename3' * ***************************************************************************/#define FORM_FILE_SEPARATOR ','#define FORM_TYPE_SEPARATOR ';'staticint FormParse(char *input, struct curl_httppost **httppost, struct curl_httppost **last_post){ /* nextarg MUST be a string in the format 'name=contents' and we'll build a linked list with the info */ char name[256]; char *contents; char major[128]; char minor[128]; long flags = 0; char *contp; const char *type = NULL; char *prevtype = NULL; char *sep; char *sep2; struct curl_httppost *post; struct curl_httppost *subpost; /* a sub-node */ unsigned int i; /* Preallocate contents to the length of input to make sure we don't overwrite anything. */ contents = malloc(strlen(input)); contents[0] = '\000'; if(1 <= sscanf(input, "%255[^=]=%[^\n]", name, contents)) { /* the input was using the correct format */ contp = contents; if('@' == contp[0]) { /* we use the @-letter to indicate file name(s) */ flags = HTTPPOST_FILENAME; contp++; post=NULL; do { /* since this was a file, it may have a content-type specifier at the end too */ sep=strchr(contp, FORM_TYPE_SEPARATOR); sep2=strchr(contp, FORM_FILE_SEPARATOR); /* pick the closest */ if(sep2 && (sep2 < sep)) { sep = sep2; /* no type was specified! */ } if(sep) { /* if we got here on a comma, don't do much */ if(FORM_FILE_SEPARATOR != *sep) type = strstr(sep+1, "type="); else type=NULL; *sep=0; /* terminate file name at separator */ if(type) { type += strlen("type="); if(2 != sscanf(type, "%127[^/]/%127[^,\n]", major, minor)) { free(contents); return 2; /* illegal content-type syntax! */ } /* now point beyond the content-type specifier */ sep = (char *)type + strlen(major)+strlen(minor)+1; /* find the following comma */ sep=strchr(sep, FORM_FILE_SEPARATOR); } } else { type=NULL; sep=strchr(contp, FORM_FILE_SEPARATOR); } if(sep) { /* the next file name starts here */ *sep =0; sep++; } if(!type) { /* * 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/plain"} }; if(prevtype) /* default to the previously set/used! */ type = prevtype; else /* It seems RFC1867 defines no Content-Type to default to text/plain so we don't actually need to set this: */ type = HTTPPOST_CONTENTTYPE_DEFAULT; for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) { if(strlen(contp) >= strlen(ctts[i].extension)) { if(strequal(contp + strlen(contp) - strlen(ctts[i].extension), ctts[i].extension)) { type = ctts[i].type; break; } } } /* we have a type by now */ } if(NULL == post) { /* For the first file name, we allocate and initiate the main list node */ post = (struct curl_httppost *)malloc(sizeof(struct curl_httppost)); if(post) { memset(post, 0, sizeof(struct curl_httppost)); GetStr(&post->name, name); /* get the name */ GetStr(&post->contents, contp); /* get the contents */ post->contentslength = 0; post->flags = flags; if(type) { GetStr(&post->contenttype, (char *)type); /* get type */ prevtype=post->contenttype; /* point to the allocated string! */ } /* make the previous point to this */ if(*last_post) (*last_post)->next = post; else (*httppost) = post; (*last_post) = post; } } else { /* we add a file name to the previously allocated node, known as 'post' now */ subpost =(struct curl_httppost *) malloc(sizeof(struct curl_httppost)); if(subpost) { memset(subpost, 0, sizeof(struct curl_httppost)); GetStr(&subpost->name, name); /* get the name */ GetStr(&subpost->contents, contp); /* get the contents */ subpost->contentslength = 0; subpost->flags = flags; if(type) { GetStr(&subpost->contenttype, (char *)type); /* get type */ prevtype=subpost->contenttype; /* point to allocated string! */ } /* now, point our 'more' to the original 'more' */ subpost->more = post->more; /* then move the original 'more' to point to ourselves */ post->more = subpost; } } contp = sep; /* move the contents pointer to after the separator */ } while(sep && *sep); /* loop if there's another file name */ } else { post = (struct curl_httppost *)malloc(sizeof(struct curl_httppost)); if(post) { memset(post, 0, sizeof(struct curl_httppost)); GetStr(&post->name, name); /* get the name */ if( contp[0]=='<' ) { GetStr(&post->contents, contp+1); /* get the contents */ post->contentslength = 0; post->flags = HTTPPOST_READFILE; } else { GetStr(&post->contents, contp); /* get the contents */ post->contentslength = 0; post->flags = 0; } /* make the previous point to this */ if(*last_post) (*last_post)->next = post; else (*httppost) = post; (*last_post) = post; } } } else { free(contents); return 1; } free(contents); return 0;}int curl_formparse(char *input, struct curl_httppost **httppost, struct curl_httppost **last_post){ return FormParse(input, httppost, last_post);}/*************************************************************************** * * AddHttpPost() * * Adds a HttpPost structure to the list, if parent_post is given becomes * a subpost of parent_post instead of a direct list element. * * Returns newly allocated HttpPost on success and NULL if malloc failed. * ***************************************************************************/static struct curl_httppost *AddHttpPost(char * name, long namelength, char * value, long contentslength,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -