From c8d2ad2513e3d564c53692ed14202bfa6538fc99 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Mar 2002 15:20:56 +0000 Subject: now -F supports 'filename=blabla' for parts that upload a file, to set the filename field of that part. A typical example line could look like: -F 'name=@filename;filename=/dev/null' This can be combined with type= too, in a manner similar to: -F "file=@log/test39.txt;filename=fakerfile;type=moo/foobar" Enjoy. --- src/main.c | 164 +++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 112 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/main.c b/src/main.c index 24b53283d..c0f67e869 100644 --- a/src/main.c +++ b/src/main.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2001, Daniel Stenberg, , et al. + * Copyright (C) 2002, Daniel Stenberg, , et al. * * In order to be useful for every potential user, curl and libcurl are * dual-licensed under the MPL and the MIT/X-derivate licenses. @@ -467,8 +467,8 @@ struct Configurable { struct curl_slist *headers; - struct HttpPost *httppost; - struct HttpPost *last_post; + struct curl_httppost *httppost; + struct curl_httppost *last_post; struct curl_slist *telnet_options; @@ -598,13 +598,16 @@ struct multi_files { /* Add a new list entry possibly with a type_name */ -static void *AddMultiFiles (const char *file_name, - const char *type_name, - struct multi_files **multi_start, - struct multi_files **multi_current) +static struct multi_files * +AddMultiFiles (const char *file_name, + const char *type_name, + const char *show_filename, + struct multi_files **multi_start, + struct multi_files **multi_current) { struct multi_files *multi; struct multi_files *multi_type = NULL; + struct multi_files *multi_name = NULL; multi = (struct multi_files *)malloc(sizeof(struct multi_files)); if (multi) { memset(multi, 0, sizeof(struct multi_files)); @@ -613,6 +616,10 @@ static void *AddMultiFiles (const char *file_name, } else return NULL; + + if (!*multi_start) + *multi_start = multi; + if (type_name) { multi_type = (struct multi_files *)malloc(sizeof(struct multi_files)); if (multi_type) { @@ -620,41 +627,46 @@ static void *AddMultiFiles (const char *file_name, multi_type->form.option = CURLFORM_CONTENTTYPE; multi_type->form.value = type_name; multi->next = multi_type; + + multi = multi_type; } else { free (multi); return NULL; } } - if (!*multi_start) - *multi_start = multi; - if (!*multi_current) { - if (multi_type) - *multi_current = multi_type; - else - *multi_current = multi; - } - else { - if (multi_type) { - (*multi_current)->next = multi; - *multi_current = multi_type; + if (show_filename) { + multi_name = (struct multi_files *)malloc(sizeof(struct multi_files)); + if (multi_name) { + memset(multi_name, 0, sizeof(struct multi_files)); + multi_name->form.option = CURLFORM_FILENAME; + multi_name->form.value = show_filename; + multi->next = multi_name; + + multi = multi_name; } else { - (*multi_current)->next = multi; - *multi_current = multi; + free (multi); + return NULL; } } + + if (*multi_current) + (*multi_current)->next = multi; + + *multi_current = multi; + return *multi_current; } /* Free the items of the list. */ -static void FreeMultiInfo (struct multi_files **multi_start) +static void FreeMultiInfo (struct multi_files *multi_start) { struct multi_files *multi; - while (*multi_start) { - multi = *multi_start; - *multi_start = (*multi_start)->next; + while (multi_start) { + multi = multi_start; + multi_start = multi_start->next; free (multi); } } @@ -677,8 +689,19 @@ static void FreeMultiInfo (struct multi_files **multi_start) * * 'name=@filename;type=image/gif,filename2,filename3' * - * Does use curl_formadd to fulfill it's job. Is heavily based on the - * old curl_formparse code. + * If you want custom headers added for a single part, write them in a separate + * file and do like this: + * + * 'name=foo;headers=@headerfile' or why not + * 'name=@filemame;headers=@headerfile' + * + * To upload a file, but to fake the file name that will be included in the + * formpost, do like this: + * + * 'name=@filename;filename=/dev/null' + * + * This function uses curl_formadd to fulfill it's job. Is heavily based on + * the old curl_formparse code. * ***************************************************************************/ @@ -686,8 +709,8 @@ static void FreeMultiInfo (struct multi_files **multi_start) #define FORM_TYPE_SEPARATOR ';' static int formparse(char *input, - struct HttpPost **httppost, - struct HttpPost **last_post) + 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 */ @@ -718,7 +741,9 @@ static int formparse(char *input, do { /* since this was a file, it may have a content-type specifier - at the end too */ + at the end too, or a filename. Or both. */ + char *ptr; + char *filename=NULL; sep=strchr(contp, FORM_TYPE_SEPARATOR); sep2=strchr(contp, FORM_FILE_SEPARATOR); @@ -729,35 +754,67 @@ static int formparse(char *input, /* no type was specified! */ } + + type = NULL; + if(sep) { /* if we got here on a comma, don't do much */ - if(FORM_FILE_SEPARATOR != *sep) - type = strstr(sep+1, "type="); + if(FORM_FILE_SEPARATOR == *sep) + ptr = NULL; else - type=NULL; + ptr = sep+1; *sep=0; /* terminate file name at separator */ - if(type) { - type += strlen("type="); + while(ptr && (FORM_FILE_SEPARATOR!= *ptr)) { + + /* pass all white spaces */ + while(isspace((int)*ptr)) + ptr++; + + if(curl_strnequal("type=", ptr, 5)) { + + /* set type pointer */ + type = &ptr[5]; - if(2 != sscanf(type, "%127[^/]/%127[^,\n]", - major, minor)) { - fprintf(stderr, "Illegally formatted content-type field!\n"); - free(contents); - FreeMultiInfo (&multi_start); - 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); + /* verify that this is a fine type specifier */ + if(2 != sscanf(type, "%127[^/]/%127[^;,\n]", + major, minor)) { + fprintf(stderr, "Illegally formatted content-type field!\n"); + free(contents); + FreeMultiInfo (multi_start); + return 2; /* illegal content-type syntax! */ + } + /* now point beyond the content-type specifier */ + sep = (char *)type + strlen(major)+strlen(minor)+1; + + *sep=0; /* zero terminate type string */ + + ptr=sep+1; + } + else if(curl_strnequal("filename=", ptr, 9)) { + filename = &ptr[9]; + ptr=strchr(filename, FORM_TYPE_SEPARATOR); + if(!ptr) { + ptr=strchr(filename, FORM_FILE_SEPARATOR); + } + if(ptr) { + *ptr=0; /* zero terminate */ + ptr++; + } + } + else + /* confusion, bail out of loop */ + break; } + /* find the following comma */ + if(ptr) + sep=strchr(ptr, FORM_FILE_SEPARATOR); + else + sep=NULL; } else { - type=NULL; sep=strchr(contp, FORM_FILE_SEPARATOR); } if(sep) { @@ -767,14 +824,17 @@ static int formparse(char *input, } /* if type == NULL curl_formadd takes care of the problem */ - if (!AddMultiFiles (contp, type, &multi_start, &multi_current)) { + if (!AddMultiFiles (contp, type, filename, &multi_start, + &multi_current)) { fprintf(stderr, "Error building form post!\n"); free(contents); - FreeMultiInfo (&multi_start); + FreeMultiInfo (multi_start); return 3; } contp = sep; /* move the contents pointer to after the separator */ + } while(sep && *sep); /* loop if there's another file name */ + /* now we add the multiple files section */ if (multi_start) { struct curl_forms *forms = NULL; @@ -790,7 +850,7 @@ static int formparse(char *input, { fprintf(stderr, "Error building form post!\n"); free(contents); - FreeMultiInfo (&multi_start); + FreeMultiInfo (multi_start); return 4; } for (i = 0, ptr = multi_start; i < count; ++i, ptr = ptr->next) @@ -799,7 +859,7 @@ static int formparse(char *input, forms[i].value = ptr->form.value; } forms[count].option = CURLFORM_END; - FreeMultiInfo (&multi_start); + FreeMultiInfo (multi_start); if (curl_formadd (httppost, last_post, CURLFORM_COPYNAME, name, CURLFORM_ARRAY, forms, CURLFORM_END) != 0) { -- cgit v1.2.3