now -F supports 'filename=blabla' for parts that upload a file, to set the
authorDaniel Stenberg <daniel@haxx.se>
Mon, 11 Mar 2002 15:20:56 +0000 (15:20 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 11 Mar 2002 15:20:56 +0000 (15:20 +0000)
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

index 24b53283d98b976257a86ca8fd78baa292a5df59..c0f67e86989c8751894842fa7365c4997e23382d 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___ 
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, 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) {