application, so you must make sure it remains until curl no longer needs it.
If the data isn't NUL-terminated, or if you'd like it to contain zero bytes,
you must set its length with \fBCURLFORM_CONTENTSLENGTH\fP.
+.IP CURLFORM_CONTENTLEN
+followed by a curl_off_t value giving the length of the contents. Note that
+for \fICURLFORM_STREAM\fP contents, this option is mandatory.
+
+If you pass a 0 (zero) for this option, libcurl will instead do a strlen() on
+the contents to figure out the size. If you really want to send a zero byte
+content then you must make sure strlen() on the data pointer returns zero.
+
+(Option added in 7.46.0)
.IP CURLFORM_CONTENTSLENGTH
+(This option is deprecated. Use \fICURLFORM_CONTENTLEN\fP instead!)
+
followed by a long giving the length of the contents. Note that for
\fICURLFORM_STREAM\fP contents, this option is mandatory.
CURLFORM_BUFFERLENGTH 7.9.8
CURLFORM_BUFFERPTR 7.9.8
CURLFORM_CONTENTHEADER 7.9.3
+CURLFORM_CONTENTLEN 7.46.0
CURLFORM_CONTENTSLENGTH 7.9
CURLFORM_CONTENTTYPE 7.9
CURLFORM_COPYCONTENTS 7.9
CURL_GLOBAL_NOTHING 7.8
CURL_GLOBAL_SSL 7.8
CURL_GLOBAL_WIN32 7.8.1
+CURL_HTTPPOST_LARGE 7.46.0
CURL_HTTP_VERSION_1_0 7.9.1
CURL_HTTP_VERSION_1_1 7.9.1
CURL_HTTP_VERSION_2 7.43.0
char *name; /* pointer to allocated name */
long namelength; /* length of name length */
char *contents; /* pointer to allocated data contents */
- long contentslength; /* length of contents field */
+ long contentslength; /* length of contents field, see also
+ CURL_HTTPPOST_LARGE */
char *buffer; /* pointer to allocated buffer contents */
long bufferlength; /* length of buffer field */
char *contenttype; /* Content-Type */
/* upload file contents by using the regular read callback to get the data and
pass the given pointer as custom pointer */
#define CURL_HTTPPOST_CALLBACK (1<<6)
+/* use size in 'contentlen', added in 7.46.0 */
+#define CURL_HTTPPOST_LARGE (1<<7)
char *showfilename; /* The file name to show. If not set, the
actual file name will be used (if this
is a file part) */
void *userp; /* custom pointer used for
HTTPPOST_CALLBACK posts */
+ curl_off_t contentlen; /* alternative length of contents
+ field. Used if CURL_HTTPPOST_LARGE is
+ set. Added in 7.46.0 */
};
/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered
CFINIT(OBSOLETE2),
CFINIT(STREAM),
+ CFINIT(CONTENTLEN), /* added in 7.46.0, provide a curl_off_t length */
CURLFORM_LASTENTRY /* the last unused */
} CURLformoption;
***************************************************************************/
static struct curl_httppost *
AddHttpPost(char *name, size_t namelength,
- char *value, size_t contentslength,
+ char *value, curl_off_t contentslength,
char *buffer, size_t bufferlength,
char *contenttype,
long flags,
post->name = name;
post->namelength = (long)(name?(namelength?namelength:strlen(name)):0);
post->contents = value;
- post->contentslength = (long)contentslength;
+ post->contentlen = contentslength;
post->buffer = buffer;
post->bufferlength = (long)bufferlength;
post->contenttype = contenttype;
post->contentheader = contentHeader;
post->showfilename = showfilename;
post->userp = userp,
- post->flags = flags;
+ post->flags = flags | CURL_HTTPPOST_LARGE;
}
else
return NULL;
}
break;
case CURLFORM_CONTENTSLENGTH:
- if(current_form->contentslength)
- return_value = CURL_FORMADD_OPTION_TWICE;
- else
- current_form->contentslength =
- array_state?(size_t)array_value:(size_t)va_arg(params, long);
+ current_form->contentslength =
+ array_state?(size_t)array_value:(size_t)va_arg(params, long);
+ break;
+
+ case CURLFORM_CONTENTLEN:
+ current_form->flags |= CURL_HTTPPOST_LARGE;
+ current_form->contentslength =
+ array_state?(curl_off_t)array_value:va_arg(params, curl_off_t);
break;
/* Get contents from a given file name */
HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER |
HTTPPOST_CALLBACK)) && form->value) {
/* copy value (without strdup; possibly contains null characters) */
- form->value = Curl_memdup(form->value, form->contentslength?
- form->contentslength:
- strlen(form->value)+1);
+ size_t clen = (size_t) form->contentslength;
+ if(!clen)
+ clen = strlen(form->value)+1;
+
+ form->value = Curl_memdup(form->value, clen);
+
if(!form->value) {
return_value = CURL_FORMADD_MEMORY;
break;
static CURLcode AddFormData(struct FormData **formp,
enum formtype type,
const void *line,
- size_t length,
+ curl_off_t length,
curl_off_t *size)
{
struct FormData *newform = malloc(sizeof(struct FormData));
result = AddFormData(&form, FORM_CONTENT, post->buffer,
post->bufferlength, &size);
else if(post->flags & HTTPPOST_CALLBACK)
- /* the contents should be read with the callback and the size
- is set with the contentslength */
+ /* the contents should be read with the callback and the size is set
+ with the contentslength */
result = AddFormData(&form, FORM_CALLBACK, post->userp,
- post->contentslength, &size);
+ post->flags&CURL_HTTPPOST_LARGE?
+ post->contentlen:post->contentslength, &size);
else
/* include the contents we got */
result = AddFormData(&form, FORM_CONTENT, post->contents,
- post->contentslength, &size);
-
+ post->flags&CURL_HTTPPOST_LARGE?
+ post->contentlen:post->contentslength, &size);
file = file->more;
} while(file && !result); /* for each specified file for this field */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2015, 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
size_t namelength;
char *value;
bool value_alloc;
- size_t contentslength;
+ curl_off_t contentslength;
char *contenttype;
bool contenttype_alloc;
long flags;
\r
hello
</data>
+<datacheck>
+HTTP/1.1 200 OK\r
+Date: Thu, 09 Nov 2010 14:49:00 GMT\r
+Server: test-server/fake swsclose\r
+Connection: close\r
+Content-Type: text/html\r
+\r
+hello
+HTTP/1.1 200 OK\r
+Date: Thu, 09 Nov 2010 14:49:00 GMT\r
+Server: test-server/fake swsclose\r
+Connection: close\r
+Content-Type: text/html\r
+\r
+hello
+</datacheck>
</reply>
# Client-side
Content-Disposition: form-data; name="somename"; filename="somefile.txt"\r
Content-Type: text/plain\r
\r
+blah blah\r
+--------------------------------\r
+POST /554 HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+Accept: */*\r
+Content-Length: 732\r
+Expect: 100-continue\r
+Content-Type: multipart/form-data; boundary=----------------------------\r
+\r
+------------------------------\r
+Content-Disposition: form-data; name="sendfile alternative"; filename="file name 2"\r
+\r
+this is what we post to the silly web server
+\r
+------------------------------\r
+Content-Disposition: form-data; name="callbackdata"\r
+\r
+this is what we post to the silly web server
+\r
+------------------------------\r
+Content-Disposition: form-data; name="filename"\r
+\r
+postit2.c\r
+------------------------------\r
+Content-Disposition: form-data; name="submit"\r
+\r
+send\r
+------------------------------\r
+Content-Disposition: form-data; name="somename"; filename="somefile.txt"\r
+Content-Type: text/plain\r
+\r
blah blah\r
--------------------------------\r
</protocol>
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2015, 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
#endif
}
-int test(char *URL)
+static int once(char *URL, bool oldstyle)
{
CURL *curl;
CURLcode res=CURLE_OK;
struct WriteThis pooh;
struct WriteThis pooh2;
- if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
- fprintf(stderr, "curl_global_init() failed\n");
- return TEST_ERR_MAJOR_BAD;
- }
-
pooh.readptr = data;
pooh.sizeleft = strlen(data);
/* Fill in the file upload field */
- formrc = curl_formadd(&formpost,
- &lastptr,
- CURLFORM_COPYNAME, "sendfile",
- CURLFORM_STREAM, &pooh,
- CURLFORM_CONTENTSLENGTH, (long)pooh.sizeleft,
- CURLFORM_FILENAME, "postit2.c",
- CURLFORM_END);
+ if(oldstyle) {
+ formrc = curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "sendfile",
+ CURLFORM_STREAM, &pooh,
+ CURLFORM_CONTENTSLENGTH, (long)pooh.sizeleft,
+ CURLFORM_FILENAME, "postit2.c",
+ CURLFORM_END);
+ }
+ else {
+ /* new style */
+ formrc = curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "sendfile alternative",
+ CURLFORM_STREAM, &pooh,
+ CURLFORM_CONTENTLEN, (curl_off_t)pooh.sizeleft,
+ CURLFORM_FILENAME, "file name 2",
+ CURLFORM_END);
+ }
if(formrc)
printf("curl_formadd(1) = %d\n", (int)formrc);
/* always cleanup */
curl_easy_cleanup(curl);
- curl_global_cleanup();
/* now cleanup the formpost chain */
curl_formfree(formpost);
return res;
}
+
+int test(char *URL)
+{
+ int res;
+
+ if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+ fprintf(stderr, "curl_global_init() failed\n");
+ return TEST_ERR_MAJOR_BAD;
+ }
+
+ res = once(URL, TRUE); /* old */
+ if(!res)
+ res = once(URL, FALSE); /* new */
+
+ curl_global_cleanup();
+
+ return res;
+}