Fix dynamic CURLOPT_POSTFIELDS bug: back to static.
CURLOPT_COPYPOSTFIELDS option added for dynamic. Fix some OS400 features.
This commit is contained in:
Родитель
001a2d9b67
Коммит
a005243908
4
CHANGES
4
CHANGES
|
@ -6,6 +6,10 @@
|
|||
|
||||
Changelog
|
||||
|
||||
Patrick M (15 October 2007)
|
||||
- Fixed the dynamic CURLOPT_POSTFIELDS problem: this option is now static again
|
||||
and option CURLOPT_COPYPOSTFIELDS has been added to support dynamic mode.
|
||||
|
||||
Patrick M (12 October 2007)
|
||||
- Added per-protocol callback static tables, replacing callback ptr storage
|
||||
in the connectdata structure by a single handler table ptr.
|
||||
|
|
|
@ -386,8 +386,7 @@ POST/PUT and a 401 or 407 is received immediately afterwards.
|
|||
.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 @@ also make the library use the a "Content-Type:
|
|||
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 @@ If you issue a POST request and then want to make a HEAD or GET using the same
|
|||
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 @@ Pass a curl_off_t as parameter. Use this to set the size of the
|
|||
\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
|
||||
|
|
|
@ -659,7 +659,7 @@ typedef enum {
|
|||
*/
|
||||
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 @@ typedef enum {
|
|||
CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163),
|
||||
CINIT(OPENSOCKETDATA, OBJECTPOINT, 164),
|
||||
|
||||
/* POST volatile input fields. */
|
||||
CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165),
|
||||
|
||||
CURLOPT_LASTENTRY /* the last unused */
|
||||
} CURLoption;
|
||||
|
||||
|
|
|
@ -361,6 +361,9 @@
|
|||
/* The size of a `long double', as computed by sizeof. */
|
||||
#define SIZEOF_LONG_DOUBLE 8
|
||||
|
||||
/* Define if 64 bit integers are supported. */
|
||||
#define HAVE_LONGLONG
|
||||
|
||||
/* The size of a `long long', as computed by sizeof. */
|
||||
#define SIZEOF_LONG_LONG 8
|
||||
|
||||
|
|
11
lib/http.c
11
lib/http.c
|
@ -2554,8 +2554,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||
/* 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
|
||||
|
@ -2580,7 +2579,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||
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 */
|
||||
|
@ -2608,7 +2607,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||
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;
|
||||
}
|
||||
|
@ -2616,7 +2615,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||
/* 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,
|
||||
|
@ -2630,7 +2629,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
|||
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;
|
||||
|
||||
|
|
|
@ -233,7 +233,7 @@ CURLcode Curl_readrewind(struct connectdata *conn)
|
|||
/* 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 {
|
||||
|
|
69
lib/url.c
69
lib/url.c
|
@ -771,6 +771,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||
va_list param)
|
||||
{
|
||||
char *argptr;
|
||||
curl_off_t bigsize;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
switch(option) {
|
||||
|
@ -1029,12 +1030,52 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||
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;
|
||||
|
||||
|
@ -1043,7 +1084,16 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||
* 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:
|
||||
|
@ -1051,7 +1101,16 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||
* 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:
|
||||
|
|
|
@ -1286,7 +1286,7 @@ enum dupstring {
|
|||
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 @@ struct UserDefined {
|
|||
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) */
|
||||
|
|
|
@ -81,7 +81,7 @@ options:
|
|||
CURLOPT_KEYPASSWD
|
||||
CURLOPT_KRBLEVEL
|
||||
CURLOPT_NETRC_FILE
|
||||
CURLOPT_POSTFIELDS
|
||||
CURLOPT_COPYPOSTFIELDS
|
||||
CURLOPT_PROXY
|
||||
CURLOPT_PROXYUSERPWD
|
||||
CURLOPT_RANDOM_FILE
|
||||
|
@ -102,6 +102,10 @@ options:
|
|||
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. If CURLOPT_COPYPOSTFIELDS is issued after
|
||||
CURLOPT_POSTFIELDSIZE != -1, the data size is adjusted according to the
|
||||
CCSID conversion result length.
|
||||
|
||||
_ curl_formadd_ccsid()
|
||||
In the variable argument list, string pointers should be followed by a (long)
|
||||
|
|
|
@ -40,8 +40,13 @@
|
|||
|
||||
#include "os400sys.h"
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
#define SIZE_MAX ((size_t) ~0) /* Is unsigned on OS/400. */
|
||||
#endif
|
||||
|
||||
|
||||
#define ASCII_CCSID 819 /* Use ISO-8859-1 as ASCII. */
|
||||
#define NOCONV_CCSID 65535 /* No conversion. */
|
||||
#define ICONV_ID_SIZE 32 /* Size of iconv_open() code identifier. */
|
||||
#define ICONV_OPEN_ERROR(t) ((t).return_value == -1)
|
||||
|
||||
|
@ -62,7 +67,7 @@ makeOS400IconvCode(char buf[ICONV_ID_SIZE], unsigned int ccsid)
|
|||
|
||||
ccsid &= 0xFFFF;
|
||||
|
||||
if (ccsid == 65535)
|
||||
if (ccsid == NOCONV_CCSID)
|
||||
ccsid = ASCII_CCSID;
|
||||
|
||||
memset(buf, 0, ICONV_ID_SIZE);
|
||||
|
@ -1004,7 +1009,10 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
|||
va_list arg;
|
||||
struct SessionHandle * data;
|
||||
char * s;
|
||||
char * cp;
|
||||
unsigned int ccsid;
|
||||
size_t len;
|
||||
curl_off_t pfsize;
|
||||
static char testwarn = 1;
|
||||
|
||||
/* Warns if this procedure has not been updated when the dupstring enum
|
||||
|
@ -1042,7 +1050,6 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
|||
case CURLOPT_KEYPASSWD:
|
||||
case CURLOPT_KRBLEVEL:
|
||||
case CURLOPT_NETRC_FILE:
|
||||
case CURLOPT_POSTFIELDS:
|
||||
case CURLOPT_PROXY:
|
||||
case CURLOPT_PROXYUSERPWD:
|
||||
case CURLOPT_RANDOM_FILE:
|
||||
|
@ -1079,6 +1086,66 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...)
|
|||
|
||||
break;
|
||||
|
||||
case CURLOPT_COPYPOSTFIELDS:
|
||||
/* Special case: byte count may have been given by CURLOPT_POSTFIELDSIZE
|
||||
prior to this call. In this case, convert the given byte count and
|
||||
replace the length according to the conversion result. */
|
||||
s = va_arg(arg, char *);
|
||||
ccsid = va_arg(arg, unsigned int);
|
||||
|
||||
pfsize = data->set.postfieldsize;
|
||||
|
||||
if (!s || !pfsize || ccsid == NOCONV_CCSID || ccsid == ASCII_CCSID) {
|
||||
result = curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pfsize == -1) {
|
||||
/* Data is null-terminated. */
|
||||
s = dynconvert(ASCII_CCSID, s, -1, ccsid);
|
||||
|
||||
if (!s) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Data length specified. */
|
||||
|
||||
if (pfsize < 0 || pfsize > SIZE_MAX) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
len = pfsize;
|
||||
pfsize = len * MAX_CONV_EXPANSION;
|
||||
|
||||
if (pfsize > SIZE_MAX)
|
||||
pfsize = SIZE_MAX;
|
||||
|
||||
cp = malloc(pfsize);
|
||||
|
||||
if (!cp) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
pfsize = convert(cp, pfsize, ASCII_CCSID, s, len, ccsid);
|
||||
|
||||
if (pfsize < 0) {
|
||||
free(cp);
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
data->set.postfieldsize = pfsize; /* Replace data size. */
|
||||
s = cp;
|
||||
}
|
||||
|
||||
result = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, s);
|
||||
data->set.str[STRING_COPYPOSTFIELDS] = s; /* Give to library. */
|
||||
break;
|
||||
|
||||
case CURLOPT_ERRORBUFFER: /* This is an output buffer. */
|
||||
default:
|
||||
result = Curl_setopt(data, tag, arg);
|
||||
|
|
Загрузка…
Ссылка в новой задаче