]> granicus.if.org Git - curl/commitdiff
cli tool: fix mime post with --disable-libcurl-option configure option
authorPatrick Monnerat <patrick@monnerat.net>
Tue, 19 Feb 2019 16:08:58 +0000 (17:08 +0100)
committerPatrick Monnerat <patrick@monnerat.net>
Tue, 19 Feb 2019 16:08:58 +0000 (17:08 +0100)
Reported-by: Marcel Raad
Fixes #3576
Closes #3583

src/tool_cfgable.c
src/tool_cfgable.h
src/tool_formparse.c
src/tool_formparse.h
src/tool_getparam.c
src/tool_operate.c
src/tool_setopt.c
src/tool_setopt.h

index 6d4a0ed9b7657101953e72962220d685c980d7aa..cf5212bab09cf4321e496b489304c36fefdd510d 100644 (file)
@@ -144,10 +144,10 @@ static void free_config_fields(struct OperationConfig *config)
   curl_slist_free_all(config->headers);
   curl_slist_free_all(config->proxyheaders);
 
-  if(config->mimepost) {
-    tool_mime_free(config->mimepost);
-    config->mimepost = NULL;
-  }
+  curl_mime_free(config->mimepost);
+  config->mimepost = NULL;
+  tool_mime_free(config->mimeroot);
+  config->mimeroot = NULL;
   config->mimecurrent = NULL;
 
   curl_slist_free_all(config->telnet_options);
index 0ebe947ae92fb7ab377707b1b5164e21539d9c75..2adfcae23e59a8989abc7c31ff479717718a9fb4 100644 (file)
@@ -178,8 +178,9 @@ struct OperationConfig {
   curl_off_t condtime;
   struct curl_slist *headers;
   struct curl_slist *proxyheaders;
-  tool_mime *mimepost;
+  tool_mime *mimeroot;
   tool_mime *mimecurrent;
+  curl_mime *mimepost;
   struct curl_slist *telnet_options;
   struct curl_slist *resolve;
   struct curl_slist *connect_to;
index bba1d07e762c7611e9215ffaf6b3faf64405a9da..49993470b3f5e32019c59ffe4688d3e5c398a65a 100644 (file)
@@ -166,7 +166,6 @@ void tool_mime_free(tool_mime *mime)
       tool_mime_free(mime->subparts);
     if(mime->prev)
       tool_mime_free(mime->prev);
-    curl_mime_free(mime->handle);
     CONST_SAFEFREE(mime->name);
     CONST_SAFEFREE(mime->filename);
     CONST_SAFEFREE(mime->type);
@@ -237,6 +236,109 @@ int tool_mime_stdin_seek(void *instream, curl_off_t offset, int whence)
   return CURL_SEEKFUNC_OK;
 }
 
+/* Translate an internal mime tree into a libcurl mime tree. */
+
+static CURLcode tool2curlparts(CURL *curl, tool_mime *m, curl_mime *mime)
+{
+  CURLcode ret = CURLE_OK;
+  curl_mimepart *part = NULL;
+  curl_mime *submime = NULL;
+  const char *filename = NULL;
+
+  if(m) {
+    ret = tool2curlparts(curl, m->prev, mime);
+    if(!ret) {
+      part = curl_mime_addpart(mime);
+      if(!part)
+        ret = CURLE_OUT_OF_MEMORY;
+    }
+    if(!ret) {
+      filename = m->filename;
+      switch(m->kind) {
+      case TOOLMIME_PARTS:
+        ret = tool2curlmime(curl, m, &submime);
+        if(!ret) {
+          ret = curl_mime_subparts(part, submime);
+          if(ret)
+            curl_mime_free(submime);
+        }
+        break;
+
+      case TOOLMIME_DATA:
+#ifdef CURL_DOES_CONVERSIONS
+        /* Our data is always textual: convert it to ASCII. */
+        {
+          size_t size = strlen(m->data);
+          char *cp = malloc(size + 1);
+
+          if(!cp)
+            ret = CURLE_OUT_OF_MEMORY;
+          else {
+            memcpy(cp, m->data, size + 1);
+            ret = convert_to_network(cp, size);
+            if(!ret)
+              ret = curl_mime_data(part, cp, CURL_ZERO_TERMINATED);
+            free(cp);
+          }
+        }
+#else
+        ret = curl_mime_data(part, m->data, CURL_ZERO_TERMINATED);
+#endif
+        break;
+
+      case TOOLMIME_FILE:
+      case TOOLMIME_FILEDATA:
+        ret = curl_mime_filedata(part, m->data);
+        if(!ret && m->kind == TOOLMIME_FILEDATA && !filename)
+          ret = curl_mime_filename(part, NULL);
+        break;
+
+      case TOOLMIME_STDIN:
+        if(!filename)
+          filename = "-";
+        /* FALLTHROUGH */
+      case TOOLMIME_STDINDATA:
+        ret = curl_mime_data_cb(part, m->size,
+                                (curl_read_callback) tool_mime_stdin_read,
+                                (curl_seek_callback) tool_mime_stdin_seek,
+                                NULL, m);
+        break;
+
+      default:
+        /* Other cases not possible in this context. */
+        break;
+      }
+    }
+    if(!ret && filename)
+      ret = curl_mime_filename(part, filename);
+    if(!ret)
+      ret = curl_mime_type(part, m->type);
+    if(!ret)
+      ret = curl_mime_headers(part, m->headers, 0);
+    if(!ret)
+      ret = curl_mime_encoder(part, m->encoder);
+    if(!ret)
+      ret = curl_mime_name(part, m->name);
+  }
+  return ret;
+}
+
+CURLcode tool2curlmime(CURL *curl, tool_mime *m, curl_mime **mime)
+{
+  CURLcode ret = CURLE_OK;
+
+  *mime = curl_mime_init(curl);
+  if(!*mime)
+    ret = CURLE_OUT_OF_MEMORY;
+  else
+    ret = tool2curlparts(curl, m->subparts, *mime);
+  if(ret) {
+    curl_mime_free(*mime);
+    *mime = NULL;
+  }
+  return ret;
+}
+
 /*
  * helper function to get a word from form param
  * after call get_parm_word, str either point to string end
@@ -633,7 +735,7 @@ static int get_param_part(struct OperationConfig *config, char endchar,
 
 int formparse(struct OperationConfig *config,
               const char *input,
-              tool_mime **mimepost,
+              tool_mime **mimeroot,
               tool_mime **mimecurrent,
               bool literal_value)
 {
@@ -652,8 +754,8 @@ int formparse(struct OperationConfig *config,
 
   /* Allocate the main mime structure if needed. */
   if(!*mimecurrent) {
-    NULL_CHECK(*mimepost, tool_mime_new_parts(NULL), 1);
-    *mimecurrent = *mimepost;
+    NULL_CHECK(*mimeroot, tool_mime_new_parts(NULL), 1);
+    *mimecurrent = *mimeroot;
   }
 
   /* Make a copy we can overwrite. */
@@ -683,7 +785,7 @@ int formparse(struct OperationConfig *config,
     }
     else if(!name && !strcmp(contp, ")") && !literal_value) {
       /* Ending a multipart. */
-      if(*mimecurrent == *mimepost) {
+      if(*mimecurrent == *mimeroot) {
         warnf(config->global, "no multipart to terminate!\n");
         Curl_safefree(contents);
         return 6;
@@ -721,6 +823,7 @@ int formparse(struct OperationConfig *config,
                    tool_mime_new_filedata(subparts, data, TRUE, &res), 9);
         part->headers = headers;
         headers = NULL;
+        part->config = config->global;
         if(res == CURLE_READ_ERROR) {
             /* An error occurred while reading stdin: if read has started,
                issue the error now. Else, delay it until processed by
@@ -758,6 +861,7 @@ int formparse(struct OperationConfig *config,
                                                 &res), 15);
         part->headers = headers;
         headers = NULL;
+        part->config = config->global;
         if(res == CURLE_READ_ERROR) {
             /* An error occurred while reading stdin: if read has started,
                issue the error now. Else, delay it until processed by
index 203f5ab3028d8ff5f5284d030164a5077a42485b..750fe451fa3d24c8a129ca626163ff7547808aa7 100644 (file)
@@ -50,7 +50,6 @@ struct tool_mime {
   struct curl_slist *headers;   /* User-defined headers. */
   /* TOOLMIME_PARTS fields. */
   tool_mime *subparts;          /* Part's subparts. */
-  curl_mime *handle;            /* Libcurl mime handle. */
   /* TOOLMIME_STDIN/TOOLMIME_STDINDATA fields. */
   curl_off_t origin;            /* Stdin read origin offset. */
   curl_off_t size;              /* Stdin data size. */
@@ -64,9 +63,10 @@ int tool_mime_stdin_seek(void *instream, curl_off_t offset, int whence);
 
 int formparse(struct OperationConfig *config,
               const char *input,
-              tool_mime **mimepost,
+              tool_mime **mimeroot,
               tool_mime **mimecurrent,
               bool literal_value);
+CURLcode tool2curlmime(CURL *curl, tool_mime *m, curl_mime **mime);
 void tool_mime_free(tool_mime *mime);
 
 #endif /* HEADER_CURL_TOOL_FORMPARSE_H */
index c7ba5f243b0b59a767bc35b3de14fc89658252d9..82ba8b2157c5107dc99d26e842a505a8a1e2f500 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, 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
@@ -1691,7 +1691,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
          to sort this out slowly and carefully */
       if(formparse(config,
                    nextarg,
-                   &config->mimepost,
+                   &config->mimeroot,
                    &config->mimecurrent,
                    (subletter == 's')?TRUE:FALSE)) /* 's' is literal string */
         return PARAM_BAD_USE;
index 7d58dde27c80ecec268e962947a4c6b6ccab4c1a..a8698285d71f4cd5cda8c0990852388c7d3d6bb2 100644 (file)
@@ -945,6 +945,9 @@ static CURLcode operate_do(struct GlobalConfig *global,
                     config->postfieldsize);
           break;
         case HTTPREQ_MIMEPOST:
+          result = tool2curlmime(curl, config->mimeroot, &config->mimepost);
+          if(result)
+            goto show_error;
           my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost);
           break;
         default:
index 26102d3129d05ae3cc51e33fdaf81c7fe5e740cb..745b4546ed7493f3aa24a2f2d8b25498450e21c4 100644 (file)
@@ -414,60 +414,45 @@ static CURLcode libcurl_generate_slist(struct curl_slist *slist, int *slistno)
 static CURLcode libcurl_generate_mime(CURL *curl,
                                       struct GlobalConfig *config,
                                       tool_mime *toolmime,
-                                      curl_mime **mime,
                                       int *mimeno);     /* Forward. */
 
-/* Wrapper to build and generate source code for a mime part. */
+/* Wrapper to generate source code for a mime part. */
 static CURLcode libcurl_generate_mime_part(CURL *curl,
                                            struct GlobalConfig *config,
                                            tool_mime *part,
-                                           curl_mime *mime,
                                            int mimeno)
 {
   CURLcode ret = CURLE_OK;
-  curl_mimepart *mimepart;
   int submimeno = 0;
-  curl_mime *submime = NULL;
   char *escaped = NULL;
   const char *data = NULL;
   const char *filename = part->filename;
 
   /* Parts are linked in reverse order. */
   if(part->prev) {
-    ret = libcurl_generate_mime_part(curl, config, part->prev, mime, mimeno);
+    ret = libcurl_generate_mime_part(curl, config, part->prev, mimeno);
     if(ret)
       return ret;
   }
 
   /* Create the part. */
-  mimepart = curl_mime_addpart(mime);
-  NULL_CHECK(mimepart);
-  if(config->libcurl)
-    CODE2("part%d = curl_mime_addpart(mime%d);", mimeno, mimeno);
+  CODE2("part%d = curl_mime_addpart(mime%d);", mimeno, mimeno);
 
   switch(part->kind) {
   case TOOLMIME_PARTS:
-    ret = libcurl_generate_mime(curl, config, part, &submime, &submimeno);
+    ret = libcurl_generate_mime(curl, config, part, &submimeno);
     if(!ret) {
-      ret = curl_mime_subparts(mimepart, submime);
-      if(!ret) {
-        submime = NULL;
-        if(config->libcurl) {
-          CODE2("curl_mime_subparts(part%d, mime%d);", mimeno, submimeno);
-          CODE1("mime%d = NULL;", submimeno);   /* Avoid freeing in CLEAN. */
-        }
-      }
+      CODE2("curl_mime_subparts(part%d, mime%d);", mimeno, submimeno);
+      CODE1("mime%d = NULL;", submimeno);   /* Avoid freeing in CLEAN. */
     }
     break;
 
   case TOOLMIME_DATA:
 #ifdef CURL_DOES_CONVERSIONS
-    if(config->libcurl) {
-      /* Data will be set in ASCII, thus issue a comment with clear text. */
-      escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
-      NULL_CHECK(escaped);
-      CODE1("/* \"%s\" */", escaped);
-    }
+    /* Data will be set in ASCII, thus issue a comment with clear text. */
+    escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
+    NULL_CHECK(escaped);
+    CODE1("/* \"%s\" */", escaped);
 
     /* Our data is always textual: convert it to ASCII. */
     {
@@ -482,9 +467,7 @@ static CURLcode libcurl_generate_mime_part(CURL *curl,
 #else
     data = part->data;
 #endif
-    if(!ret)
-      ret = curl_mime_data(mimepart, data, CURL_ZERO_TERMINATED);
-    if(!ret && config->libcurl) {
+    if(!ret) {
       Curl_safefree(escaped);
       escaped = c_escape(data, CURL_ZERO_TERMINATED);
       NULL_CHECK(escaped);
@@ -495,16 +478,11 @@ static CURLcode libcurl_generate_mime_part(CURL *curl,
 
   case TOOLMIME_FILE:
   case TOOLMIME_FILEDATA:
-    ret = curl_mime_filedata(mimepart, part->data);
-    if(!ret && config->libcurl) {
-      escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
-      NULL_CHECK(escaped);
-      CODE2("curl_mime_filedata(part%d, \"%s\");", mimeno, escaped);
-    }
-    if(!ret && part->kind == TOOLMIME_FILEDATA && !filename) {
-      ret = curl_mime_filename(mimepart, NULL);
-      if(!ret && config->libcurl)
-        CODE1("curl_mime_filename(part%d, NULL);", mimeno);
+    escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
+    NULL_CHECK(escaped);
+    CODE2("curl_mime_filedata(part%d, \"%s\");", mimeno, escaped);
+    if(part->kind == TOOLMIME_FILEDATA && !filename) {
+      CODE1("curl_mime_filename(part%d, NULL);", mimeno);
     }
     break;
 
@@ -513,17 +491,10 @@ static CURLcode libcurl_generate_mime_part(CURL *curl,
       filename = "-";
     /* FALLTHROUGH */
   case TOOLMIME_STDINDATA:
-    part->config = config;
-    ret = curl_mime_data_cb(mimepart, part->size,
-                            (curl_read_callback) tool_mime_stdin_read,
-                            (curl_seek_callback) tool_mime_stdin_seek,
-                            NULL, part);
-    if(!ret && config->libcurl) {
-      /* Can only be reading stdin in the current context. */
-      CODE1("curl_mime_data_cb(part%d, -1, (curl_read_callback) fread, \\",
-            mimeno);
-      CODE0("                  (curl_seek_callback) fseek, NULL, stdin);");
-      }
+    /* Can only be reading stdin in the current context. */
+    CODE1("curl_mime_data_cb(part%d, -1, (curl_read_callback) fread, \\",
+          mimeno);
+    CODE0("                  (curl_seek_callback) fseek, NULL, stdin);");
     break;
   default:
     /* Other cases not possible in this context. */
@@ -531,55 +502,40 @@ static CURLcode libcurl_generate_mime_part(CURL *curl,
   }
 
   if(!ret && part->encoder) {
-    ret = curl_mime_encoder(mimepart, part->encoder);
-    if(!ret && config->libcurl) {
-      Curl_safefree(escaped);
-      escaped = c_escape(part->encoder, CURL_ZERO_TERMINATED);
-      NULL_CHECK(escaped);
-      CODE2("curl_mime_encoder(part%d, \"%s\");", mimeno, escaped);
-    }
+    Curl_safefree(escaped);
+    escaped = c_escape(part->encoder, CURL_ZERO_TERMINATED);
+    NULL_CHECK(escaped);
+    CODE2("curl_mime_encoder(part%d, \"%s\");", mimeno, escaped);
   }
 
   if(!ret && filename) {
-    ret = curl_mime_filename(mimepart, filename);
-    if(!ret && config->libcurl) {
-      Curl_safefree(escaped);
-      escaped = c_escape(filename, CURL_ZERO_TERMINATED);
-      NULL_CHECK(escaped);
-      CODE2("curl_mime_filename(part%d, \"%s\");", mimeno, escaped);
-    }
+    Curl_safefree(escaped);
+    escaped = c_escape(filename, CURL_ZERO_TERMINATED);
+    NULL_CHECK(escaped);
+    CODE2("curl_mime_filename(part%d, \"%s\");", mimeno, escaped);
   }
 
   if(!ret && part->name) {
-    ret = curl_mime_name(mimepart, part->name);
-    if(!ret && config->libcurl) {
-      Curl_safefree(escaped);
-      escaped = c_escape(part->name, CURL_ZERO_TERMINATED);
-      NULL_CHECK(escaped);
-      CODE2("curl_mime_name(part%d, \"%s\");", mimeno, escaped);
-    }
+    Curl_safefree(escaped);
+    escaped = c_escape(part->name, CURL_ZERO_TERMINATED);
+    NULL_CHECK(escaped);
+    CODE2("curl_mime_name(part%d, \"%s\");", mimeno, escaped);
   }
 
   if(!ret && part->type) {
-    ret = curl_mime_type(mimepart, part->type);
-    if(!ret && config->libcurl) {
-      Curl_safefree(escaped);
-      escaped = c_escape(part->type, CURL_ZERO_TERMINATED);
-      NULL_CHECK(escaped);
-      CODE2("curl_mime_type(part%d, \"%s\");", mimeno, escaped);
-    }
+    Curl_safefree(escaped);
+    escaped = c_escape(part->type, CURL_ZERO_TERMINATED);
+    NULL_CHECK(escaped);
+    CODE2("curl_mime_type(part%d, \"%s\");", mimeno, escaped);
   }
 
   if(!ret && part->headers) {
-    ret = curl_mime_headers(mimepart, part->headers, 0);
-    if(!ret && config->libcurl) {
-      int slistno;
-
-      ret = libcurl_generate_slist(part->headers, &slistno);
-      if(!ret) {
-        CODE2("curl_mime_headers(part%d, slist%d, 1);", mimeno, slistno);
-        CODE1("slist%d = NULL;", slistno); /* Prevent CLEANing. */
-      }
+    int slistno;
+
+    ret = libcurl_generate_slist(part->headers, &slistno);
+    if(!ret) {
+      CODE2("curl_mime_headers(part%d, slist%d, 1);", mimeno, slistno);
+      CODE1("slist%d = NULL;", slistno); /* Prevent CLEANing. */
     }
   }
 
@@ -589,38 +545,30 @@ nomem:
     free((char *) data);
 #endif
 
-  curl_mime_free(submime);
   Curl_safefree(escaped);
   return ret;
 }
 
-/* Wrapper to build and generate source code for a mime structure. */
+/* Wrapper to generate source code for a mime structure. */
 static CURLcode libcurl_generate_mime(CURL *curl,
                                       struct GlobalConfig *config,
                                       tool_mime *toolmime,
-                                      curl_mime **mime,
                                       int *mimeno)
 {
   CURLcode ret = CURLE_OK;
 
-  *mime = curl_mime_init(curl);
-  NULL_CHECK(*mime);
-
-  if(config->libcurl) {
-    /* May need several mime variables, so invent name. */
-    *mimeno = ++easysrc_mime_count;
-    DECL1("curl_mime *mime%d;", *mimeno);
-    DATA1("mime%d = NULL;", *mimeno);
-    CODE1("mime%d = curl_mime_init(hnd);", *mimeno);
-    CLEAN1("curl_mime_free(mime%d);", *mimeno);
-    CLEAN1("mime%d = NULL;", *mimeno);
-  }
+  /* May need several mime variables, so invent name. */
+  *mimeno = ++easysrc_mime_count;
+  DECL1("curl_mime *mime%d;", *mimeno);
+  DATA1("mime%d = NULL;", *mimeno);
+  CODE1("mime%d = curl_mime_init(hnd);", *mimeno);
+  CLEAN1("curl_mime_free(mime%d);", *mimeno);
+  CLEAN1("mime%d = NULL;", *mimeno);
 
   if(toolmime->subparts) {
-    if(config->libcurl)
-      DECL1("curl_mimepart *part%d;", *mimeno);
+    DECL1("curl_mimepart *part%d;", *mimeno);
     ret = libcurl_generate_mime_part(curl, config,
-                                     toolmime->subparts, *mime, *mimeno);
+                                     toolmime->subparts, *mimeno);
   }
 
 nomem:
@@ -630,18 +578,16 @@ nomem:
 /* setopt wrapper for CURLOPT_MIMEPOST */
 CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config,
                               const char *name, CURLoption tag,
-                              tool_mime *mimepost)
+                              curl_mime *mimepost)
 {
-  CURLcode ret = CURLE_OK;
+  CURLcode ret = curl_easy_setopt(curl, tag, mimepost);
   int mimeno = 0;
 
-  ret = libcurl_generate_mime(curl, config, mimepost,
-                              &mimepost->handle, &mimeno);
-
-  if(!ret) {
-    ret = curl_easy_setopt(curl, tag, mimepost->handle);
+  if(!ret && config->libcurl) {
+    ret = libcurl_generate_mime(curl, config,
+                                config->current->mimeroot, &mimeno);
 
-    if(config->libcurl && !ret)
+    if(!ret)
       CODE2("curl_easy_setopt(hnd, %s, mime%d);", name, mimeno);
   }
 
index 4a03a06fce71a8a74d9c1edf508071dac8f5a681..663041f65d76a59153f3333e5ae4f060301fc54a 100644 (file)
@@ -89,7 +89,7 @@ CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config,
                              const NameValueUnsigned *nv, long lval);
 CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config,
                               const char *name, CURLoption tag,
-                              tool_mime *mimepost);
+                              curl_mime *mimepost);
 CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config,
                            const char *name, CURLoption tag,
                            struct curl_slist *list);