Index: docs/libcurl/curl_easy_setopt.3
===================================================================
RCS file: /cvsroot/curl/curl/docs/libcurl/curl_easy_setopt.3,v
retrieving revision 1.200
diff -u -r1.200 curl_easy_setopt.3
--- docs/libcurl/curl_easy_setopt.3	9 Oct 2007 14:53:50 -0000	1.200
+++ docs/libcurl/curl_easy_setopt.3	12 Oct 2007 17:03:35 -0000
@@ -386,8 +386,7 @@
 .SH NETWORK OPTIONS
 .IP CURLOPT_URL
 The actual URL to deal with. The parameter should be a char * to a zero
-terminated string. The string must remain present until curl no longer needs
-it, as it doesn't copy the string.
+terminated string.
 
 If the given URL lacks the protocol part ("http://" or "ftp://" etc), it will
 attempt to guess which protocol to use based on the given host name. If the
@@ -662,14 +661,16 @@
 application/x-www-form-urlencoded" header. (This is by far the most commonly
 used POST method).
 
-Use the \fICURLOPT_POSTFIELDS\fP option to specify what data to post and
-\fICURLOPT_POSTFIELDSIZE\fP to set the data size.
+Use one of \fICURLOPT_POSTFIELDS\fP or \fICURLOPT_COPYPOSTFIELDS\fP options to
+specify what data to post and \fICURLOPT_POSTFIELDSIZE\fP or
+\fICURLOPT_POSTFIELDSIZE_LARGE\fP to set the data size.
 
 Optionally, you can provide data to POST using the \fICURLOPT_READFUNCTION\fP
 and \fICURLOPT_READDATA\fP options but then you must make sure to not set
 \fICURLOPT_POSTFIELDS\fP to anything but NULL. When providing data with a
 callback, you must transmit it using chunked transfer-encoding or you must set
-the size of the data with the \fICURLOPT_POSTFIELDSIZE\fP option.
+the size of the data with the \fICURLOPT_POSTFIELDSIZE\fP or
+\fICURLOPT_POSTFIELDSIZE_LARGE\fP option.
 
 You can override the default POST Content-Type: header by setting your own
 with \fICURLOPT_HTTPHEADER\fP.
@@ -690,11 +691,14 @@
 re-used handle, you must explicitly set the new request type using
 \fICURLOPT_NOBODY\fP or \fICURLOPT_HTTPGET\fP or similar.
 .IP CURLOPT_POSTFIELDS
-Pass a char * as parameter, which should be the full data to post in an HTTP
+Pass a void * as parameter, which should be the full data to post in an HTTP
 POST operation. You must make sure that the data is formatted the way you want
 the server to receive it. libcurl will not convert or encode it for you. Most
 web servers will assume this data to be url-encoded. Take note.
 
+The pointed data are NOT copied by the library: as a consequence, they must
+be preserved by the calling application until the transfer finishes.
+
 This POST is a normal application/x-www-form-urlencoded kind (and libcurl will
 set that Content-Type by default when this option is used), which is the most
 commonly used one by HTML forms. See also the \fICURLOPT_POST\fP. Using
@@ -721,6 +725,21 @@
 \fICURLOPT_POSTFIELDS\fP data to prevent libcurl from doing strlen() on the
 data to figure out the size. This is the large file version of the
 \fICURLOPT_POSTFIELDSIZE\fP option. (Added in 7.11.1)
+.IP CURLOPT_COPYPOSTFIELDS
+Pass a char * as parameter, which should be the full data to post in an HTTP
+POST operation. It behaves has the \fICURLOPT_POSTFIELDS\fP option, but the
+original data are copied by the library, allowing the application to overwrite
+the original data after setting this option.
+
+Because data are copied, care must be taken when using this option in
+conjunction with \fICURLOPT_POSTFIELDSIZE\fP or
+\fICURLOPT_POSTFIELDSIZE_LARGE\fP: If the size has not been set prior to
+\fICURLOPT_COPYPOSTFIELDS\fP, the data are assumed to be a null-terminated
+string; else the stored size informs the library about the data byte count to
+copy. In any case, the size must not be changed after
+\fICURLOPT_COPYPOSTFIELDS\fP, unless another \fICURLOPT_POSTFIELDS\fP or
+\fICURLOPT_COPYPOSTFIELDS\fP option is issued.
+
 .IP CURLOPT_HTTPPOST
 Tells libcurl you want a multipart/formdata HTTP POST to be made and you
 instruct what data to pass on to the server.  Pass a pointer to a linked list
Index: include/curl/curl.h
===================================================================
RCS file: /cvsroot/curl/curl/include/curl/curl.h,v
retrieving revision 1.330
diff -u -r1.330 curl.h
--- include/curl/curl.h	6 Oct 2007 17:20:06 -0000	1.330
+++ include/curl/curl.h	12 Oct 2007 15:17:55 -0000
@@ -659,7 +659,7 @@
    */
   CINIT(INFILESIZE, LONG, 14),
 
-  /* POST input fields. */
+  /* POST static input fields. */
   CINIT(POSTFIELDS, OBJECTPOINT, 15),
 
   /* Set the referer page (needed by some CGIs) */
@@ -1156,6 +1156,9 @@
   CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163),
   CINIT(OPENSOCKETDATA, OBJECTPOINT, 164),
 
+  /* POST volatile input fields. */
+  CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
Index: lib/http.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/http.c,v
retrieving revision 1.339
diff -u -r1.339 http.c
--- lib/http.c	12 Oct 2007 13:36:38 -0000	1.339
+++ lib/http.c	12 Oct 2007 15:22:41 -0000
@@ -2552,8 +2552,7 @@
         /* figure out the size of the postfields */
         postsize = (data->set.postfieldsize != -1)?
           data->set.postfieldsize:
-          (data->set.str[STRING_POSTFIELDS]?
-           (curl_off_t)strlen(data->set.str[STRING_POSTFIELDS]):0);
+          (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0);
 
       if(!conn->bits.upload_chunky) {
         /* We only set Content-Length and allow a custom Content-Length if
@@ -2578,7 +2577,7 @@
           return result;
       }
 
-      if(data->set.str[STRING_POSTFIELDS]) {
+      if(data->set.postfields) {
 
         /* for really small posts we don't use Expect: headers at all, and for
            the somewhat bigger ones we allow the app to disable it */
@@ -2606,7 +2605,7 @@
           if(!conn->bits.upload_chunky) {
             /* We're not sending it 'chunked', append it to the request
                already now to reduce the number if send() calls */
-            result = add_buffer(req_buffer, data->set.str[STRING_POSTFIELDS],
+            result = add_buffer(req_buffer, data->set.postfields,
                                 (size_t)postsize);
             included_body = postsize;
           }
@@ -2614,7 +2613,7 @@
             /* Append the POST data chunky-style */
             result = add_bufferf(req_buffer, "%x\r\n", (int)postsize);
             if(CURLE_OK == result)
-              result = add_buffer(req_buffer, data->set.str[STRING_POSTFIELDS],
+              result = add_buffer(req_buffer, data->set.postfields,
                                   (size_t)postsize);
             if(CURLE_OK == result)
               result = add_buffer(req_buffer,
@@ -2628,7 +2627,7 @@
         else {
           /* A huge POST coming up, do data separate from the request */
           http->postsize = postsize;
-          http->postdata = data->set.str[STRING_POSTFIELDS];
+          http->postdata = data->set.postfields;
 
           http->sending = HTTPSEND_BODY;
 
Index: lib/transfer.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/transfer.c,v
retrieving revision 1.369
diff -u -r1.369 transfer.c
--- lib/transfer.c	2 Oct 2007 10:21:36 -0000	1.369
+++ lib/transfer.c	12 Oct 2007 14:27:37 -0000
@@ -233,7 +233,7 @@
   /* We have sent away data. If not using CURLOPT_POSTFIELDS or
      CURLOPT_HTTPPOST, call app to rewind
   */
-  if(data->set.str[STRING_POSTFIELDS] ||
+  if(data->set.postfields ||
      (data->set.httpreq == HTTPREQ_POST_FORM))
     ; /* do nothing */
   else {
Index: lib/url.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/url.c,v
retrieving revision 1.652
diff -u -r1.652 url.c
--- lib/url.c	12 Oct 2007 13:36:38 -0000	1.652
+++ lib/url.c	12 Oct 2007 16:41:07 -0000
@@ -773,6 +773,7 @@
                      va_list param)
 {
   char *argptr;
+  curl_off_t bigsize;
   CURLcode result = CURLE_OK;
 
   switch(option) {
@@ -1031,12 +1032,52 @@
       data->set.httpreq = HTTPREQ_GET;
     break;
 
-  case CURLOPT_POSTFIELDS:
+  case CURLOPT_COPYPOSTFIELDS:
     /*
      * A string with POST data. Makes curl HTTP POST. Even if it is NULL.
+     * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to
+     *  CURLOPT_COPYPOSTFIELDS and not altered later.
      */
-    result = Curl_setstropt(&data->set.str[STRING_POSTFIELDS],
-                            va_arg(param, char *));
+    argptr = va_arg(param, char *);
+
+    if (!argptr || data->set.postfieldsize == -1)
+      result = Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);
+    else {
+      /*
+       *  Check that request length does not overflow the size_t type.
+       */
+
+      if ((curl_off_t) ((size_t) data->set.postfieldsize) !=
+          data->set.postfieldsize ||
+          data->set.postfieldsize < (curl_off_t) 0 ||
+          (size_t) data->set.postfieldsize < (size_t) 0)
+        result = CURLE_OUT_OF_MEMORY;
+      else {
+        char * p;
+
+        (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+        p = malloc(data->set.postfieldsize);
+
+        if (!p)
+          result = CURLE_OUT_OF_MEMORY;
+        else {
+          memcpy(p, argptr, data->set.postfieldsize);
+          data->set.str[STRING_COPYPOSTFIELDS] = p;
+	}
+      }
+    }
+
+    data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
+    data->set.httpreq = HTTPREQ_POST;
+    break;
+
+  case CURLOPT_POSTFIELDS:
+    /*
+     * Like above, but use static data instead of copying it.
+     */
+    data->set.postfields = va_arg(param, void *);
+    /* Release old copied data. */
+    (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
     data->set.httpreq = HTTPREQ_POST;
     break;
 
@@ -1045,7 +1086,16 @@
      * The size of the POSTFIELD data to prevent libcurl to do strlen() to
      * figure it out. Enables binary posts.
      */
-    data->set.postfieldsize = va_arg(param, long);
+    bigsize = va_arg(param, long);
+
+    if (data->set.postfieldsize < bigsize &&
+        data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
+      /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
+      (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+      data->set.postfields = NULL;
+      }
+
+    data->set.postfieldsize = bigsize;
     break;
 
   case CURLOPT_POSTFIELDSIZE_LARGE:
@@ -1053,7 +1103,16 @@
      * The size of the POSTFIELD data to prevent libcurl to do strlen() to
      * figure it out. Enables binary posts.
      */
-    data->set.postfieldsize = va_arg(param, curl_off_t);
+    bigsize = va_arg(param, curl_off_t);
+
+    if (data->set.postfieldsize < bigsize &&
+        data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
+      /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
+      (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
+      data->set.postfields = NULL;
+      }
+
+    data->set.postfieldsize = bigsize;
     break;
 
   case CURLOPT_HTTPPOST:
Index: lib/urldata.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/urldata.h,v
retrieving revision 1.351
diff -u -r1.351 urldata.h
--- lib/urldata.h	12 Oct 2007 13:36:38 -0000	1.351
+++ lib/urldata.h	12 Oct 2007 15:20:42 -0000
@@ -1286,7 +1286,7 @@
   STRING_KRB_LEVEL,       /* krb security level */
   STRING_NETRC_FILE,      /* if not NULL, use this instead of trying to find
                              $HOME/.netrc */
-  STRING_POSTFIELDS,      /* if POST, set the fields' values here */
+  STRING_COPYPOSTFIELDS,  /* if POST, set the fields' values here */
   STRING_PROXY,           /* proxy to use */
   STRING_PROXYUSERPWD,    /* Proxy <user:password>, if used */
   STRING_SET_RANGE,       /* range, if used */
@@ -1326,6 +1326,7 @@
   bool post301;      /* Obey RFC 2616/10.3.2 and keep POSTs as POSTs after a 301 */
   bool free_referer; /* set TRUE if 'referer' points to a string we
                         allocated */
+  void *postfields;  /* if POST, set the fields' values here */
   curl_off_t postfieldsize; /* if POST, this might have a size to use instead
                                of strlen(), and then the data *may* be binary
                                (contain zero bytes) */
Index: packages/OS400/README.OS400
===================================================================
RCS file: /cvsroot/curl/curl/packages/OS400/README.OS400,v
retrieving revision 1.3
diff -u -r1.3 README.OS400
--- packages/OS400/README.OS400	3 Oct 2007 15:09:21 -0000	1.3
+++ packages/OS400/README.OS400	12 Oct 2007 15:28:48 -0000
@@ -81,7 +81,7 @@
         CURLOPT_KEYPASSWD
         CURLOPT_KRBLEVEL
         CURLOPT_NETRC_FILE
-        CURLOPT_POSTFIELDS
+        CURLOPT_COPYPOSTFIELDS
         CURLOPT_PROXY
         CURLOPT_PROXYUSERPWD
         CURLOPT_RANDOM_FILE
@@ -102,6 +102,9 @@
   Else it is the same as for curl_easy_setopt().
   Note that CURLOPT_ERRORBUFFER is not in the list above, since it gives the
 address of an (empty) character buffer, not the address of a string.
+CURLOPT_POSTFIELDS stores the address of static binary data (of type void *) and
+thus is not converted. CURLOPT_COPYPOSTFIELDS may only be used here with a
+null-terminated string and without prior CURLOPT_POSTFIELDSIZE setting.
 
 _ curl_formadd_ccsid()
   In the variable argument list, string pointers should be followed by a (long)
Index: packages/OS400/ccsidcurl.c
===================================================================
RCS file: /cvsroot/curl/curl/packages/OS400/ccsidcurl.c,v
retrieving revision 1.3
diff -u -r1.3 ccsidcurl.c
--- packages/OS400/ccsidcurl.c	3 Oct 2007 15:09:21 -0000	1.3
+++ packages/OS400/ccsidcurl.c	12 Oct 2007 15:19:34 -0000
@@ -1042,7 +1042,7 @@
   case CURLOPT_KEYPASSWD:
   case CURLOPT_KRBLEVEL:
   case CURLOPT_NETRC_FILE:
-  case CURLOPT_POSTFIELDS:
+  case CURLOPT_COPYPOSTFIELDS:
   case CURLOPT_PROXY:
   case CURLOPT_PROXYUSERPWD:
   case CURLOPT_RANDOM_FILE:
