aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES12
-rw-r--r--RELEASE-NOTES1
-rw-r--r--docs/libcurl/curl_easy_getinfo.34
-rw-r--r--docs/libcurl/curl_easy_setopt.322
-rw-r--r--include/curl/curlver.h8
-rw-r--r--lib/connect.c20
-rw-r--r--lib/easy.c7
-rw-r--r--lib/ftp.c40
-rw-r--r--lib/getinfo.c2
-rw-r--r--lib/gtls.c10
-rw-r--r--lib/gtls.h4
-rw-r--r--lib/http.c46
-rw-r--r--lib/nss.c9
-rw-r--r--lib/nssg.h4
-rw-r--r--lib/ssh.c10
-rw-r--r--lib/sslgen.c19
-rw-r--r--lib/ssluse.c56
-rw-r--r--lib/transfer.c4
-rw-r--r--lib/url.c220
-rw-r--r--lib/url.h2
-rw-r--r--lib/urldata.h82
21 files changed, 364 insertions, 218 deletions
diff --git a/CHANGES b/CHANGES
index a245e7d09..ef30dc1e6 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,18 @@
Changelog
Daniel S (1 August 2007)
+- Patrick Monnerat and I modified libcurl so that now it *copies* all strings
+ passed to it with curl_easy_setopt()! Previously it has always just refered
+ to the data, forcing the user to keep the data around until libcurl is done
+ with it. That is now history and libcurl will instead clone the given
+ strings and keep private copies. This is also part of Patrick Monnerat's
+ OS/400 port.
+
+ Due to this being a somewhat interesting change API wise, I've decided to
+ bump the version of the upcoming release to 7.17.0. Older applications will
+ of course not notice this change nor do they have to care, but new
+ applications can be written to take advantage of this.
+
- Greg Morse reported a problem with POSTing using ANYAUTH to a server
requiring NTLM, and he provided test code and a test server and we worked
out a bug fix. We failed to count sent body data at times, which then caused
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 5e64b764c..0377adb93 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -12,6 +12,7 @@ Curl and libcurl 7.16.5
This release includes the following changes:
o support for OS/400 Secure Sockets Layer library
+ o curl_easy_setopt() now allocates strings passed to it
This release includes the following bugfixes:
diff --git a/docs/libcurl/curl_easy_getinfo.3 b/docs/libcurl/curl_easy_getinfo.3
index fe13f07c9..95455e3a1 100644
--- a/docs/libcurl/curl_easy_getinfo.3
+++ b/docs/libcurl/curl_easy_getinfo.3
@@ -133,7 +133,9 @@ protocol used doesn't support this.
.IP CURLINFO_PRIVATE
Pass a pointer to a 'char *' to receive the pointer to the private data
associated with the curl handle (set with the CURLOPT_PRIVATE option to
-\fIcurl_easy_setopt(3)\fP). (Added in 7.10.3)
+\fIcurl_easy_setopt(3)\fP). Please note that for internal reasons, the
+value is returned as a 'char *', although effectively being a 'void *'.
+(Added in 7.10.3)
.IP CURLINFO_HTTPAUTH_AVAIL
Pass a pointer to a long to receive a bitmask indicating the authentication
method(s) available. The meaning of the bits is explained in the
diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
index 63b53f7c4..016bb9181 100644
--- a/docs/libcurl/curl_easy_setopt.3
+++ b/docs/libcurl/curl_easy_setopt.3
@@ -21,7 +21,7 @@
.\" * $Id$
.\" **************************************************************************
.\"
-.TH curl_easy_setopt 3 "22 Feb 2007" "libcurl 7.16.2" "libcurl Manual"
+.TH curl_easy_setopt 3 "1 Aug 2007" "libcurl 7.17.0" "libcurl Manual"
.SH NAME
curl_easy_setopt \- set options for a curl easy handle
.SH SYNOPSIS
@@ -44,11 +44,13 @@ between transfers, so if you want subsequent transfers with different options,
you must change them between the transfers. You can optionally reset all
options back to internal default with \fIcurl_easy_reset(3)\fP.
-Strings passed to libcurl as 'char *' arguments, will not be copied by the
-library. Instead you should keep them available until libcurl no longer needs
-them. Failing to do so will cause very odd behavior or even crashes. libcurl
-will need them until you call \fIcurl_easy_cleanup(3)\fP or you set the same
-option again to use a different pointer.
+Strings passed to libcurl as 'char *' arguments, are copied by the library;
+thus the string storage associated to the pointer argument may be overwritten
+after curl_easy_setopt() returns. Exceptions to this rule are described in
+the option details below.
+
+NOTE: before 7.17.0 strings were not copied. Instead the user was forced keep
+them available until libcurl no longer needed them.
The \fIhandle\fP is the return code from a \fIcurl_easy_init(3)\fP or
\fIcurl_easy_duphandle(3)\fP call.
@@ -330,6 +332,12 @@ system.
Pass a char * to a buffer that the libcurl may store human readable error
messages in. This may be more helpful than just the return code from
\fIcurl_easy_perform\fP. The buffer must be at least CURL_ERROR_SIZE big.
+Although this argument is a 'char *', it does not describe an input string.
+Therefore the (probably undefined) contents of the buffer is NOT copied
+by the library. You should keep the associated storage available until
+libcurl no longer needs it. Failing to do so will cause very odd behavior
+or even crashes. libcurl will need it until you call \fIcurl_easy_cleanup(3)\fP
+or you set the same option again to use a different pointer.
Use \fICURLOPT_VERBOSE\fP and \fICURLOPT_DEBUGFUNCTION\fP to better
debug/trace why errors happen.
@@ -1397,7 +1405,7 @@ If the file is password-protected, set the password with \fICURLOPT_SSLKEYPASSWD
(Added in 7.16.1)
.SH OTHER OPTIONS
.IP CURLOPT_PRIVATE
-Pass a char * as parameter, pointing to data that should be associated with
+Pass a void * as parameter, pointing to data that should be associated with
this curl handle. The pointer can subsequently be retrieved using
\fIcurl_easy_getinfo(3)\fP with the CURLINFO_PRIVATE option. libcurl itself
does nothing with this data. (Added in 7.10.3)
diff --git a/include/curl/curlver.h b/include/curl/curlver.h
index 11b34dcaf..4657398bc 100644
--- a/include/curl/curlver.h
+++ b/include/curl/curlver.h
@@ -28,13 +28,13 @@
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.16.5-CVS"
+#define LIBCURL_VERSION "7.17.0-CVS"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 16
-#define LIBCURL_VERSION_PATCH 5
+#define LIBCURL_VERSION_MINOR 17
+#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
@@ -51,7 +51,7 @@
and it is always a greater number in a more recent release. It makes
comparisons with greater than and less than work.
*/
-#define LIBCURL_VERSION_NUM 0x071005
+#define LIBCURL_VERSION_NUM 0x071100
/*
* This is the date and time when the full source package was created. The
diff --git a/lib/connect.c b/lib/connect.c
index d608e1e2e..634595766 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -228,11 +228,12 @@ static CURLcode bindlocal(struct connectdata *conn,
"random" */
/* how many port numbers to try to bind to, increasing one at a time */
int portnum = data->set.localportrange;
+ const char *dev = data->set.str[STRING_DEVICE];
/*************************************************************
* Select device to bind socket to
*************************************************************/
- if (data->set.device && (strlen(data->set.device)<255) ) {
+ if (dev && (strlen(dev)<255) ) {
struct Curl_dns_entry *h=NULL;
char myhost[256] = "";
in_addr_t in;
@@ -241,10 +242,10 @@ static CURLcode bindlocal(struct connectdata *conn,
int in6 = -1;
/* First check if the given name is an IP address */
- in=inet_addr(data->set.device);
+ in=inet_addr(dev);
if((in == CURL_INADDR_NONE) &&
- Curl_if2ip(data->set.device, myhost, sizeof(myhost))) {
+ Curl_if2ip(dev, myhost, sizeof(myhost))) {
/*
* We now have the numerical IPv4-style x.y.z.w in the 'myhost' buffer
*/
@@ -263,7 +264,7 @@ static CURLcode bindlocal(struct connectdata *conn,
* This was not an interface, resolve the name as a host name
* or IP number
*/
- rc = Curl_resolv(conn, data->set.device, 0, &h);
+ rc = Curl_resolv(conn, dev, 0, &h);
if(rc == CURLRESOLV_PENDING)
(void)Curl_wait_for_resolv(conn, &h);
@@ -275,7 +276,7 @@ static CURLcode bindlocal(struct connectdata *conn,
myhost, sizeof myhost);
else
/* we know data->set.device is shorter than the myhost array */
- strcpy(myhost, data->set.device);
+ strcpy(myhost, dev);
Curl_resolv_unlock(data, h);
}
}
@@ -287,7 +288,7 @@ static CURLcode bindlocal(struct connectdata *conn,
hostent_buf,
sizeof(hostent_buf));
*/
- failf(data, "Couldn't bind to '%s'", data->set.device);
+ failf(data, "Couldn't bind to '%s'", dev);
return CURLE_INTERFACE_FAILED;
}
@@ -307,11 +308,10 @@ static CURLcode bindlocal(struct connectdata *conn,
* hostname or ip address.
*/
if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
- data->set.device, strlen(data->set.device)+1) != 0) {
+ dev, strlen(dev)+1) != 0) {
/* printf("Failed to BINDTODEVICE, socket: %d device: %s error: %s\n",
- sockfd, data->set.device, Curl_strerror(SOCKERRNO)); */
- infof(data, "SO_BINDTODEVICE %s failed\n",
- data->set.device);
+ sockfd, dev, Curl_strerror(SOCKERRNO)); */
+ infof(data, "SO_BINDTODEVICE %s failed\n", dev);
/* This is typically "errno 1, error: Operation not permitted" if
you're not running as root or another suitable privileged user */
}
diff --git a/lib/easy.c b/lib/easy.c
index b1080a22d..54915fb88 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -579,7 +579,8 @@ CURL *curl_easy_duphandle(CURL *incurl)
outcurl->state.headersize=HEADERSIZE;
/* copy all userdefined values */
- outcurl->set = data->set;
+ if (Curl_dupset(outcurl, data) != CURLE_OK)
+ break;
if(data->state.used_interface == Curl_if_multi)
outcurl->state.connc = data->state.connc;
@@ -658,6 +659,7 @@ CURL *curl_easy_duphandle(CURL *incurl)
free(outcurl->change.url);
if(outcurl->change.referer)
free(outcurl->change.referer);
+ Curl_freeset(outcurl);
free(outcurl); /* free the memory again */
outcurl = NULL;
}
@@ -681,6 +683,7 @@ void curl_easy_reset(CURL *curl)
data->reqdata.proto.generic=NULL;
/* zero out UserDefined data: */
+ Curl_freeset(data);
memset(&data->set, 0, sizeof(struct UserDefined));
/* zero out Progress data: */
@@ -732,7 +735,7 @@ void curl_easy_reset(CURL *curl)
data->set.ssl.verifyhost = 2;
#ifdef CURL_CA_BUNDLE
/* This is our prefered CA cert bundle since install time */
- data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE;
+ (void) curl_easy_setopt(curl, CURLOPT_CAINFO, (char *) CURL_CA_BUNDLE);
#endif
data->set.ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
diff --git a/lib/ftp.c b/lib/ftp.c
index 4df17decb..6958eb7f2 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -871,11 +871,12 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
/* Step 1, figure out what address that is requested */
- if(data->set.ftpport && (strlen(data->set.ftpport) > 1)) {
+ if(data->set.str[STRING_FTPPORT] &&
+ (strlen(data->set.str[STRING_FTPPORT]) > 1)) {
/* attempt to get the address of the given interface name */
- if(!Curl_if2ip(data->set.ftpport, hbuf, sizeof(hbuf)))
+ if(!Curl_if2ip(data->set.str[STRING_FTPPORT], hbuf, sizeof(hbuf)))
/* not an interface, use the given string as host name instead */
- host = data->set.ftpport;
+ host = data->set.str[STRING_FTPPORT];
else
host = hbuf; /* use the hbuf for host name */
} /* data->set.ftpport */
@@ -1080,27 +1081,28 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
unsigned short ip[4];
bool freeaddr = TRUE;
socklen_t sslen = sizeof(sa);
+ const char *ftpport = data->set.str[STRING_FTPPORT];
(void)fcmd; /* not used in the IPv4 code */
- if(data->set.ftpport) {
+ if(ftpport) {
in_addr_t in;
/* First check if the given name is an IP address */
- in=inet_addr(data->set.ftpport);
+ in=inet_addr(ftpport);
if(in != CURL_INADDR_NONE)
/* this is an IPv4 address */
- addr = Curl_ip2addr(in, data->set.ftpport, 0);
+ addr = Curl_ip2addr(in, ftpport, 0);
else {
- if(Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) {
+ if(Curl_if2ip(ftpport, myhost, sizeof(myhost))) {
/* The interface to IP conversion provided a dotted address */
in=inet_addr(myhost);
addr = Curl_ip2addr(in, myhost, 0);
}
- else if(strlen(data->set.ftpport)> 1) {
+ else if(strlen(ftpport)> 1) {
/* might be a host name! */
struct Curl_dns_entry *h=NULL;
- int rc = Curl_resolv(conn, data->set.ftpport, 0, &h);
+ int rc = Curl_resolv(conn, ftpport, 0, &h);
if(rc == CURLRESOLV_PENDING)
/* BLOCKING */
rc = Curl_wait_for_resolv(conn, &h);
@@ -1114,11 +1116,11 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
since it points to a DNS cache entry! */
} /* (h) */
else {
- infof(data, "Failed to resolve host name %s\n", data->set.ftpport);
+ infof(data, "Failed to resolve host name %s\n", ftpport);
}
} /* strlen */
} /* CURL_INADDR_NONE */
- } /* data->set.ftpport */
+ } /* ftpport */
if(!addr) {
/* pick a suitable default here */
@@ -1346,7 +1348,8 @@ static CURLcode ftp_state_post_listtype(struct connectdata *conn)
servers either... */
NBFTPSENDF(conn, "%s",
- data->set.customrequest?data->set.customrequest:
+ data->set.str[STRING_CUSTOMREQUEST]?
+ data->set.str[STRING_CUSTOMREQUEST]:
(data->set.ftp_list_only?"NLST":"LIST"));
state(conn, FTP_LIST);
@@ -1720,7 +1723,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
return CURLE_FTP_WEIRD_PASV_REPLY;
}
- if(data->set.proxy && *data->set.proxy) {
+ if(data->set.str[STRING_PROXY] && *data->set.str[STRING_PROXY]) {
/*
* This is a tunnel through a http proxy and we need to connect to the
* proxy again here.
@@ -2384,8 +2387,8 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
result = ftp_state_loggedin(conn);
}
else if(ftpcode == 332) {
- if(data->set.ftp_account) {
- NBFTPSENDF(conn, "ACCT %s", data->set.ftp_account);
+ if(data->set.str[STRING_FTP_ACCOUNT]) {
+ NBFTPSENDF(conn, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]);
state(conn, FTP_ACCT);
}
else {
@@ -2399,10 +2402,11 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
530 User ... access denied
(the server denies to log the specified user) */
- if (conn->data->set.ftp_alternative_to_user &&
+ if (conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
!conn->data->state.ftp_trying_alternative) {
/* Ok, USER failed. Let's try the supplied command. */
- NBFTPSENDF(conn, "%s", conn->data->set.ftp_alternative_to_user);
+ NBFTPSENDF(conn, "%s",
+ conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
conn->data->state.ftp_trying_alternative = TRUE;
state(conn, FTP_USER);
result = CURLE_OK;
@@ -2488,7 +2492,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
Curl_sec_request_prot(conn, "private");
/* We set private first as default, in case the line below fails to
set a valid level */
- Curl_sec_request_prot(conn, data->set.krb_level);
+ Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]);
if(Curl_sec_login(conn) != 0)
infof(data, "Logging in with password in cleartext!\n");
diff --git a/lib/getinfo.c b/lib/getinfo.c
index c94ca2cb9..2ec0242a6 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -176,7 +176,7 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
*param_charp = data->info.contenttype;
break;
case CURLINFO_PRIVATE:
- *param_charp = data->set.private_data;
+ *param_charp = (char *) data->set.private_data;
break;
case CURLINFO_HTTPAUTH_AVAIL:
*param_longp = data->info.httpauthavail;
diff --git a/lib/gtls.c b/lib/gtls.c
index 03572d88e..a40ea096b 100644
--- a/lib/gtls.c
+++ b/lib/gtls.c
@@ -299,11 +299,13 @@ Curl_gtls_connect(struct connectdata *conn,
if(rc < 0)
return CURLE_SSL_CONNECT_ERROR;
- if(data->set.cert) {
+ if(data->set.str[STRING_CERT]) {
if( gnutls_certificate_set_x509_key_file(
- conn->ssl[sockindex].cred, data->set.cert,
- data->set.key != 0 ? data->set.key : data->set.cert,
- do_file_type(data->set.cert_type) ) ) {
+ conn->ssl[sockindex].cred,
+ data->set.str[STRING_CERT],
+ data->set.str[STRING_KEY] ?
+ data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
+ do_file_type(data->set.str[STRING_CERT_TYPE]) ) ) {
failf(data, "error reading X.509 key or certificate file");
return CURLE_SSL_CONNECT_ERROR;
}
diff --git a/lib/gtls.h b/lib/gtls.h
index bff3f8693..feb02fd64 100644
--- a/lib/gtls.h
+++ b/lib/gtls.h
@@ -29,7 +29,9 @@ CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex);
/* tell GnuTLS to close down all open information regarding connections (and
thus session ID caching etc) */
void Curl_gtls_close_all(struct SessionHandle *data);
-void Curl_gtls_close(struct connectdata *conn); /* close a SSL connection */
+
+ /* close a SSL connection */
+void Curl_gtls_close(struct connectdata *conn, int index);
/* return number of sent (non-SSL) bytes */
ssize_t Curl_gtls_send(struct connectdata *conn, int sockindex,
diff --git a/lib/http.c b/lib/http.c
index 19e7483df..61511b57a 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -1187,7 +1187,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
if(!checkheaders(data, "Proxy-Connection:"))
proxyconn = "Proxy-Connection: Keep-Alive\r\n";
- if(!checkheaders(data, "User-Agent:") && data->set.useragent)
+ if(!checkheaders(data, "User-Agent:") &&
+ data->set.str[STRING_USERAGENT])
useragent = conn->allocptr.uagent;
/* Send the connect request to the proxy */
@@ -1770,8 +1771,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
/* Now set the 'request' pointer to the proper request string */
- if(data->set.customrequest)
- request = data->set.customrequest;
+ if(data->set.str[STRING_CUSTOMREQUEST])
+ request = data->set.str[STRING_CUSTOMREQUEST];
else {
if(conn->bits.no_body)
request = (char *)"HEAD";
@@ -1826,14 +1827,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
else
conn->allocptr.ref = NULL;
- if(data->set.cookie && !checkheaders(data, "Cookie:"))
- addcookies = data->set.cookie;
+ if(data->set.str[STRING_COOKIE] && !checkheaders(data, "Cookie:"))
+ addcookies = data->set.str[STRING_COOKIE];
if(!checkheaders(data, "Accept-Encoding:") &&
- data->set.encoding) {
+ data->set.str[STRING_ENCODING]) {
Curl_safefree(conn->allocptr.accept_encoding);
conn->allocptr.accept_encoding =
- aprintf("Accept-Encoding: %s\r\n", data->set.encoding);
+ aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
if(!conn->allocptr.accept_encoding)
return CURLE_OUT_OF_MEMORY;
}
@@ -2107,19 +2108,23 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.userpwd?conn->allocptr.userpwd:"",
(data->reqdata.use_range && conn->allocptr.rangeline)?
conn->allocptr.rangeline:"",
- (data->set.useragent && *data->set.useragent && conn->allocptr.uagent)?
+ (data->set.str[STRING_USERAGENT] &&
+ *data->set.str[STRING_USERAGENT] && conn->allocptr.uagent)?
conn->allocptr.uagent:"",
(conn->allocptr.host?conn->allocptr.host:""), /* Host: host */
http->p_pragma?http->p_pragma:"",
http->p_accept?http->p_accept:"",
- (data->set.encoding && *data->set.encoding && conn->allocptr.accept_encoding)?
- conn->allocptr.accept_encoding:"",
- (data->change.referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: <data> */,
- (conn->bits.httpproxy &&
- !conn->bits.tunnel_proxy &&
- !checkheaders(data, "Proxy-Connection:"))?
+ (data->set.str[STRING_ENCODING] &&
+ *data->set.str[STRING_ENCODING] &&
+ conn->allocptr.accept_encoding)?
+ conn->allocptr.accept_encoding:"",
+ (data->change.referer && conn->allocptr.ref)?
+ conn->allocptr.ref:"" /* Referer: <data> */,
+ (conn->bits.httpproxy &&
+ !conn->bits.tunnel_proxy &&
+ !checkheaders(data, "Proxy-Connection:"))?
"Proxy-Connection: Keep-Alive\r\n":"",
- te
+ te
);
if(result)
@@ -2384,7 +2389,8 @@ 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.postfields?(curl_off_t)strlen(data->set.postfields):0);
+ (data->set.str[STRING_POSTFIELDS]?
+ (curl_off_t)strlen(data->set.str[STRING_POSTFIELDS]):0);
if(!conn->bits.upload_chunky) {
/* We only set Content-Length and allow a custom Content-Length if
@@ -2409,7 +2415,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
return result;
}
- if(data->set.postfields) {
+ if(data->set.str[STRING_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 */
@@ -2437,7 +2443,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.postfields,
+ result = add_buffer(req_buffer, data->set.str[STRING_POSTFIELDS],
(size_t)postsize);
included_body = postsize;
}
@@ -2445,7 +2451,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.postfields,
+ result = add_buffer(req_buffer, data->set.str[STRING_POSTFIELDS],
(size_t)postsize);
if(CURLE_OK == result)
result = add_buffer(req_buffer,
@@ -2459,7 +2465,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.postfields;
+ http->postdata = data->set.str[STRING_POSTFIELDS];
http->sending = HTTPSEND_BODY;
diff --git a/lib/nss.c b/lib/nss.c
index c99258969..e90156e15 100644
--- a/lib/nss.c
+++ b/lib/nss.c
@@ -225,8 +225,8 @@ static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg)
pphrase_arg_t *parg = (pphrase_arg_t *) arg;
(void)slot; /* unused */
(void)retry; /* unused */
- if(parg->data->set.key_passwd)
- return (char *)PORT_Strdup((char *)parg->data->set.key_passwd);
+ if(parg->data->set.str[STRING_KEY_PASSWD])
+ return (char *)PORT_Strdup((char *)parg->data->set.str[STRING_KEY_PASSWD]);
else
return NULL;
}
@@ -488,10 +488,11 @@ CURLcode Curl_nss_connect(struct connectdata * conn, int sockindex)
NULL) != SECSuccess)
goto error;
- if(data->set.cert) {
+ if(data->set.str[STRING_CERT]) {
if(SSL_GetClientAuthDataHook(model,
(SSLGetClientAuthData) SelectClientCert,
- (void *)data->set.cert) != SECSuccess) {
+ (void *)data->set.str[STRING_CERT]) !=
+ SECSuccess) {
curlerr = CURLE_SSL_CERTPROBLEM;
goto error;
}
diff --git a/lib/nssg.h b/lib/nssg.h
index 3774c0fb3..c8582d389 100644
--- a/lib/nssg.h
+++ b/lib/nssg.h
@@ -32,7 +32,9 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex);
CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
int sockindex,
bool *done);
-void Curl_nss_close(struct connectdata *conn); /* close a SSL connection */
+/* close a SSL connection */
+void Curl_nss_close(struct connectdata *conn, int index);
+
/* tell NSS to close down all open information regarding connections (and
thus session ID caching etc) */
int Curl_nss_close_all(struct SessionHandle *data);
diff --git a/lib/ssh.c b/lib/ssh.c
index 58d7c6963..7a0da7475 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -422,8 +422,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
HOME environment variable etc? */
home = curl_getenv("HOME");
- if (data->set.ssh_public_key)
- sshc->rsa_pub = aprintf("%s", data->set.ssh_public_key);
+ if (data->set.str[STRING_SSH_PUBLIC_KEY])
+ sshc->rsa_pub = aprintf("%s", data->set.str[STRING_SSH_PUBLIC_KEY]);
else if (home)
sshc->rsa_pub = aprintf("%s/.ssh/id_dsa.pub", home);
@@ -435,8 +435,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break;
}
- if (data->set.ssh_private_key)
- sshc->rsa = aprintf("%s", data->set.ssh_private_key);
+ if (data->set.str[STRING_SSH_PRIVATE_KEY])
+ sshc->rsa = aprintf("%s", data->set.str[STRING_SSH_PRIVATE_KEY]);
else if (home)
sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
@@ -450,7 +450,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break;
}
- sshc->passphrase = data->set.key_passwd;
+ sshc->passphrase = data->set.str[STRING_KEY_PASSWD];
if (!sshc->passphrase)
sshc->passphrase = "";
diff --git a/lib/sslgen.c b/lib/sslgen.c
index 7410a00de..90af86053 100644
--- a/lib/sslgen.c
+++ b/lib/sslgen.c
@@ -135,20 +135,11 @@ Curl_clone_ssl_config(struct ssl_config_data *source,
void Curl_free_ssl_config(struct ssl_config_data* sslc)
{
- if(sslc->CAfile)
- free(sslc->CAfile);
-
- if(sslc->CApath)
- free(sslc->CApath);
-
- if(sslc->cipher_list)
- free(sslc->cipher_list);
-
- if(sslc->egdsocket)
- free(sslc->egdsocket);
-
- if(sslc->random_file)
- free(sslc->random_file);
+ Curl_safefree(sslc->CAfile);
+ Curl_safefree(sslc->CApath);
+ Curl_safefree(sslc->cipher_list);
+ Curl_safefree(sslc->egdsocket);
+ Curl_safefree(sslc->random_file);
}
/**
diff --git a/lib/ssluse.c b/lib/ssluse.c
index b5fc08d18..f10002eca 100644
--- a/lib/ssluse.c
+++ b/lib/ssluse.c
@@ -182,8 +182,9 @@ static int ossl_seed(struct SessionHandle *data)
#endif
{
/* let the option override the define */
- nread += RAND_load_file((data->set.ssl.random_file?
- data->set.ssl.random_file:RANDOM_FILE),
+ nread += RAND_load_file((data->set.str[STRING_SSL_RANDOM_FILE]?
+ data->set.str[STRING_SSL_RANDOM_FILE]:
+ RANDOM_FILE),
RAND_LOAD_LENGTH);
if(seed_enough(nread))
return nread;
@@ -195,14 +196,14 @@ static int ossl_seed(struct SessionHandle *data)
#ifndef EGD_SOCKET
/* If we don't have the define set, we only do this if the egd-option
is set */
- if(data->set.ssl.egdsocket)
+ if(data->set.str[STRING_SSL_EGDSOCKET])
#define EGD_SOCKET "" /* doesn't matter won't be used */
#endif
{
/* If there's an option and a define, the option overrides the
define */
- int ret = RAND_egd(data->set.ssl.egdsocket?
- data->set.ssl.egdsocket:EGD_SOCKET);
+ int ret = RAND_egd(data->set.str[STRING_SSL_EGDSOCKET]?
+ data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET);
if(-1 != ret) {
nread += ret;
if(seed_enough(nread))
@@ -261,7 +262,8 @@ int Curl_ossl_seed(struct SessionHandle *data)
time-consuming seedings in vain */
static bool ssl_seeded = FALSE;
- if(!ssl_seeded || data->set.ssl.random_file || data->set.ssl.egdsocket) {
+ if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
+ data->set.str[STRING_SSL_EGDSOCKET]) {
ossl_seed(data);
ssl_seeded = TRUE;
}
@@ -306,7 +308,7 @@ int cert_stuff(struct connectdata *conn,
X509 *x509;
int cert_done = 0;
- if(data->set.key_passwd) {
+ if(data->set.str[STRING_KEY_PASSWD]) {
#ifndef HAVE_USERDATA_IN_PWD_CALLBACK
/*
* If password has been given, we store that in the global
@@ -320,7 +322,7 @@ int cert_stuff(struct connectdata *conn,
* We set the password in the callback userdata
*/
SSL_CTX_set_default_passwd_cb_userdata(ctx,
- data->set.key_passwd);
+ data->set.str[STRING_KEY_PASSWD]);
#endif
/* Set passwd callback: */
SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
@@ -373,7 +375,8 @@ int cert_stuff(struct connectdata *conn,
PKCS12_PBE_add();
- if (!PKCS12_parse(p12, data->set.key_passwd, &pri, &x509, NULL)) {
+ if (!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509,
+ NULL)) {
failf(data,
"could not parse PKCS12 file, check password, OpenSSL error %s",
ERR_error_string(ERR_get_error(), NULL) );
@@ -446,7 +449,7 @@ int cert_stuff(struct connectdata *conn,
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
ui_method,
#endif
- data->set.key_passwd);
+ data->set.str[STRING_KEY_PASSWD]);
if(!priv_key) {
failf(data, "failed to load private key from crypto engine\n");
return 0;
@@ -1340,37 +1343,40 @@ Curl_ossl_connect_step1(struct connectdata *conn,
SSL_CTX_ctrl(connssl->ctx, BIO_C_SET_NBIO, 1, NULL);
#endif
- if(data->set.cert) {
+ if(data->set.str[STRING_CERT]) {
if(!cert_stuff(conn,
connssl->ctx,
- data->set.cert,
- data->set.cert_type,
- data->set.key,
- data->set.key_type)) {
+ data->set.str[STRING_CERT],
+ data->set.str[STRING_CERT_TYPE],
+ data->set.str[STRING_KEY],
+ data->set.str[STRING_KEY_TYPE])) {
/* failf() is already done in cert_stuff() */
return CURLE_SSL_CERTPROBLEM;
}
}
- if(data->set.ssl.cipher_list) {
+ if(data->set.str[STRING_SSL_CIPHER_LIST]) {
if(!SSL_CTX_set_cipher_list(connssl->ctx,
- data->set.ssl.cipher_list)) {
+ data->set.str[STRING_SSL_CIPHER_LIST])) {
failf(data, "failed setting cipher list");
return CURLE_SSL_CIPHER;
}
}
- if (data->set.ssl.CAfile || data->set.ssl.CApath) {
+ if (data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) {
/* tell SSL where to find CA certificates that are used to verify
the servers certificate. */
- if (!SSL_CTX_load_verify_locations(connssl->ctx, data->set.ssl.CAfile,
- data->set.ssl.CApath)) {
+ if (!SSL_CTX_load_verify_locations(connssl->ctx,
+ data->set.str[STRING_SSL_CAFILE],
+ data->set.str[STRING_SSL_CAPATH])) {
if (data->set.ssl.verifypeer) {
/* Fail if we insist on successfully verifying the server. */
failf(data,"error setting certificate verify locations:\n"
" CAfile: %s\n CApath: %s\n",
- data->set.ssl.CAfile ? data->set.ssl.CAfile : "none",
- data->set.ssl.CApath ? data->set.ssl.CApath : "none");
+ data->set.str[STRING_SSL_CAFILE]?
+ data->set.str[STRING_SSL_CAFILE]: "none",
+ data->set.str[STRING_SSL_CAPATH]?
+ data->set.str[STRING_SSL_CAPATH] : "none");
return CURLE_SSL_CACERT_BADFILE;
}
else {
@@ -1387,8 +1393,10 @@ Curl_ossl_connect_step1(struct connectdata *conn,
infof(data,
" CAfile: %s\n"
" CApath: %s\n",
- data->set.ssl.CAfile ? data->set.ssl.CAfile : "none",
- data->set.ssl.CApath ? data->set.ssl.CApath : "none");
+ data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
+ "none",
+ data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
+ "none");
}
/* SSL always tries to verify the peer, this only says whether it should
* fail to connect if the verification fails, or if it should continue
diff --git a/lib/transfer.c b/lib/transfer.c
index 8cf10f20e..efa8cdd02 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -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.postfields ||
+ if(data->set.str[STRING_POSTFIELDS] ||
(data->set.httpreq == HTTPREQ_POST_FORM))
; /* do nothing */
else {
@@ -992,7 +992,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
}
else if (checkprefix("Content-Encoding:", k->p) &&
- data->set.encoding) {
+ data->set.str[STRING_ENCODING]) {
/*
* Process Content-Encoding. Look for the values: identity,
* gzip, deflate, compress, x-gzip and x-compress. x-gzip and
diff --git a/lib/url.c b/lib/url.c
index 7a8effb1e..0de87a824 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -217,6 +217,59 @@ static void close_connections(struct SessionHandle *data)
; /* empty loop */
}
+void Curl_freeset(struct SessionHandle * data)
+{
+ /* Free all dynamic strings stored in the data->set substructure. */
+ enum dupstring i;
+ for(i=0; i < STRING_LAST; i++)
+ Curl_safefree(data->set.str[i]);
+}
+
+static CURLcode Curl_setstropt(char **charp, char * s)
+{
+ /* Release the previous storage at `charp' and replace by a dynamic storage
+ copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
+
+ if (*charp) {
+ free(*charp);
+ *charp = (char *) NULL;
+ }
+
+ if (s) {
+ s = strdup(s);
+
+ if (!s)
+ return CURLE_OUT_OF_MEMORY;
+
+ *charp = s;
+ }
+
+ return CURLE_OK;
+}
+
+CURLcode Curl_dupset(struct SessionHandle * dst, struct SessionHandle * src)
+{
+ CURLcode r;
+ enum dupstring i;
+
+ /* Copy src->set into dst->set first, then deal with the strings
+ afterwards */
+ dst->set = src->set;
+
+ /* clear all string pointers first */
+ memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
+
+ /* duplicate all strings */
+ for(i=0; i< STRING_LAST; i++) {
+ r = Curl_setstropt(&dst->set.str[i], src->set.str[i]);
+ if (r != CURLE_OK)
+ break;
+ }
+
+ /* If a failure occurred, freeing has to be performed externally. */
+ return r;
+}
+
/*
* This is the internal function curl_easy_cleanup() calls. This should
* cleanup and free all resources associated with this sessionhandle.
@@ -329,7 +382,7 @@ CURLcode Curl_close(struct SessionHandle *data)
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
- if(data->set.cookiejar) {
+ if(data->set.str[STRING_COOKIEJAR]) {
if(data->change.cookielist) {
/* If there is a list of cookie files to read, do it first so that
we have all the told files read before we write the new jar */
@@ -337,9 +390,9 @@ CURLcode Curl_close(struct SessionHandle *data)
}
/* we have a "destination" for all the cookies to get dumped to */
- if(Curl_cookie_output(data->cookies, data->set.cookiejar))
+ if(Curl_cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR]))
infof(data, "WARNING: failed to save cookies in %s\n",
- data->set.cookiejar);
+ data->set.str[STRING_COOKIEJAR]);
}
else {
if(data->change.cookielist)
@@ -381,6 +434,7 @@ CURLcode Curl_close(struct SessionHandle *data)
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
}
+ Curl_freeset(data);
free(data);
return CURLE_OK;
}
@@ -609,7 +663,8 @@ CURLcode Curl_open(struct SessionHandle **curl)
data->set.ssl.sessionid = TRUE; /* session ID caching enabled by default */
#ifdef CURL_CA_BUNDLE
/* This is our preferred CA cert bundle since install time */
- data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE;
+ res = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE],
+ (char *) CURL_CA_BUNDLE);
#endif
}
@@ -617,6 +672,7 @@ CURLcode Curl_open(struct SessionHandle **curl)
ares_destroy(data->state.areschannel);
if(data->state.headerbuff)
free(data->state.headerbuff);
+ Curl_freeset(data);
free(data);
data = NULL;
}
@@ -648,7 +704,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
break;
case CURLOPT_SSL_CIPHER_LIST:
/* set a list of cipher we want to use in the SSL connection */
- data->set.ssl.cipher_list = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
+ va_arg(param, char *));
break;
case CURLOPT_RANDOM_FILE:
@@ -656,13 +713,15 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* This is the path name to a file that contains random data to seed
* the random SSL stuff with. The file is only used for reading.
*/
- data->set.ssl.random_file = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
+ va_arg(param, char *));
break;
case CURLOPT_EGDSOCKET:
/*
* The Entropy Gathering Daemon socket pathname
*/
- data->set.ssl.egdsocket = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
+ va_arg(param, char *));
break;
case CURLOPT_MAXCONNECTS:
/*
@@ -785,7 +844,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* Use this file instead of the $HOME/.netrc file
*/
- data->set.netrc_file = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_NETRC_FILE],
+ va_arg(param, char *));
break;
case CURLOPT_TRANSFERTEXT:
/*
@@ -836,9 +896,10 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* and ignore an received Content-Encoding header.
*
*/
- data->set.encoding = va_arg(param, char *);
- if(data->set.encoding && !*data->set.encoding)
- data->set.encoding = (char*)ALL_CONTENT_ENCODINGS;
+ argptr = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_ENCODING],
+ (argptr && !*argptr)?
+ (char *) ALL_CONTENT_ENCODINGS: argptr);
break;
case CURLOPT_FOLLOWLOCATION:
@@ -881,7 +942,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* A string with POST data. Makes curl HTTP POST. Even if it is NULL.
*/
- data->set.postfields = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_POSTFIELDS],
+ va_arg(param, char *));
data->set.httpreq = HTTPREQ_POST;
break;
@@ -918,15 +980,17 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
free(data->change.referer);
data->change.referer_alloc = FALSE;
}
- data->set.set_referer = va_arg(param, char *);
- data->change.referer = data->set.set_referer;
+ result = Curl_setstropt(&data->set.str[STRING_SET_REFERER],
+ va_arg(param, char *));
+ data->change.referer = data->set.str[STRING_SET_REFERER];
break;
case CURLOPT_USERAGENT:
/*
* String to use in the HTTP User-Agent field
*/
- data->set.useragent = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_USERAGENT],
+ va_arg(param, char *));
break;
case CURLOPT_HTTPHEADER:
@@ -948,7 +1012,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* Cookie string to send to the remote server in the request.
*/
- data->set.cookie = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_COOKIE],
+ va_arg(param, char *));
break;
case CURLOPT_COOKIEFILE:
@@ -973,7 +1038,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* Set cookie file name to dump all cookies to when we're done.
*/
- data->set.cookiejar = (char *)va_arg(param, void *);
+ result = Curl_setstropt(&data->set.str[STRING_COOKIEJAR],
+ va_arg(param, char *));
/*
* Activate the cookie parser. This may or may not already
@@ -1071,7 +1137,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* Set a custom string to use as request
*/
- data->set.customrequest = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_CUSTOMREQUEST],
+ va_arg(param, char *));
/* we don't set
data->set.httpreq = HTTPREQ_CUSTOM;
@@ -1137,7 +1204,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* Setting it to NULL, means no proxy but allows the environment variables
* to decide for us.
*/
- data->set.proxy = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_PROXY],
+ va_arg(param, char *));
break;
case CURLOPT_WRITEHEADER:
@@ -1163,8 +1231,9 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* Use FTP PORT, this also specifies which IP address to use
*/
- data->set.ftpport = va_arg(param, char *);
- data->set.ftp_use_port = (bool)(NULL != data->set.ftpport);
+ result = Curl_setstropt(&data->set.str[STRING_FTPPORT],
+ va_arg(param, char *));
+ data->set.ftp_use_port = (bool)(NULL != data->set.str[STRING_FTPPORT]);
break;
case CURLOPT_FTP_USE_EPRT:
@@ -1247,8 +1316,9 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
free(data->change.url);
data->change.url_alloc=FALSE;
}
- data->set.set_url = va_arg(param, char *);
- data->change.url = data->set.set_url;
+ result = Curl_setstropt(&data->set.str[STRING_SET_URL],
+ va_arg(param, char *));
+ data->change.url = data->set.str[STRING_SET_URL];
data->change.url_changed = TRUE;
break;
case CURLOPT_PORT:
@@ -1284,7 +1354,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* user:password to use in the operation
*/
- data->set.userpwd = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_USERPWD],
+ va_arg(param, char *));
break;
case CURLOPT_POSTQUOTE:
/*
@@ -1325,13 +1396,15 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* user:password needed to use the proxy
*/
- data->set.proxyuserpwd = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_PROXYUSERPWD],
+ va_arg(param, char *));
break;
case CURLOPT_RANGE:
/*
* What range of the file you want to transfer
*/
- data->set.set_range = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_SET_RANGE],
+ va_arg(param, char *));
break;
case CURLOPT_RESUME_FROM:
/*
@@ -1428,31 +1501,36 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* String that holds file name of the SSL certificate to use
*/
- data->set.cert = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_CERT],
+ va_arg(param, char *));
break;
case CURLOPT_SSLCERTTYPE:
/*
* String that holds file type of the SSL certificate to use
*/
- data->set.cert_type = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE],
+ va_arg(param, char *));
break;
case CURLOPT_SSLKEY:
/*
* String that holds file name of the SSL certificate to use
*/
- data->set.key = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_KEY],
+ va_arg(param, char *));
break;
case CURLOPT_SSLKEYTYPE:
/*
* String that holds file type of the SSL certificate to use
*/
- data->set.key_type = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE],
+ va_arg(param, char *));
break;
case CURLOPT_SSLKEYPASSWD:
/*
* String that holds the SSL private key password.
*/
- data->set.key_passwd = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD],
+ va_arg(param, char *));
break;
case CURLOPT_SSLENGINE:
/*
@@ -1481,7 +1559,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* Set what interface or address/hostname to bind the socket to when
* performing an operation and thus what from-IP your connection will use.
*/
- data->set.device = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_DEVICE],
+ va_arg(param, char *));
break;
case CURLOPT_LOCALPORT:
/*
@@ -1499,8 +1578,9 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* A string that defines the kerberos security level.
*/
- data->set.krb_level = va_arg(param, char *);
- data->set.krb = (bool)(NULL != data->set.krb_level);
+ result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL],
+ va_arg(param, char *));
+ data->set.krb = (bool)(NULL != data->set.str[STRING_KRB_LEVEL]);
break;
case CURLOPT_SSL_VERIFYPEER:
/*
@@ -1530,7 +1610,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* Set CA info for SSL connection. Specify file name of the CA certificate
*/
- data->set.ssl.CAfile = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE],
+ va_arg(param, char *));
break;
case CURLOPT_CAPATH:
/*
@@ -1538,7 +1619,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
* certificates which have been prepared using openssl c_rehash utility.
*/
/* This does not work on windows. */
- data->set.ssl.CApath = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH],
+ va_arg(param, char *));
break;
case CURLOPT_TELNETOPTIONS:
/*
@@ -1639,7 +1721,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* Set private data pointer.
*/
- data->set.private_data = va_arg(param, char *);
+ data->set.private_data = va_arg(param, void *);
break;
case CURLOPT_MAXFILESIZE:
@@ -1691,7 +1773,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
These former 3rd party transfer options are deprecated */
case CURLOPT_FTP_ACCOUNT:
- data->set.ftp_account = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_FTP_ACCOUNT],
+ va_arg(param, char *));
break;
case CURLOPT_IGNORE_CONTENT_LENGTH:
@@ -1706,7 +1789,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
break;
case CURLOPT_FTP_ALTERNATIVE_TO_USER:
- data->set.ftp_alternative_to_user = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
+ va_arg(param, char *));
break;
case CURLOPT_SOCKOPTFUNCTION:
@@ -1735,14 +1819,16 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/*
* Use this file instead of the $HOME/.ssh/id_dsa.pub file
*/
- data->set.ssh_public_key = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
+ va_arg(param, char *));
break;
case CURLOPT_SSH_PRIVATE_KEYFILE:
/*
* Use this file instead of the $HOME/.ssh/id_dsa file
*/
- data->set.ssh_private_key = va_arg(param, char *);
+ result = Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
+ va_arg(param, char *));
break;
case CURLOPT_HTTP_TRANSFER_DECODING:
@@ -2780,14 +2866,14 @@ static CURLcode setup_range(struct SessionHandle *data)
struct HandleData *req = &data->reqdata;
req->resume_from = data->set.set_resume_from;
- if (req->resume_from || data->set.set_range) {
+ if (req->resume_from || data->set.str[STRING_SET_RANGE]) {
if (req->rangestringalloc == TRUE)
free(req->range);
if(req->resume_from)
req->range = aprintf("%" FORMAT_OFF_T "-", req->resume_from);
else
- req->range = strdup(data->set.set_range);
+ req->range = strdup(data->set.str[STRING_SET_RANGE]);
req->rangestringalloc = req->range?TRUE:FALSE;
@@ -2892,7 +2978,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
conn->connectindex = -1; /* no index */
conn->proxytype = data->set.proxytype; /* type */
- conn->bits.proxy = (bool)(data->set.proxy && *data->set.proxy);
+ conn->bits.proxy = (bool)(data->set.str[STRING_PROXY] &&
+ *data->set.str[STRING_PROXY]);
conn->bits.httpproxy = (bool)(conn->bits.proxy
&& (conn->proxytype == CURLPROXY_HTTP));
@@ -2911,8 +2998,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/* Store creation time to help future close decision making */
conn->created = Curl_tvnow();
- conn->bits.user_passwd = (bool)(NULL != data->set.userpwd);
- conn->bits.proxy_user_passwd = (bool)(NULL != data->set.proxyuserpwd);
+ conn->bits.user_passwd = (bool)(NULL != data->set.str[STRING_USERPWD]);
+ conn->bits.proxy_user_passwd = (bool)(NULL != data->set.str[STRING_PROXYUSERPWD]);
conn->bits.no_body = data->set.opt_no_body;
conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
@@ -2945,11 +3032,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
if(urllen < LEAST_PATH_ALLOC)
urllen=LEAST_PATH_ALLOC;
- if (!data->set.source_url /* 3rd party FTP */
- && data->reqdata.pathbuffer) {
- /* Free the old buffer */
- free(data->reqdata.pathbuffer);
- }
+ /* Free the old buffer */
+ Curl_safefree(data->reqdata.pathbuffer);
/*
* We malloc() the buffers below urllen+2 to make room for to possibilities:
@@ -2981,7 +3065,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
char proxyuser[MAX_CURL_USER_LENGTH]="";
char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
- sscanf(data->set.proxyuserpwd,
+ sscanf(data->set.str[STRING_PROXYUSERPWD],
"%" MAX_CURL_USER_LENGTH_TXT "[^:]:"
"%" MAX_CURL_PASSWORD_LENGTH_TXT "[^\n]",
proxyuser, proxypasswd);
@@ -2995,8 +3079,9 @@ static CURLcode CreateConnection(struct SessionHandle *data,
return CURLE_OUT_OF_MEMORY;
}
- if (data->set.proxy) {
- proxy = strdup(data->set.proxy); /* if global proxy is set, this is it */
+ if (data->set.str[STRING_PROXY]) {
+ proxy = strdup(data->set.str[STRING_PROXY]);
+ /* if global proxy is set, this is it */
if(NULL == proxy) {
failf(data, "memory shortage");
return CURLE_OUT_OF_MEMORY;
@@ -3711,9 +3796,9 @@ static CURLcode CreateConnection(struct SessionHandle *data,
* user_password is set in "inherit initial knowledge' above,
* so it doesn't have to be set in this block
*/
- if (data->set.userpwd != NULL) {
+ if (data->set.str[STRING_USERPWD] != NULL) {
/* the name is given, get user+password */
- sscanf(data->set.userpwd,
+ sscanf(data->set.str[STRING_USERPWD],
"%" MAX_CURL_USER_LENGTH_TXT "[^:]:"
"%" MAX_CURL_PASSWORD_LENGTH_TXT "[^\n]",
user, passwd);
@@ -3723,7 +3808,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
if (data->set.use_netrc != CURL_NETRC_IGNORED) {
if(Curl_parsenetrc(conn->host.name,
user, passwd,
- data->set.netrc_file)) {
+ data->set.str[STRING_NETRC_FILE])) {
infof(data, "Couldn't find host %s in the " DOT_CHAR
"netrc file, using defaults\n",
conn->host.name);
@@ -3760,8 +3845,21 @@ static CURLcode CreateConnection(struct SessionHandle *data,
* new one.
*************************************************************/
- /* get a cloned copy of the SSL config situation stored in the
- connection struct */
+ /* Get a cloned copy of the SSL config situation stored in the
+ connection struct. But to get this going nicely, we must first make
+ sure that the strings in the master copy are pointing to the correct
+ strings in the session handle strings array!
+
+ Keep in mind that the pointers in the master copy are pointing to strings
+ that will be freed as part of the SessionHandle struct, but all cloned
+ copies will be separately allocated.
+ */
+ data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH];
+ data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE];
+ data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
+ data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
+ data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
+
if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config))
return CURLE_OUT_OF_MEMORY;
@@ -4081,10 +4179,10 @@ static CURLcode SetupConnection(struct connectdata *conn,
/*************************************************************
* Set user-agent for HTTP
*************************************************************/
- if((conn->protocol&PROT_HTTP) && data->set.useragent) {
+ if((conn->protocol&PROT_HTTP) && data->set.str[STRING_USERAGENT]) {
Curl_safefree(conn->allocptr.uagent);
conn->allocptr.uagent =
- aprintf("User-Agent: %s\r\n", data->set.useragent);
+ aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
if(!conn->allocptr.uagent)
return CURLE_OUT_OF_MEMORY;
}
diff --git a/lib/url.h b/lib/url.h
index 9f92e693b..0431cb065 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -32,6 +32,8 @@
CURLcode Curl_open(struct SessionHandle **curl);
CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
va_list arg);
+CURLcode Curl_dupset(struct SessionHandle * dst, struct SessionHandle * src);
+void Curl_freeset(struct SessionHandle * data);
CURLcode Curl_close(struct SessionHandle *data); /* opposite of curl_open() */
CURLcode Curl_connect(struct SessionHandle *, struct connectdata **,
bool *async, bool *protocol_connect);
diff --git a/lib/urldata.h b/lib/urldata.h
index d1da3331c..41d852832 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -195,7 +195,7 @@ struct ssl_config_data {
long verifyhost; /* 0: no verify
1: check that CN exists
2: CN must match hostname */
- char *CApath; /* DOES NOT WORK ON WINDOWS */
+ char *CApath; /* certificate dir (doesn't work on windows) */
char *CAfile; /* cerficate to verify peer against */
char *random_file; /* path to file containing "random" data */
char *egdsocket; /* path to file containing the EGD daemon socket */
@@ -1237,43 +1237,69 @@ struct DynamicStatic {
* calculated internally for the "session handle" MUST be defined within the
* 'struct UrlState' instead. The only exceptions MUST note the changes in
* the 'DynamicStatic' struct.
+ * Character pointer fields point to dynamic storage, unless otherwise stated.
*/
struct Curl_one_easy; /* declared and used only in multi.c */
struct Curl_multi; /* declared and used only in multi.c */
+enum dupstring {
+ STRING_CERT, /* client certificate file name */
+ STRING_CERT_TYPE, /* format for certificate (default: PEM)*/
+ STRING_COOKIE, /* HTTP cookie string to send */
+ STRING_COOKIEJAR, /* dump all cookies to this file */
+ STRING_CUSTOMREQUEST, /* HTTP/FTP request/method to use */
+ STRING_DEVICE, /* local network interface/address to use */
+ STRING_ENCODING, /* Accept-Encoding string */
+ STRING_FTP_ACCOUNT, /* ftp account data */
+ STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */
+ STRING_FTPPORT, /* port to send with the FTP PORT command */
+ STRING_KEY, /* private key file name */
+ STRING_KEY_PASSWD, /* plain text private key password */
+ STRING_KEY_TYPE, /* format for private key (default: PEM) */
+ 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_PROXY, /* proxy to use */
+ STRING_PROXYUSERPWD, /* Proxy <user:password>, if used */
+ STRING_SET_RANGE, /* range, if used */
+ STRING_SET_REFERER, /* custom string for the HTTP referer field */
+ STRING_SET_URL, /* what original URL to work on */
+ STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */
+ STRING_SSH_PUBLIC_KEY, /* path to the public key file for auth */
+ STRING_SSL_CAPATH, /* CA directory name (doesn't work on windows) */
+ STRING_SSL_CAFILE, /* certificate file to verify peer against */
+ STRING_SSL_CIPHER_LIST, /* list of ciphers to use */
+ STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */
+ STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */
+ STRING_USERAGENT, /* User-Agent string */
+ STRING_USERPWD, /* <user:password>, if used */
+
+ /* -- end of strings -- */
+ STRING_LAST /* not used, just an end-of-list marker */
+};
+
struct UserDefined {
FILE *err; /* the stderr user data goes here */
void *debugdata; /* the data that will be passed to fdebug */
- char *errorbuffer; /* store failure messages in here */
- char *proxyuserpwd; /* Proxy <user:password>, if used */
+ char *errorbuffer; /* (Static) store failure messages in here */
long proxyport; /* If non-zero, use this port number by default. If the
proxy string features a ":[port]" that one will override
this. */
void *out; /* the fetched file goes here */
void *in; /* the uploaded file is read from here */
void *writeheader; /* write the header to this if non-NULL */
- char *set_url; /* what original URL to work on */
- char *proxy; /* proxy to use */
long use_port; /* which port to use (when not using default) */
- char *userpwd; /* <user:password>, if used */
long httpauth; /* what kind of HTTP authentication to use (bitmask) */
long proxyauth; /* what kind of proxy authentication to use (bitmask) */
- char *set_range; /* range, if used. See README for detailed specification
- on this syntax. */
long followlocation; /* as in HTTP Location: */
long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1
for infinity */
- char *set_referer; /* custom string */
bool free_referer; /* set TRUE if 'referer' points to a string we
allocated */
- char *useragent; /* User-Agent string */
- char *encoding; /* Accept-Encoding string */
- char *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) */
- char *ftpport; /* port to send with the FTP PORT command */
- char *device; /* local network interface/address to use */
unsigned short localport; /* local port number to bind to */
int localportrange; /* number of additional port numbers to test in case the
'localport' one can't be bind()ed */
@@ -1305,19 +1331,10 @@ struct UserDefined {
curl_off_t max_send_speed; /* high speed limit in bytes/second for upload */
curl_off_t max_recv_speed; /* high speed limit in bytes/second for download */
curl_off_t set_resume_from; /* continue [ftp] transfer from here */
- char *cookie; /* HTTP cookie string to send */
struct curl_slist *headers; /* linked list of extra headers */
struct curl_httppost *httppost; /* linked list of POST data */
- char *cert; /* certificate */
- char *cert_type; /* format for certificate (default: PEM) */
- char *key; /* private key */
- char *key_type; /* format for private key (default: PEM) */
- char *key_passwd; /* plain text private key password */
- char *cookiejar; /* dump all cookies to this file */
bool cookiesession; /* new cookie session? */
bool crlf; /* convert crlf on ftp upload(?) */
- char *ftp_account; /* ftp account data */
- char *ftp_alternative_to_user; /* command to send if USER/PASS fails */
struct curl_slist *quote; /* after connection is established */
struct curl_slist *postquote; /* after the transfer */
struct curl_slist *prequote; /* before the transfer, after type */
@@ -1330,14 +1347,8 @@ struct UserDefined {
curl_TimeCond timecondition; /* kind of time/date comparison */
time_t timevalue; /* what time to compare with */
Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
- char *customrequest; /* HTTP/FTP request to use */
long httpversion; /* when non-zero, a specific HTTP version requested to
be used in the library's request(s) */
- char *auth_host; /* if set, this is the allocated string to the host name
- * to which to send the authorization data to, and no other
- * host (which location-following otherwise could lead to)
- */
- char *krb_level; /* what security level */
struct ssl_config_data ssl; /* user defined SSL stuff */
curl_proxytype proxytype; /* what kind of proxy that is in use */
@@ -1345,7 +1356,7 @@ struct UserDefined {
int dns_cache_timeout; /* DNS cache timeout */
long buffer_size; /* size of receive buffer to use */
- char *private_data; /* Private data */
+ void *private_data; /* Private data */
struct Curl_one_easy *one_easy; /* When adding an easy handle to a multi
handle, an internal 'Curl_one_easy'
@@ -1359,9 +1370,6 @@ struct UserDefined {
curl_off_t max_filesize; /* Maximum file size to download */
- char *source_url; /* for 3rd party transfer */
- char *source_userpwd; /* for 3rd party transfer */
-
curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */
/* Here follows boolean settings that define how to behave during
@@ -1388,8 +1396,6 @@ struct UserDefined {
bool upload;
enum CURL_NETRC_OPTION
use_netrc; /* defined in include/curl.h */
- char *netrc_file; /* if not NULL, use this instead of trying to find
- $HOME/.netrc */
bool verbose;
bool krb; /* kerberos connection requested */
bool reuse_forbid; /* forbidden to be reused, close after use */
@@ -1408,16 +1414,14 @@ struct UserDefined {
us */
bool connect_only; /* make connection, let application use the socket */
long ssh_auth_types; /* allowed SSH auth types */
- char *ssh_public_key; /* the path to the public key file for
- authentication */
- char *ssh_private_key; /* the path to the private key file for
- authentication */
bool http_te_skip; /* pass the raw body data to the user, even when
transfer-encoded (chunked, compressed) */
bool http_ce_skip; /* pass the raw body data to the user, even when
content-encoded (chunked, compressed) */
long new_file_perms; /* Permissions to use when creating remote files */
long new_directory_perms; /* Permissions to use when creating remote dirs */
+
+ char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
};
struct Names {