Revert "Update to 7.40.1"
[platform/upstream/curl.git] / lib / formdata.c
index c7d85c4..3260928 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, 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
 
 #include <curl/curl.h>
 
-/* Length of the random boundary string. */
-#define BOUNDARY_LENGTH 40
-
 #if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY)
 
 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
 #include <libgen.h>
 #endif
 
-#include "curl_urldata.h" /* for struct SessionHandle */
-#include "curl_formdata.h"
-#include "curl_rand.h"
-#include "curl_strequal.h"
+#include "urldata.h" /* for struct SessionHandle */
+#include "formdata.h"
+#include "vtls/vtls.h"
+#include "strequal.h"
 #include "curl_memory.h"
-#include "curl_sendf.h"
+#include "sendf.h"
 
 #define _MPRINTF_REPLACE /* use our functions only */
 #include <curl/mprintf.h>
 
 /* The last #include file should be: */
-#include "curl_memdebug.h"
+#include "memdebug.h"
 
 #endif  /* !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) */
 
@@ -56,6 +53,7 @@ static char *Curl_basename(char *path);
 #endif
 
 static size_t readfromfile(struct Form *form, char *buffer, size_t size);
+static char *formboundary(struct SessionHandle *data);
 
 /* What kind of Content-Type to use on un-specified files with unrecognized
    extensions. */
@@ -170,8 +168,8 @@ static FormInfo * AddFormInfo(char *value,
  * Returns some valid contenttype for filename.
  *
  ***************************************************************************/
-static const char * ContentTypeForFilename (const char *filename,
-                                            const char *prevtype)
+static const char *ContentTypeForFilename(const char *filename,
+                                          const char *prevtype)
 {
   const char *contenttype = NULL;
   unsigned int i;
@@ -180,7 +178,7 @@ static const char * ContentTypeForFilename (const char *filename,
    * extensions and pick the first we match!
    */
   struct ContentType {
-    char extension[6];
+    const char *extension;
     const char *type;
   };
   static const struct ContentType ctts[]={
@@ -428,7 +426,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
 
       /* Get contents from a given file name */
     case CURLFORM_FILECONTENT:
-      if(current_form->flags != 0)
+      if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
         return_value = CURL_FORMADD_OPTION_TWICE;
       else {
         const char *filename = array_state?
@@ -669,9 +667,11 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
         if(((form->flags & HTTPPOST_FILENAME) ||
             (form->flags & HTTPPOST_BUFFER)) &&
            !form->contenttype ) {
+          char *f = form->flags & HTTPPOST_BUFFER?
+            form->showfilename : form->value;
+
           /* our contenttype is missing */
-          form->contenttype
-            = strdup(ContentTypeForFilename(form->value, prevtype));
+          form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
           if(!form->contenttype) {
             return_value = CURL_FORMADD_MEMORY;
             break;
@@ -776,6 +776,70 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
   return result;
 }
 
+#ifdef __VMS
+#include <fabdef.h>
+/*
+ * get_vms_file_size does what it takes to get the real size of the file
+ *
+ * For fixed files, find out the size of the EOF block and adjust.
+ *
+ * For all others, have to read the entire file in, discarding the contents.
+ * Most posted text files will be small, and binary files like zlib archives
+ * and CD/DVD images should be either a STREAM_LF format or a fixed format.
+ *
+ */
+curl_off_t VmsRealFileSize(const char * name,
+                           const struct_stat * stat_buf)
+{
+  char buffer[8192];
+  curl_off_t count;
+  int ret_stat;
+  FILE * file;
+
+  file = fopen(name, "r");
+  if(file == NULL)
+    return 0;
+
+  count = 0;
+  ret_stat = 1;
+  while(ret_stat > 0) {
+    ret_stat = fread(buffer, 1, sizeof(buffer), file);
+    if(ret_stat != 0)
+      count += ret_stat;
+  }
+  fclose(file);
+
+  return count;
+}
+
+/*
+ *
+ *  VmsSpecialSize checks to see if the stat st_size can be trusted and
+ *  if not to call a routine to get the correct size.
+ *
+ */
+static curl_off_t VmsSpecialSize(const char * name,
+                                 const struct_stat * stat_buf)
+{
+  switch(stat_buf->st_fab_rfm) {
+  case FAB$C_VAR:
+  case FAB$C_VFC:
+    return VmsRealFileSize(name, stat_buf);
+    break;
+  default:
+    return stat_buf->st_size;
+  }
+}
+
+#endif
+
+#ifndef __VMS
+#define filesize(name, stat_data) (stat_data.st_size)
+#else
+    /* Getting the expected file size needs help on VMS */
+#define filesize(name, stat_data) VmsSpecialSize(name, &stat_data)
+#endif
+
 /*
  * AddFormData() adds a chunk of data to the FormData linked list.
  *
@@ -830,9 +894,10 @@ static CURLcode AddFormData(struct FormData **formp,
          file */
       if(!strequal("-", newform->line)) {
         struct_stat file;
-        if(!stat(newform->line, &file)) {
-          *size += file.st_size;
-        }
+        if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
+          *size += filesize(newform->line, file);
+        else
+          return CURLE_BAD_FUNCTION_ARGUMENT;
       }
     }
   }
@@ -857,8 +922,8 @@ static CURLcode AddFormDataf(struct FormData **formp,
 }
 
 /*
- * Curl_formclean() is used from curl_http.c, this cleans a built FormData
- * linked list
+ * Curl_formclean() is used from http.c, this cleans a built FormData linked
+ * list
  */
 void Curl_formclean(struct FormData **form_ptr)
 {
@@ -1024,6 +1089,49 @@ static char *strippath(const char *fullfile)
   return base; /* returns an allocated string or NULL ! */
 }
 
+static CURLcode formdata_add_filename(const struct curl_httppost *file,
+                                      struct FormData **form,
+                                      curl_off_t *size)
+{
+  CURLcode result = CURLE_OK;
+  char *filename = file->showfilename;
+  char *filebasename = NULL;
+  char *filename_escaped = NULL;
+
+  if(!filename) {
+    filebasename = strippath(file->contents);
+    if(!filebasename)
+      return CURLE_OUT_OF_MEMORY;
+    filename = filebasename;
+  }
+
+  if(strchr(filename, '\\') || strchr(filename, '"')) {
+    char *p0, *p1;
+
+    /* filename need be escaped */
+    filename_escaped = malloc(strlen(filename)*2+1);
+    if(!filename_escaped) {
+      Curl_safefree(filebasename);
+      return CURLE_OUT_OF_MEMORY;
+    }
+    p0 = filename_escaped;
+    p1 = filename;
+    while(*p1) {
+      if(*p1 == '\\' || *p1 == '"')
+        *p0++ = '\\';
+      *p0++ = *p1++;
+    }
+    *p0 = '\0';
+    filename = filename_escaped;
+  }
+  result = AddFormDataf(form, size,
+                        "; filename=\"%s\"",
+                        filename);
+  Curl_safefree(filename_escaped);
+  Curl_safefree(filebasename);
+  return result;
+}
+
 /*
  * Curl_getformdata() converts a linked list of "meta data" into a complete
  * (possibly huge) multipart formdata. The input list is in 'post', while the
@@ -1058,7 +1166,7 @@ CURLcode Curl_getformdata(struct SessionHandle *data,
   if(!post)
     return result; /* no input => no output! */
 
-  boundary = Curl_FormBoundary();
+  boundary = formboundary(data);
   if(!boundary)
     return CURLE_OUT_OF_MEMORY;
 
@@ -1114,14 +1222,14 @@ CURLcode Curl_getformdata(struct SessionHandle *data,
          the magic to include several files with the same field name */
 
       Curl_safefree(fileboundary);
-      fileboundary = Curl_FormBoundary();
+      fileboundary = formboundary(data);
       if(!fileboundary) {
         result = CURLE_OUT_OF_MEMORY;
         break;
       }
 
       result = AddFormDataf(&form, &size,
-                            "\r\nContent-Type: multipart/mixed,"
+                            "\r\nContent-Type: multipart/mixed;"
                             " boundary=%s\r\n",
                             fileboundary);
       if(result)
@@ -1138,22 +1246,13 @@ CURLcode Curl_getformdata(struct SessionHandle *data,
 
       if(post->more) {
         /* if multiple-file */
-        char *filebasename = NULL;
-        if(!file->showfilename) {
-          filebasename = strippath(file->contents);
-          if(!filebasename) {
-            result = CURLE_OUT_OF_MEMORY;
-            break;
-          }
-        }
-
         result = AddFormDataf(&form, &size,
                               "\r\n--%s\r\nContent-Disposition: "
-                              "attachment; filename=\"%s\"",
-                              fileboundary,
-                              (file->showfilename?file->showfilename:
-                               filebasename));
-        Curl_safefree(filebasename);
+                              "attachment",
+                              fileboundary);
+        if(result)
+          break;
+        result = formdata_add_filename(file, &form, &size);
         if(result)
           break;
       }
@@ -1163,14 +1262,7 @@ CURLcode Curl_getformdata(struct SessionHandle *data,
            HTTPPOST_CALLBACK cases the ->showfilename struct member is always
            assigned at this point */
         if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) {
-          char *filebasename=
-            (!post->showfilename)?strippath(post->contents):NULL;
-
-          result = AddFormDataf(&form, &size,
-                                "; filename=\"%s\"",
-                                (post->showfilename?post->showfilename:
-                                 filebasename));
-          Curl_safefree(filebasename);
+          result = formdata_add_filename(post, &form, &size);
         }
 
         if(result)
@@ -1316,6 +1408,36 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata )
   return 0;
 }
 
+#ifndef __VMS
+# define fopen_read fopen
+#else
+  /*
+   * vmsfopenread
+   *
+   * For upload to work as expected on VMS, different optional
+   * parameters must be added to the fopen command based on
+   * record format of the file.
+   *
+   */
+# define fopen_read vmsfopenread
+static FILE * vmsfopenread(const char *file, const char *mode) {
+  struct_stat statbuf;
+  int result;
+
+  result = stat(file, &statbuf);
+
+  switch (statbuf.st_fab_rfm) {
+  case FAB$C_VAR:
+  case FAB$C_VFC:
+  case FAB$C_STMCR:
+    return fopen(file, "r");
+    break;
+  default:
+    return fopen(file, "r", "rfm=stmlf", "ctx=stm");
+  }
+}
+#endif
+
 /*
  * readfromfile()
  *
@@ -1338,7 +1460,7 @@ static size_t readfromfile(struct Form *form, char *buffer,
   else {
     if(!form->fp) {
       /* this file hasn't yet been opened */
-      form->fp = fopen(form->data->line, "rb"); /* b is for binary */
+      form->fp = fopen_read(form->data->line, "rb"); /* b is for binary */
       if(!form->fp)
         return (size_t)-1; /* failure */
     }
@@ -1433,6 +1555,18 @@ char *Curl_formpostheader(void *formp, size_t *len)
   return header;
 }
 
+/*
+ * formboundary() creates a suitable boundary string and returns an allocated
+ * one.
+ */
+static char *formboundary(struct SessionHandle *data)
+{
+  /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
+     combinations */
+  return aprintf("------------------------%08x%08x",
+                 Curl_rand(data), Curl_rand(data));
+}
+
 #else  /* CURL_DISABLE_HTTP */
 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
                           struct curl_httppost **last_post,
@@ -1458,37 +1592,5 @@ void curl_formfree(struct curl_httppost *form)
   /* does nothing HTTP is disabled */
 }
 
-#endif  /* CURL_DISABLE_HTTP */
-
-#if !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY)
-
-/*
- * Curl_FormBoundary() creates a suitable boundary string and returns an
- * allocated one. This is also used by SSL-code so it must be present even
- * if HTTP is disabled!
- */
-char *Curl_FormBoundary(void)
-{
-  char *retstring;
-  size_t i;
-
-  static const char table16[]="0123456789abcdef";
 
-  retstring = malloc(BOUNDARY_LENGTH+1);
-
-  if(!retstring)
-    return NULL; /* failed */
-
-  strcpy(retstring, "----------------------------");
-
-  for(i=strlen(retstring); i<BOUNDARY_LENGTH; i++)
-    retstring[i] = table16[Curl_rand()%16];
-
-  /* 28 dashes and 12 hexadecimal digits makes 12^16 (184884258895036416)
-     combinations */
-  retstring[BOUNDARY_LENGTH]=0; /* zero terminate */
-
-  return retstring;
-}
-
-#endif  /* !defined(CURL_DISABLE_HTTP) || defined(USE_SSLEAY) */
+#endif  /* !defined(CURL_DISABLE_HTTP) */