1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-21 23:58:49 -05:00

multiple connection support initial commit

This commit is contained in:
Daniel Stenberg 2001-02-20 17:35:51 +00:00
parent 5f3d63ed5b
commit a1d6ad2610
20 changed files with 1601 additions and 1133 deletions

48
CHANGES
View File

@ -6,6 +6,54 @@
History of Changes History of Changes
** curl 7.7 DOES NOT currently WORK. **
Daniel (20 February 2001)
- Added the docs/examples/win32sockets.c file for our windows friends.
- Linus Nielsen Feltzing provided brand new TELNET functionality and
improvements:
* Negotiation is now passive. Curl does not negotiate until the peer does.
* Possibility to set negotiation options on the command line, currently only
XDISPLOC, TTYPE and NEW_ENVIRON (called NEW_ENV).
* Now sends the USER environment variable if the -u switch is used.
* Use -t to set telnet options (Linus even updated the man page, awesome!)
- Haven't done this big changes to curl for a while. Moved around a lot of
struct fields and stuff to make multiple connections get connection specific
data in separate structs so that they can co-exist in a nice way. See the
mailing lists for discussions around how this is gonna be implemented. Docs
and more will follow.
Studied the HTTP RFC to find out better how persistant connections should
work. Seems cool enough.
Daniel (19 February 2001)
- Bob Schader brought me two files that help set up a MS VC++ libcurl project
easier. He also provided me with an up-to-date libcurl.def file.
- I moved a bunch of prototypes from the public <curl/curl.h> file to the
library private urldata.h. This is because of the upcoming changes. The
low level interface is no longer being planned to become reality.
Daniel (15 February 2001)
- CURLOPT_POST is not required anymore. Just setting the POST string with
CURLOPT_POSTFIELDS will switch on the HTTP POST. Most other things in
libcurl already works this way, i.e they require only the parameter to
switch on a feature so I think this works well with the rest. Setting a NULL
string switches off the POST again.
- Excellent suggestions from Rich Gray, Rick Jones, Johan Nilsson and Bjorn
Reese helped me define a way how to incorporate persistant connections into
libcurl in a very smooth way. If done right, no change may have to be made
to older programs and they will just start using persistant connections when
applicable!
Daniel (13 February 2001)
- Changed the word 'timeouted' to 'timed out' in two different error messages.
Suggested by Larry Fahnoe.
Version 7.6.1 Version 7.6.1
Daniel (9 February 2001) Daniel (9 February 2001)

View File

@ -20,6 +20,7 @@ Misc
- compiles on win32 - compiles on win32
- redirectable stderr - redirectable stderr
- use selected network interface for outgoing traffic - use selected network interface for outgoing traffic
- IPv6 support
HTTP HTTP
- GET - GET
@ -28,7 +29,7 @@ HTTP
- POST - POST
- multipart POST - multipart POST
- authentication - authentication
- resume - resume (both GET and PUT)
- follow redirects - follow redirects
- maximum amount of redirects to follow - maximum amount of redirects to follow
- custom HTTP request - custom HTTP request

View File

@ -425,11 +425,14 @@ If this option is used twice, the second will again disable mute.
When used with -s it makes curl show error message if it fails. When used with -s it makes curl show error message if it fails.
If this option is used twice, the second will again disable show error. If this option is used twice, the second will again disable show error.
.IP "-t/--upload" .IP "-t/--telnet-option <OPT=val>"
.B Deprecated. Use '-T -' instead. Pass options to the telnet protocol. Supported options are:
Transfer the stdin data to the specified file. Curl will read
everything from stdin until EOF and store with the supplied name. If TTYPE=<term> Sets the terminal type.
this is used on a http(s) server, the PUT command will be used.
XDISPLOC=<X display> Sets the X display location.
NEW_ENV=<var,val> Sets an environment variable.
.IP "-T/--upload-file <file>" .IP "-T/--upload-file <file>"
Like -t, but this transfers the specified local file. If there is no Like -t, but this transfers the specified local file. If there is no
file part in the specified URL, Curl will append the local file file part in the specified URL, Curl will append the local file
@ -758,7 +761,7 @@ If you do find bugs, mail them to curl-bug@haxx.se.
- Lars J. Aas <larsa@sim.no> - Lars J. Aas <larsa@sim.no>
- Jörn Hartroth <Joern.Hartroth@computer.org> - Jörn Hartroth <Joern.Hartroth@computer.org>
- Matthew Clarke <clamat@van.maves.ca> - Matthew Clarke <clamat@van.maves.ca>
- Linus Nielsen <Linus.Nielsen@haxx.se> - Linus Nielsen Feltzing <linus@haxx.se>
- Felix von Leitner <felix@convergence.de> - Felix von Leitner <felix@convergence.de>
- Dan Zitter <dzitter@zitter.net> - Dan Zitter <dzitter@zitter.net>
- Jongki Suwandi <Jongki.Suwandi@eng.sun.com> - Jongki Suwandi <Jongki.Suwandi@eng.sun.com>

View File

@ -158,6 +158,9 @@ typedef enum {
CURLE_BAD_PASSWORD_ENTERED, /* when the my_getpass() returns fail */ CURLE_BAD_PASSWORD_ENTERED, /* when the my_getpass() returns fail */
CURLE_TOO_MANY_REDIRECTS , /* catch endless re-direct loops */ CURLE_TOO_MANY_REDIRECTS , /* catch endless re-direct loops */
CURLE_UNKNOWN_TELNET_OPTION , /* User specified an unknown option */
CURLE_TELNET_OPTION_SYNTAX , /* Malformed telnet option */
CURL_LAST CURL_LAST
} CURLcode; } CURLcode;
@ -406,6 +409,9 @@ typedef enum {
document! Pass a NULL to shut it off. */ document! Pass a NULL to shut it off. */
CINIT(FILETIME, OBJECTPOINT, 69), CINIT(FILETIME, OBJECTPOINT, 69),
/* This points to a linked list of telnet options */
CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
CURLOPT_LASTENTRY /* the last unusued */ CURLOPT_LASTENTRY /* the last unusued */
} CURLoption; } CURLoption;
@ -452,8 +458,8 @@ char *curl_getenv(char *variable);
char *curl_version(void); char *curl_version(void);
/* This is the version number */ /* This is the version number */
#define LIBCURL_VERSION "7.6.1" #define LIBCURL_VERSION "7.7-alpha1"
#define LIBCURL_VERSION_NUM 0x070601 #define LIBCURL_VERSION_NUM 0x070000
/* linked-list structure for the CURLOPT_QUOTE option (and other) */ /* linked-list structure for the CURLOPT_QUOTE option (and other) */
struct curl_slist { struct curl_slist {
@ -520,6 +526,20 @@ typedef enum {
*/ */
CURLcode curl_getinfo(CURL *curl, CURLINFO info, ...); CURLcode curl_getinfo(CURL *curl, CURLINFO info, ...);
typedef enum {
CURLCLOSEPOLICY_NONE, /* first, never use this */
CURLCLOSEPOLICY_OLDEST,
CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
CURLCLOSEPOLICY_LEAST_TRAFFIC,
CURLCLOSEPOLICY_SLOWEST,
CURLCLOSEPOLICY_CALLBACK,
CURLCLOSEPOLICY_LAST /* last, never use this */
} curl_closepolicy;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -141,7 +141,7 @@ CURLcode Curl_dict(struct connectdata *conn)
nth = atoi(nthdef); nth = atoi(nthdef);
} }
Curl_sendf(data->firstsocket, conn, Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n" "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"MATCH " "MATCH "
"%s " /* database */ "%s " /* database */
@ -154,7 +154,7 @@ CURLcode Curl_dict(struct connectdata *conn)
word word
); );
result = Curl_Transfer(conn, data->firstsocket, -1, FALSE, bytecount, result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */ -1, NULL); /* no upload */
if(result) if(result)
@ -191,7 +191,7 @@ CURLcode Curl_dict(struct connectdata *conn)
nth = atoi(nthdef); nth = atoi(nthdef);
} }
Curl_sendf(data->firstsocket, conn, Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n" "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"DEFINE " "DEFINE "
"%s " /* database */ "%s " /* database */
@ -202,7 +202,7 @@ CURLcode Curl_dict(struct connectdata *conn)
word word
); );
result = Curl_Transfer(conn, data->firstsocket, -1, FALSE, bytecount, result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */ -1, NULL); /* no upload */
if(result) if(result)
@ -220,13 +220,13 @@ CURLcode Curl_dict(struct connectdata *conn)
if (ppath[i] == ':') if (ppath[i] == ':')
ppath[i] = ' '; ppath[i] = ' ';
} }
Curl_sendf(data->firstsocket, conn, Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n" "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"%s\n" "%s\n"
"QUIT\n", "QUIT\n",
ppath); ppath);
result = Curl_Transfer(conn, data->firstsocket, -1, FALSE, bytecount, result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL); -1, NULL);
if(result) if(result)

141
lib/ftp.c
View File

@ -158,6 +158,7 @@ void curl_slist_free_all(struct curl_slist *list)
static CURLcode AllowServerConnect(struct UrlData *data, static CURLcode AllowServerConnect(struct UrlData *data,
struct connectdata *conn,
int sock) int sock)
{ {
fd_set rdset; fd_set rdset;
@ -199,7 +200,7 @@ static CURLcode AllowServerConnect(struct UrlData *data,
} }
infof(data, "Connection accepted from server\n"); infof(data, "Connection accepted from server\n");
data->secondarysocket = s; conn->secondarysocket = s;
} }
break; break;
} }
@ -362,7 +363,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
memset(ftp, 0, sizeof(struct FTP)); memset(ftp, 0, sizeof(struct FTP));
data->proto.ftp = ftp; conn->proto.ftp = ftp;
/* get some initial data into the ftp struct */ /* get some initial data into the ftp struct */
ftp->bytecountp = &conn->bytecount; ftp->bytecountp = &conn->bytecount;
@ -371,14 +372,14 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
if (data->bits.tunnel_thru_httpproxy) { if (data->bits.tunnel_thru_httpproxy) {
/* We want "seamless" FTP operations through HTTP proxy tunnel */ /* We want "seamless" FTP operations through HTTP proxy tunnel */
result = Curl_ConnectHTTPProxyTunnel(conn, data->firstsocket, result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket,
data->hostname, data->remote_port); conn->hostname, conn->remote_port);
if(CURLE_OK != result) if(CURLE_OK != result)
return result; return result;
} }
/* The first thing we do is wait for the "220*" line: */ /* The first thing we do is wait for the "220*" line: */
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -398,7 +399,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
set a valid level */ set a valid level */
sec_request_prot(conn, data->krb4_level); sec_request_prot(conn, data->krb4_level);
data->cmdchannel = fdopen(data->firstsocket, "w"); data->cmdchannel = fdopen(conn->firstsocket, "w");
if(sec_login(conn) != 0) if(sec_login(conn) != 0)
infof(data, "Logging in with password in cleartext!\n"); infof(data, "Logging in with password in cleartext!\n");
@ -408,10 +409,10 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
#endif #endif
/* send USER */ /* send USER */
ftpsendf(data->firstsocket, conn, "USER %s", ftp->user); ftpsendf(conn->firstsocket, conn, "USER %s", ftp->user);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -424,8 +425,8 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
else if(ftpcode == 331) { else if(ftpcode == 331) {
/* 331 Password required for ... /* 331 Password required for ...
(the server requires to send the user's password too) */ (the server requires to send the user's password too) */
ftpsendf(data->firstsocket, conn, "PASS %s", ftp->passwd); ftpsendf(conn->firstsocket, conn, "PASS %s", ftp->passwd);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -477,7 +478,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
CURLcode Curl_ftp_done(struct connectdata *conn) CURLcode Curl_ftp_done(struct connectdata *conn)
{ {
struct UrlData *data = conn->data; struct UrlData *data = conn->data;
struct FTP *ftp = data->proto.ftp; struct FTP *ftp = conn->proto.ftp;
size_t nread; size_t nread;
char *buf = data->buffer; /* this is our buffer */ char *buf = data->buffer; /* this is our buffer */
struct curl_slist *qitem; /* QUOTE item */ struct curl_slist *qitem; /* QUOTE item */
@ -502,16 +503,16 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
} }
} }
#ifdef KRB4 #ifdef KRB4
sec_fflush_fd(conn, data->secondarysocket); sec_fflush_fd(conn, conn->secondarysocket);
#endif #endif
/* shut down the socket to inform the server we're done */ /* shut down the socket to inform the server we're done */
sclose(data->secondarysocket); sclose(conn->secondarysocket);
data->secondarysocket = -1; conn->secondarysocket = -1;
if(!data->bits.no_body) { if(!data->bits.no_body) {
/* now let's see what the server says about the transfer we /* now let's see what the server says about the transfer we
just performed: */ just performed: */
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -529,9 +530,9 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
while (qitem) { while (qitem) {
/* Send string */ /* Send string */
if (qitem->data) { if (qitem->data) {
ftpsendf(data->firstsocket, conn, "%s", qitem->data); ftpsendf(conn->firstsocket, conn, "%s", qitem->data);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -571,7 +572,7 @@ CURLcode _ftp(struct connectdata *conn)
struct curl_slist *qitem; /* QUOTE item */ struct curl_slist *qitem; /* QUOTE item */
/* the ftp struct is already inited in ftp_connect() */ /* the ftp struct is already inited in ftp_connect() */
struct FTP *ftp = data->proto.ftp; struct FTP *ftp = conn->proto.ftp;
long *bytecountp = ftp->bytecountp; long *bytecountp = ftp->bytecountp;
int ftpcode; /* for ftp status */ int ftpcode; /* for ftp status */
@ -583,9 +584,9 @@ CURLcode _ftp(struct connectdata *conn)
while (qitem) { while (qitem) {
/* Send string */ /* Send string */
if (qitem->data) { if (qitem->data) {
ftpsendf(data->firstsocket, conn, "%s", qitem->data); ftpsendf(conn->firstsocket, conn, "%s", qitem->data);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -601,8 +602,8 @@ CURLcode _ftp(struct connectdata *conn)
/* change directory first! */ /* change directory first! */
if(ftp->dir && ftp->dir[0]) { if(ftp->dir && ftp->dir[0]) {
ftpsendf(data->firstsocket, conn, "CWD %s", ftp->dir); ftpsendf(conn->firstsocket, conn, "CWD %s", ftp->dir);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -615,9 +616,9 @@ CURLcode _ftp(struct connectdata *conn)
if(data->bits.get_filetime && ftp->file) { if(data->bits.get_filetime && ftp->file) {
/* we have requested to get the modified-time of the file, this is yet /* we have requested to get the modified-time of the file, this is yet
again a grey area as the MDTM is not kosher RFC959 */ again a grey area as the MDTM is not kosher RFC959 */
ftpsendf(data->firstsocket, conn, "MDTM %s", ftp->file); ftpsendf(conn->firstsocket, conn, "MDTM %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -651,10 +652,10 @@ CURLcode _ftp(struct connectdata *conn)
/* Some servers return different sizes for different modes, and thus we /* Some servers return different sizes for different modes, and thus we
must set the proper type before we check the size */ must set the proper type before we check the size */
ftpsendf(data->firstsocket, conn, "TYPE %s", ftpsendf(conn->firstsocket, conn, "TYPE %s",
(data->bits.ftp_ascii)?"A":"I"); (data->bits.ftp_ascii)?"A":"I");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -665,9 +666,9 @@ CURLcode _ftp(struct connectdata *conn)
CURLE_FTP_COULDNT_SET_BINARY; CURLE_FTP_COULDNT_SET_BINARY;
} }
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file); ftpsendf(conn->firstsocket, conn, "SIZE %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -731,7 +732,7 @@ CURLcode _ftp(struct connectdata *conn)
* I believe we should use the same address as the control connection. * I believe we should use the same address as the control connection.
*/ */
sslen = sizeof(ss); sslen = sizeof(ss);
if (getsockname(data->firstsocket, (struct sockaddr *)&ss, &sslen) < 0) if (getsockname(conn->firstsocket, (struct sockaddr *)&ss, &sslen) < 0)
return CURLE_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
if (getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL, 0, if (getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL, 0,
@ -819,7 +820,7 @@ CURLcode _ftp(struct connectdata *conn)
if (q) if (q)
*q = '\0'; *q = '\0';
} }
ftpsendf(data->firstsocket, conn, "%s |%d|%s|%s|", *modep, eprtaf, ftpsendf(conn->firstsocket, conn, "%s |%d|%s|%s|", *modep, eprtaf,
portmsgbuf, tmp); portmsgbuf, tmp);
} else if (strcmp(*modep, "LPRT") == 0 || strcmp(*modep, "PORT") == 0) { } else if (strcmp(*modep, "LPRT") == 0 || strcmp(*modep, "PORT") == 0) {
int i; int i;
@ -856,10 +857,10 @@ CURLcode _ftp(struct connectdata *conn)
goto again; goto again;
} }
} }
ftpsendf(data->firstsocket, conn, "%s %s", *modep, portmsgbuf); ftpsendf(conn->firstsocket, conn, "%s %s", *modep, portmsgbuf);
} }
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if (nread < 0) if (nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -909,7 +910,7 @@ again:;
/* we set the secondary socket variable to this for now, it /* we set the secondary socket variable to this for now, it
is only so that the cleanup function will close it in case is only so that the cleanup function will close it in case
we fail before the true secondary stuff is made */ we fail before the true secondary stuff is made */
data->secondarysocket = portsock; conn->secondarysocket = portsock;
memset((char *)&sa, 0, sizeof(sa)); memset((char *)&sa, 0, sizeof(sa));
memcpy((char *)&sa.sin_addr, memcpy((char *)&sa.sin_addr,
@ -971,13 +972,13 @@ again:;
sscanf( inet_ntoa(in), "%hu.%hu.%hu.%hu", sscanf( inet_ntoa(in), "%hu.%hu.%hu.%hu",
&ip[0], &ip[1], &ip[2], &ip[3]); &ip[0], &ip[1], &ip[2], &ip[3]);
#endif #endif
ftpsendf(data->firstsocket, conn, "PORT %d,%d,%d,%d,%d,%d", ftpsendf(conn->firstsocket, conn, "PORT %d,%d,%d,%d,%d,%d",
ip[0], ip[1], ip[2], ip[3], ip[0], ip[1], ip[2], ip[3],
porttouse >> 8, porttouse >> 8,
porttouse & 255); porttouse & 255);
} }
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -998,8 +999,8 @@ again:;
int modeoff; int modeoff;
for (modeoff = 0; mode[modeoff]; modeoff++) { for (modeoff = 0; mode[modeoff]; modeoff++) {
ftpsendf(data->firstsocket, conn, mode[modeoff]); ftpsendf(conn->firstsocket, conn, mode[modeoff]);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -1081,15 +1082,15 @@ again:;
} }
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
data->secondarysocket = -1; conn->secondarysocket = -1;
for (ai = res; ai; ai = ai->ai_next) { for (ai = res; ai; ai = ai->ai_next) {
/* XXX for now, we can do IPv4 only */ /* XXX for now, we can do IPv4 only */
if (ai->ai_family != AF_INET) if (ai->ai_family != AF_INET)
continue; continue;
data->secondarysocket = socket(ai->ai_family, ai->ai_socktype, conn->secondarysocket = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol); ai->ai_protocol);
if (data->secondarysocket < 0) if (conn->secondarysocket < 0)
continue; continue;
if(data->bits.verbose) { if(data->bits.verbose) {
@ -1114,21 +1115,21 @@ again:;
} }
} }
if (connect(data->secondarysocket, ai->ai_addr, ai->ai_addrlen) < 0) { if (connect(conn->secondarysocket, ai->ai_addr, ai->ai_addrlen) < 0) {
close(data->secondarysocket); close(conn->secondarysocket);
data->secondarysocket = -1; conn->secondarysocket = -1;
continue; continue;
} }
break; break;
} }
if (data->secondarysocket < 0) { if (conn->secondarysocket < 0) {
failf(data, strerror(errno)); failf(data, strerror(errno));
return CURLE_FTP_CANT_RECONNECT; return CURLE_FTP_CANT_RECONNECT;
} }
#else #else
data->secondarysocket = socket(AF_INET, SOCK_STREAM, 0); conn->secondarysocket = socket(AF_INET, SOCK_STREAM, 0);
memset((char *) &serv_addr, '\0', sizeof(serv_addr)); memset((char *) &serv_addr, '\0', sizeof(serv_addr));
memcpy((char *)&(serv_addr.sin_addr), he->h_addr, he->h_length); memcpy((char *)&(serv_addr.sin_addr), he->h_addr, he->h_length);
@ -1202,7 +1203,7 @@ again:;
if(hostdataptr) if(hostdataptr)
free(hostdataptr); free(hostdataptr);
if (connect(data->secondarysocket, (struct sockaddr *) &serv_addr, if (connect(conn->secondarysocket, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0) { sizeof(serv_addr)) < 0) {
switch(errno) { switch(errno) {
#ifdef ECONNREFUSED #ifdef ECONNREFUSED
@ -1226,7 +1227,7 @@ again:;
if (data->bits.tunnel_thru_httpproxy) { if (data->bits.tunnel_thru_httpproxy) {
/* We want "seamless" FTP operations through HTTP proxy tunnel */ /* We want "seamless" FTP operations through HTTP proxy tunnel */
result = Curl_ConnectHTTPProxyTunnel(conn, data->secondarysocket, result = Curl_ConnectHTTPProxyTunnel(conn, conn->secondarysocket,
newhost, newport); newhost, newport);
if(CURLE_OK != result) if(CURLE_OK != result)
return result; return result;
@ -1241,10 +1242,10 @@ again:;
if(data->bits.upload) { if(data->bits.upload) {
/* Set type to binary (unless specified ASCII) */ /* Set type to binary (unless specified ASCII) */
ftpsendf(data->firstsocket, conn, "TYPE %s", ftpsendf(conn->firstsocket, conn, "TYPE %s",
(data->bits.ftp_ascii)?"A":"I"); (data->bits.ftp_ascii)?"A":"I");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -1273,9 +1274,9 @@ again:;
/* we could've got a specified offset from the command line, /* we could've got a specified offset from the command line,
but now we know we didn't */ but now we know we didn't */
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file); ftpsendf(conn->firstsocket, conn, "SIZE %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -1332,11 +1333,11 @@ again:;
/* Send everything on data->in to the socket */ /* Send everything on data->in to the socket */
if(data->bits.ftp_append) if(data->bits.ftp_append)
/* we append onto the file instead of rewriting it */ /* we append onto the file instead of rewriting it */
ftpsendf(data->firstsocket, conn, "APPE %s", ftp->file); ftpsendf(conn->firstsocket, conn, "APPE %s", ftp->file);
else else
ftpsendf(data->firstsocket, conn, "STOR %s", ftp->file); ftpsendf(conn->firstsocket, conn, "STOR %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -1347,7 +1348,7 @@ again:;
} }
if(data->bits.ftp_use_port) { if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock); result = AllowServerConnect(data, conn, portsock);
if( result ) if( result )
return result; return result;
} }
@ -1360,7 +1361,7 @@ again:;
Curl_pgrsSetUploadSize(data, data->infilesize); Curl_pgrsSetUploadSize(data, data->infilesize);
result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */ result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */
data->secondarysocket, bytecountp); conn->secondarysocket, bytecountp);
if(result) if(result)
return result; return result;
@ -1414,9 +1415,9 @@ again:;
dirlist = TRUE; dirlist = TRUE;
/* Set type to ASCII */ /* Set type to ASCII */
ftpsendf(data->firstsocket, conn, "TYPE A"); ftpsendf(conn->firstsocket, conn, "TYPE A");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -1429,16 +1430,16 @@ again:;
better used since the LIST command output is not specified or better used since the LIST command output is not specified or
standard in any way */ standard in any way */
ftpsendf(data->firstsocket, conn, "%s", ftpsendf(conn->firstsocket, conn, "%s",
data->customrequest?data->customrequest: data->customrequest?data->customrequest:
(data->bits.ftp_list_only?"NLST":"LIST")); (data->bits.ftp_list_only?"NLST":"LIST"));
} }
else { else {
/* Set type to binary (unless specified ASCII) */ /* Set type to binary (unless specified ASCII) */
ftpsendf(data->firstsocket, conn, "TYPE %s", ftpsendf(conn->firstsocket, conn, "TYPE %s",
(data->bits.ftp_ascii)?"A":"I"); (data->bits.ftp_ascii)?"A":"I");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -1457,9 +1458,9 @@ again:;
* of the file we're gonna get. If we can get the size, this is by far * of the file we're gonna get. If we can get the size, this is by far
* the best way to know if we're trying to resume beyond the EOF. */ * the best way to know if we're trying to resume beyond the EOF. */
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file); ftpsendf(conn->firstsocket, conn, "SIZE %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -1501,9 +1502,9 @@ again:;
infof(data, "Instructs server to resume from offset %d\n", infof(data, "Instructs server to resume from offset %d\n",
data->resume_from); data->resume_from);
ftpsendf(data->firstsocket, conn, "REST %d", data->resume_from); ftpsendf(conn->firstsocket, conn, "REST %d", data->resume_from);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -1513,10 +1514,10 @@ again:;
} }
} }
ftpsendf(data->firstsocket, conn, "RETR %s", ftp->file); ftpsendf(conn->firstsocket, conn, "RETR %s", ftp->file);
} }
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@ -1580,7 +1581,7 @@ again:;
size = downloadsize; size = downloadsize;
if(data->bits.ftp_use_port) { if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock); result = AllowServerConnect(data, conn, portsock);
if( result ) if( result )
return result; return result;
} }
@ -1588,7 +1589,7 @@ again:;
infof(data, "Getting file with size: %d\n", size); infof(data, "Getting file with size: %d\n", size);
/* FTP download: */ /* FTP download: */
result=Curl_Transfer(conn, data->secondarysocket, size, FALSE, result=Curl_Transfer(conn, conn->secondarysocket, size, FALSE,
bytecountp, bytecountp,
-1, NULL); /* no upload here */ -1, NULL); /* no upload here */
if(result) if(result)
@ -1617,7 +1618,7 @@ CURLcode Curl_ftp(struct connectdata *conn)
int dirlength=0; /* 0 forces strlen() */ int dirlength=0; /* 0 forces strlen() */
/* the ftp struct is already inited in ftp_connect() */ /* the ftp struct is already inited in ftp_connect() */
ftp = data->proto.ftp; ftp = conn->proto.ftp;
/* We split the path into dir and file parts *before* we URLdecode /* We split the path into dir and file parts *before* we URLdecode
it */ it */

View File

@ -325,21 +325,21 @@ CURLcode Curl_http_connect(struct connectdata *conn)
if (conn->protocol & PROT_HTTPS) { if (conn->protocol & PROT_HTTPS) {
if (data->bits.httpproxy) { if (data->bits.httpproxy) {
/* HTTPS through a proxy can only be done with a tunnel */ /* HTTPS through a proxy can only be done with a tunnel */
result = Curl_ConnectHTTPProxyTunnel(conn, data->firstsocket, result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket,
data->hostname, data->remote_port); conn->hostname, conn->remote_port);
if(CURLE_OK != result) if(CURLE_OK != result)
return result; return result;
} }
/* now, perform the SSL initialization for this socket */ /* now, perform the SSL initialization for this socket */
if(Curl_SSLConnect(data)) if(Curl_SSLConnect(conn))
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
if(data->bits.user_passwd && !data->bits.this_is_a_follow) { if(data->bits.user_passwd && !data->bits.this_is_a_follow) {
/* Authorization: is requested, this is not a followed location, get the /* Authorization: is requested, this is not a followed location, get the
original host name */ original host name */
data->auth_host = strdup(data->hostname); data->auth_host = strdup(conn->hostname);
} }
return CURLE_OK; return CURLE_OK;
@ -361,7 +361,7 @@ CURLcode Curl_http_done(struct connectdata *conn)
struct HTTP *http; struct HTTP *http;
data=conn->data; data=conn->data;
http=data->proto.http; http=conn->proto.http;
if(data->bits.http_formpost) { if(data->bits.http_formpost) {
*bytecount = http->readbytecount + http->writebytecount; *bytecount = http->readbytecount + http->writebytecount;
@ -394,7 +394,7 @@ CURLcode Curl_http(struct connectdata *conn)
if(!http) if(!http)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
memset(http, 0, sizeof(struct HTTP)); memset(http, 0, sizeof(struct HTTP));
data->proto.http = http; conn->proto.http = http;
if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
data->bits.upload) { data->bits.upload) {
@ -417,7 +417,7 @@ CURLcode Curl_http(struct connectdata *conn)
host due to a location-follow, we do some weirdo checks here */ host due to a location-follow, we do some weirdo checks here */
if(!data->bits.this_is_a_follow || if(!data->bits.this_is_a_follow ||
!data->auth_host || !data->auth_host ||
strequal(data->auth_host, data->hostname)) { strequal(data->auth_host, conn->hostname)) {
sprintf(data->buffer, "%s:%s", data->user, data->passwd); sprintf(data->buffer, "%s:%s", data->user, data->passwd);
if(Curl_base64_encode(data->buffer, strlen(data->buffer), if(Curl_base64_encode(data->buffer, strlen(data->buffer),
&authorization) >= 0) { &authorization) >= 0) {
@ -690,10 +690,10 @@ CURLcode Curl_http(struct connectdata *conn)
Curl_pgrsSetUploadSize(data, http->postsize); Curl_pgrsSetUploadSize(data, http->postsize);
data->request_size = data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer); add_buffer_send(conn->firstsocket, conn, req_buffer);
result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->readbytecount, &http->readbytecount,
data->firstsocket, conn->firstsocket,
&http->writebytecount); &http->writebytecount);
if(result) { if(result) {
Curl_FormFree(http->sendit); /* free that whole lot */ Curl_FormFree(http->sendit); /* free that whole lot */
@ -716,12 +716,12 @@ CURLcode Curl_http(struct connectdata *conn)
/* this sends the buffer and frees all the buffer resources */ /* this sends the buffer and frees all the buffer resources */
data->request_size = data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer); add_buffer_send(conn->firstsocket, conn, req_buffer);
/* prepare for transfer */ /* prepare for transfer */
result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->readbytecount, &http->readbytecount,
data->firstsocket, conn->firstsocket,
&http->writebytecount); &http->writebytecount);
if(result) if(result)
return result; return result;
@ -762,10 +762,10 @@ CURLcode Curl_http(struct connectdata *conn)
/* issue the request */ /* issue the request */
data->request_size = data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer); add_buffer_send(conn->firstsocket, conn, req_buffer);
/* HTTP GET/HEAD download: */ /* HTTP GET/HEAD download: */
result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, bytecount, result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount,
-1, NULL); /* nothing to upload */ -1, NULL); /* nothing to upload */
} }
if(result) if(result)

View File

@ -290,7 +290,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
size_t nread; size_t nread;
int l = sizeof(local_addr); int l = sizeof(local_addr);
if(getsockname(conn->data->firstsocket, if(getsockname(conn->firstsocket,
(struct sockaddr *)LOCAL_ADDR, &l) < 0) (struct sockaddr *)LOCAL_ADDR, &l) < 0)
perror("getsockname()"); perror("getsockname()");
@ -339,9 +339,9 @@ krb4_auth(void *app_data, struct connectdata *conn)
return AUTH_CONTINUE; return AUTH_CONTINUE;
} }
/*ret = command("ADAT %s", p)*/ /*ret = command("ADAT %s", p)*/
Curl_ftpsendf(conn->data->firstsocket, conn, "ADAT %s", p); Curl_ftpsendf(conn->firstsocket, conn, "ADAT %s", p);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL); conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return /*CURLE_OPERATION_TIMEOUTED*/-1;
@ -409,10 +409,10 @@ void krb_kauth(struct connectdata *conn)
save = set_command_prot(conn, prot_private); save = set_command_prot(conn, prot_private);
/*ret = command("SITE KAUTH %s", name);***/ /*ret = command("SITE KAUTH %s", name);***/
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"SITE KAUTH %s", conn->data->user); "SITE KAUTH %s", conn->data->user);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, conn->data->buffer, nread = Curl_GetFTPResponse(conn->firstsocket, conn->data->buffer,
conn, NULL); conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/; return /*CURLE_OPERATION_TIMEOUTED*/;
@ -486,10 +486,10 @@ void krb_kauth(struct connectdata *conn)
} }
memset (tktcopy.dat, 0, tktcopy.length); memset (tktcopy.dat, 0, tktcopy.length);
/*ret = command("SITE KAUTH %s %s", name, p);***/ /*ret = command("SITE KAUTH %s %s", name, p);***/
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"SITE KAUTH %s %s", name, p); "SITE KAUTH %s %s", name, p);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, conn->data->buffer, nread = Curl_GetFTPResponse(conn->firstsocket, conn->data->buffer,
conn, NULL); conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/; return /*CURLE_OPERATION_TIMEOUTED*/;

View File

@ -171,10 +171,10 @@ CURLcode Curl_ldap(struct connectdata *conn)
DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long), ldap_entry2text); DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long), ldap_entry2text);
DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long, char *, char *), ldap_entry2html); DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long, char *, char *), ldap_entry2html);
server = ldap_open(data->hostname, data->port); server = ldap_open(conn->hostname, conn->port);
if (server == NULL) { if (server == NULL) {
failf(data, "LDAP: Cannot connect to %s:%d", failf(data, "LDAP: Cannot connect to %s:%d",
data->hostname, data->port); conn->hostname, conn->port);
status = CURLE_COULDNT_CONNECT; status = CURLE_COULDNT_CONNECT;
} else { } else {
rc = ldap_simple_bind_s(server, data->user, data->passwd); rc = ldap_simple_bind_s(server, data->user, data->passwd);

View File

@ -482,10 +482,10 @@ sec_prot_internal(struct connectdata *conn, int level)
} }
if(level){ if(level){
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"PBSZ %u", s); "PBSZ %u", s);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL); conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return /*CURLE_OPERATION_TIMEOUTED*/-1;
@ -501,10 +501,10 @@ sec_prot_internal(struct connectdata *conn, int level)
conn->buffer_size = s; conn->buffer_size = s;
} }
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"PROT %c", level["CSEP"]); "PROT %c", level["CSEP"]);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL); conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return /*CURLE_OPERATION_TIMEOUTED*/-1;
@ -610,10 +610,10 @@ sec_login(struct connectdata *conn)
} }
infof(data, "Trying %s...\n", (*m)->name); infof(data, "Trying %s...\n", (*m)->name);
/*ret = command("AUTH %s", (*m)->name);***/ /*ret = command("AUTH %s", (*m)->name);***/
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"AUTH %s", (*m)->name); "AUTH %s", (*m)->name);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL); conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return /*CURLE_OPERATION_TIMEOUTED*/-1;

View File

@ -111,15 +111,14 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
size_t *written) size_t *written)
{ {
size_t bytes_written; size_t bytes_written;
struct UrlData *data=conn->data; /* conn knows data, not vice versa */
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
if (data->ssl.use) { if (conn->ssl.use) {
int loop=100; /* just a precaution to never loop endlessly */ int loop=100; /* just a precaution to never loop endlessly */
while(loop--) { while(loop--) {
bytes_written = SSL_write(data->ssl.handle, mem, len); bytes_written = SSL_write(conn->ssl.handle, mem, len);
if((-1 != bytes_written) || if((-1 != bytes_written) ||
(SSL_ERROR_WANT_WRITE != SSL_get_error(data->ssl.handle, (SSL_ERROR_WANT_WRITE != SSL_get_error(conn->ssl.handle,
bytes_written) )) bytes_written) ))
break; break;
} }
@ -200,16 +199,15 @@ CURLcode Curl_read(struct connectdata *conn, int sockfd,
char *buf, size_t buffersize, char *buf, size_t buffersize,
ssize_t *n) ssize_t *n)
{ {
struct UrlData *data = conn->data;
ssize_t nread; ssize_t nread;
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
if (data->ssl.use) { if (conn->ssl.use) {
int loop=100; /* just a precaution to never loop endlessly */ int loop=100; /* just a precaution to never loop endlessly */
while(loop--) { while(loop--) {
nread = SSL_read(data->ssl.handle, buf, buffersize); nread = SSL_read(conn->ssl.handle, buf, buffersize);
if((-1 != nread) || if((-1 != nread) ||
(SSL_ERROR_WANT_READ != SSL_get_error(data->ssl.handle, nread) )) (SSL_ERROR_WANT_READ != SSL_get_error(conn->ssl.handle, nread) ))
break; break;
} }
} }

View File

@ -64,6 +64,7 @@ static int passwd_callback(char *buf, int num, int verify
static static
int cert_stuff(struct UrlData *data, int cert_stuff(struct UrlData *data,
struct connectdata *conn,
char *cert_file, char *cert_file,
char *key_file) char *key_file)
{ {
@ -78,10 +79,10 @@ int cert_stuff(struct UrlData *data,
*/ */
strcpy(global_passwd, data->cert_passwd); strcpy(global_passwd, data->cert_passwd);
/* Set passwd callback: */ /* Set passwd callback: */
SSL_CTX_set_default_passwd_cb(data->ssl.ctx, passwd_callback); SSL_CTX_set_default_passwd_cb(conn->ssl.ctx, passwd_callback);
} }
if (SSL_CTX_use_certificate_file(data->ssl.ctx, if (SSL_CTX_use_certificate_file(conn->ssl.ctx,
cert_file, cert_file,
SSL_FILETYPE_PEM) <= 0) { SSL_FILETYPE_PEM) <= 0) {
failf(data, "unable to set certificate file (wrong password?)\n"); failf(data, "unable to set certificate file (wrong password?)\n");
@ -90,14 +91,14 @@ int cert_stuff(struct UrlData *data,
if (key_file == NULL) if (key_file == NULL)
key_file=cert_file; key_file=cert_file;
if (SSL_CTX_use_PrivateKey_file(data->ssl.ctx, if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx,
key_file, key_file,
SSL_FILETYPE_PEM) <= 0) { SSL_FILETYPE_PEM) <= 0) {
failf(data, "unable to set public key file\n"); failf(data, "unable to set public key file\n");
return(0); return(0);
} }
ssl=SSL_new(data->ssl.ctx); ssl=SSL_new(conn->ssl.ctx);
x509=SSL_get_certificate(ssl); x509=SSL_get_certificate(ssl);
if (x509 != NULL) if (x509 != NULL)
@ -111,7 +112,7 @@ int cert_stuff(struct UrlData *data,
/* Now we know that a key and cert have been set against /* Now we know that a key and cert have been set against
* the SSL context */ * the SSL context */
if (!SSL_CTX_check_private_key(data->ssl.ctx)) { if (!SSL_CTX_check_private_key(conn->ssl.ctx)) {
failf(data, "Private key does not match the certificate public key\n"); failf(data, "Private key does not match the certificate public key\n");
return(0); return(0);
} }
@ -141,22 +142,23 @@ int cert_verify_callback(int ok, X509_STORE_CTX *ctx)
/* ====================================================== */ /* ====================================================== */
int int
Curl_SSLConnect (struct UrlData *data) Curl_SSLConnect(struct connectdata *conn)
{ {
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
int err; struct UrlData *data = conn->data;
char * str; int err;
SSL_METHOD *req_method; char * str;
SSL_METHOD *req_method;
/* mark this is being ssl enabled from here on out. */ /* mark this is being ssl enabled from here on out. */
data->ssl.use = TRUE; conn->ssl.use = TRUE;
/* Lets get nice error messages */ /* Lets get nice error messages */
SSL_load_error_strings(); SSL_load_error_strings();
#ifdef HAVE_RAND_STATUS #ifdef HAVE_RAND_STATUS
/* RAND_status() was introduced in OpenSSL 0.9.5 */ /* RAND_status() was introduced in OpenSSL 0.9.5 */
if(0 == RAND_status()) if(0 == RAND_status())
#endif #endif
{ {
/* We need to seed the PRNG properly! */ /* We need to seed the PRNG properly! */
@ -177,116 +179,116 @@ Curl_SSLConnect (struct UrlData *data)
#endif #endif
} }
/* Setup all the global SSL stuff */ /* Setup all the global SSL stuff */
SSLeay_add_ssl_algorithms(); SSLeay_add_ssl_algorithms();
switch(data->ssl.version) { switch(data->ssl.version) {
default: default:
req_method = SSLv23_client_method(); req_method = SSLv23_client_method();
break; break;
case 2: case 2:
req_method = SSLv2_client_method(); req_method = SSLv2_client_method();
break; break;
case 3: case 3:
req_method = SSLv3_client_method(); req_method = SSLv3_client_method();
break; break;
} }
data->ssl.ctx = SSL_CTX_new(req_method); conn->ssl.ctx = SSL_CTX_new(req_method);
if(!data->ssl.ctx) { if(!conn->ssl.ctx) {
failf(data, "SSL: couldn't create a context!"); failf(data, "SSL: couldn't create a context!");
return 1; return 1;
} }
if(data->cert) { if(data->cert) {
if (!cert_stuff(data, data->cert, data->cert)) { if (!cert_stuff(data, conn, data->cert, data->cert)) {
failf(data, "couldn't use certificate!\n"); failf(data, "couldn't use certificate!\n");
return 2; return 2;
}
} }
}
if(data->ssl.verifypeer){ if(data->ssl.verifypeer){
SSL_CTX_set_verify(data->ssl.ctx, SSL_CTX_set_verify(conn->ssl.ctx,
SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT| SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
SSL_VERIFY_CLIENT_ONCE, SSL_VERIFY_CLIENT_ONCE,
cert_verify_callback); cert_verify_callback);
if (!SSL_CTX_load_verify_locations(data->ssl.ctx, if (!SSL_CTX_load_verify_locations(conn->ssl.ctx,
data->ssl.CAfile, data->ssl.CAfile,
data->ssl.CApath)) { data->ssl.CApath)) {
failf(data,"error setting cerficate verify locations\n"); failf(data,"error setting cerficate verify locations\n");
return 2; return 2;
}
} }
else }
SSL_CTX_set_verify(data->ssl.ctx, SSL_VERIFY_NONE, cert_verify_callback); else
SSL_CTX_set_verify(conn->ssl.ctx, SSL_VERIFY_NONE, cert_verify_callback);
/* Lets make an SSL structure */ /* Lets make an SSL structure */
data->ssl.handle = SSL_new (data->ssl.ctx); conn->ssl.handle = SSL_new (conn->ssl.ctx);
SSL_set_connect_state (data->ssl.handle); SSL_set_connect_state (conn->ssl.handle);
data->ssl.server_cert = 0x0; conn->ssl.server_cert = 0x0;
/* pass the raw socket into the SSL layers */ /* pass the raw socket into the SSL layers */
SSL_set_fd (data->ssl.handle, data->firstsocket); SSL_set_fd (conn->ssl.handle, conn->firstsocket);
err = SSL_connect (data->ssl.handle); err = SSL_connect (conn->ssl.handle);
if (-1 == err) { if (-1 == err) {
err = ERR_get_error(); err = ERR_get_error();
failf(data, "SSL: %s", ERR_error_string(err, NULL)); failf(data, "SSL: %s", ERR_error_string(err, NULL));
return 10; return 10;
} }
/* Informational message */ /* Informational message */
infof (data, "SSL connection using %s\n", infof (data, "SSL connection using %s\n",
SSL_get_cipher(data->ssl.handle)); SSL_get_cipher(conn->ssl.handle));
/* Get server's certificate (note: beware of dynamic allocation) - opt */ /* Get server's certificate (note: beware of dynamic allocation) - opt */
/* major serious hack alert -- we should check certificates /* major serious hack alert -- we should check certificates
* to authenticate the server; otherwise we risk man-in-the-middle * to authenticate the server; otherwise we risk man-in-the-middle
* attack * attack
*/ */
data->ssl.server_cert = SSL_get_peer_certificate (data->ssl.handle); conn->ssl.server_cert = SSL_get_peer_certificate (conn->ssl.handle);
if(!data->ssl.server_cert) { if(!conn->ssl.server_cert) {
failf(data, "SSL: couldn't get peer certificate!"); failf(data, "SSL: couldn't get peer certificate!");
return 3; return 3;
} }
infof (data, "Server certificate:\n"); infof (data, "Server certificate:\n");
str = X509_NAME_oneline (X509_get_subject_name (data->ssl.server_cert), str = X509_NAME_oneline (X509_get_subject_name (conn->ssl.server_cert),
NULL, 0); NULL, 0);
if(!str) { if(!str) {
failf(data, "SSL: couldn't get X509-subject!"); failf(data, "SSL: couldn't get X509-subject!");
return 4; return 4;
} }
infof(data, "\t subject: %s\n", str); infof(data, "\t subject: %s\n", str);
CRYPTO_free(str); CRYPTO_free(str);
str = X509_NAME_oneline (X509_get_issuer_name (data->ssl.server_cert), str = X509_NAME_oneline (X509_get_issuer_name (conn->ssl.server_cert),
NULL, 0); NULL, 0);
if(!str) { if(!str) {
failf(data, "SSL: couldn't get X509-issuer name!"); failf(data, "SSL: couldn't get X509-issuer name!");
return 5; return 5;
} }
infof(data, "\t issuer: %s\n", str); infof(data, "\t issuer: %s\n", str);
CRYPTO_free(str); CRYPTO_free(str);
/* We could do all sorts of certificate verification stuff here before /* We could do all sorts of certificate verification stuff here before
deallocating the certificate. */ deallocating the certificate. */
if(data->ssl.verifypeer) { if(data->ssl.verifypeer) {
data->ssl.certverifyresult=SSL_get_verify_result(data->ssl.handle); data->ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle);
infof(data, "Verify result: %d\n", data->ssl.certverifyresult); infof(data, "Verify result: %d\n", data->ssl.certverifyresult);
} }
else else
data->ssl.certverifyresult=0; data->ssl.certverifyresult=0;
X509_free(data->ssl.server_cert); X509_free(conn->ssl.server_cert);
#else /* USE_SSLEAY */ #else /* USE_SSLEAY */
/* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */ /* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
(void) data; (void) data;
#endif #endif
return 0; return 0;
} }

View File

@ -22,5 +22,6 @@
* *
* $Id$ * $Id$
*****************************************************************************/ *****************************************************************************/
int Curl_SSLConnect (struct UrlData *data); #include "urldata.h"
int Curl_SSLConnect(struct connectdata *conn);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -366,6 +366,16 @@ _Transfer(struct connectdata *c_conn)
if (strnequal("Content-Length", p, 14) && if (strnequal("Content-Length", p, 14) &&
sscanf (p+14, ": %ld", &contentlength)) sscanf (p+14, ": %ld", &contentlength))
conn->size = contentlength; conn->size = contentlength;
else if (strnequal("Connection: close", p,
strlen("Connection: close"))) {
/*
* [RFC 2616, section 8.1.2.1]
* "Connection: close" is HTTP/1.1 language and means that
* the connection will close when this request has been
* served.
*/
conn->bits.close = TRUE; /* close when done */
}
else if (strnequal("Content-Range", p, 13)) { else if (strnequal("Content-Range", p, 13)) {
if (sscanf (p+13, ": bytes %d-", &offset) || if (sscanf (p+13, ": bytes %d-", &offset) ||
sscanf (p+13, ": bytes: %d-", &offset)) { sscanf (p+13, ": bytes: %d-", &offset)) {
@ -635,7 +645,9 @@ CURLcode curl_transfer(CURL *curl)
if (data->maxredirs && (data->followlocation >= data->maxredirs)) { if (data->maxredirs && (data->followlocation >= data->maxredirs)) {
failf(data,"Maximum (%d) redirects followed", data->maxredirs); failf(data,"Maximum (%d) redirects followed", data->maxredirs);
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect); curl_disconnect(c_connect);
#endif
res=CURLE_TOO_MANY_REDIRECTS; res=CURLE_TOO_MANY_REDIRECTS;
break; break;
} }
@ -772,11 +784,15 @@ CURLcode curl_transfer(CURL *curl)
*/ */
break; break;
} }
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect); curl_disconnect(c_connect);
#endif
continue; continue;
} }
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect); curl_disconnect(c_connect);
#endif
} }
break; /* it only reaches here when this shouldn't loop */ break; /* it only reaches here when this shouldn't loop */

851
lib/url.c

File diff suppressed because it is too large Load Diff

View File

@ -133,6 +133,61 @@ enum protection_level {
}; };
#endif #endif
/* struct for data related to SSL and SSL connections */
struct ssl_connect_data {
bool use; /* use ssl encrypted communications TRUE/FALSE */
#ifdef USE_SSLEAY
/* these ones requires specific SSL-types */
SSL_CTX* ctx;
SSL* handle;
X509* server_cert;
#endif /* USE_SSLEAY */
};
struct ssl_config_data {
long version; /* what version the client wants to use */
long certverifyresult; /* result from the certificate verification */
long verifypeer; /* set TRUE if this is desired */
char *CApath; /* DOES NOT WORK ON WINDOWS */
char *CAfile; /* cerficate to verify peer against */
};
/****************************************************************************
* HTTP unique setup
***************************************************************************/
struct HTTP {
struct FormData *sendit;
int postsize;
char *p_pragma; /* Pragma: string */
char *p_accept; /* Accept: string */
long readbytecount;
long writebytecount;
/* For FORM posting */
struct Form form;
size_t (*storefread)(char *, size_t , size_t , FILE *);
FILE *in;
};
/****************************************************************************
* FTP unique setup
***************************************************************************/
struct FTP {
long *bytecountp;
char *user; /* user name string */
char *passwd; /* password string */
char *urlpath; /* the originally given path part of the URL */
char *dir; /* decoded directory */
char *file; /* decoded file */
};
/*
* Boolean values that concerns this connection.
*/
struct ConnectBits {
bool close; /* if set, we close the connection after this request */
};
/* /*
* The connectdata struct contains all fields and variables that should be * The connectdata struct contains all fields and variables that should be
* unique for an entire connection. * unique for an entire connection.
@ -145,6 +200,9 @@ struct connectdata {
Handle handle; /* struct identifier */ Handle handle; /* struct identifier */
struct UrlData *data; /* link to the root CURL struct */ struct UrlData *data; /* link to the root CURL struct */
int connectindex; /* what index in the connects index this particular
struct has */
/**** curl_connect() phase fields */ /**** curl_connect() phase fields */
ConnState state; /* for state dependent actions */ ConnState state; /* for state dependent actions */
@ -166,17 +224,27 @@ struct connectdata {
struct hostent *hp; struct hostent *hp;
struct sockaddr_in serv_addr; struct sockaddr_in serv_addr;
#endif #endif
char proto[64]; /* store the protocol string in this buffer */ char protostr[64]; /* store the protocol string in this buffer */
char gname[257]; /* store the hostname in this buffer */ char gname[257]; /* store the hostname in this buffer */
char *name; /* host name pointer to fool around with */ char *name; /* host name pointer to fool around with */
char *path; /* allocated buffer to store the URL's path part in */ char *path; /* allocated buffer to store the URL's path part in */
char *hostname; /* hostname to connect, as parsed from url */
long port; /* which port to use locally */
unsigned short remote_port; /* what remote port to connect to,
not the proxy port! */
char *ppath; char *ppath;
long bytecount; long bytecount;
struct timeval now; /* current time */ struct timeval now; /* current time */
int firstsocket; /* the main socket to use */
int secondarysocket; /* for i.e ftp transfers */
long upload_bufsize; /* adjust as you see fit, never bigger than BUFSIZE long upload_bufsize; /* adjust as you see fit, never bigger than BUFSIZE
never smaller than UPLOAD_BUFSIZE */ never smaller than UPLOAD_BUFSIZE */
struct ssl_connect_data ssl; /* this is for ssl-stuff */
struct ConnectBits bits; /* various state-flags for this connection */
/* These two functions MUST be set by the curl_connect() function to be /* These two functions MUST be set by the curl_connect() function to be
be protocol dependent */ be protocol dependent */
CURLcode (*curl_do)(struct connectdata *connect); CURLcode (*curl_do)(struct connectdata *connect);
@ -205,6 +273,7 @@ struct connectdata {
the same we read from. -1 disables */ the same we read from. -1 disables */
long *writebytecountp; /* return number of bytes written or NULL */ long *writebytecountp; /* return number of bytes written or NULL */
#ifdef KRB4 #ifdef KRB4
enum protection_level command_prot; enum protection_level command_prot;
@ -218,6 +287,24 @@ struct connectdata {
void *app_data; void *app_data;
#endif #endif
/*************** Request - specific items ************/
/* previously this was in the urldata struct */
union {
struct HTTP *http;
struct HTTP *gopher; /* alias, just for the sake of being more readable */
struct HTTP *https; /* alias, just for the sake of being more readable */
struct FTP *ftp;
#if 0 /* no need for special ones for these: */
struct TELNET *telnet;
struct FILE *file;
struct LDAP *ldap;
struct DICT *dict;
#endif
void *generic;
} proto;
}; };
struct Progress { struct Progress {
@ -253,35 +340,6 @@ struct Progress {
int speeder_c; int speeder_c;
}; };
/****************************************************************************
* HTTP unique setup
***************************************************************************/
struct HTTP {
struct FormData *sendit;
int postsize;
char *p_pragma; /* Pragma: string */
char *p_accept; /* Accept: string */
long readbytecount;
long writebytecount;
/* For FORM posting */
struct Form form;
size_t (*storefread)(char *, size_t , size_t , FILE *);
FILE *in;
};
/****************************************************************************
* FTP unique setup
***************************************************************************/
struct FTP {
long *bytecountp;
char *user; /* user name string */
char *passwd; /* password string */
char *urlpath; /* the originally given path part of the URL */
char *dir; /* decoded directory */
char *file; /* decoded file */
};
typedef enum { typedef enum {
HTTPREQ_NONE, /* first in list */ HTTPREQ_NONE, /* first in list */
HTTPREQ_GET, HTTPREQ_GET,
@ -338,22 +396,6 @@ typedef enum {
CURLI_LAST CURLI_LAST
} CurlInterface; } CurlInterface;
/* struct for data related to SSL and SSL connections */
struct ssldata {
bool use; /* use ssl encrypted communications TRUE/FALSE */
long version; /* what version the client wants to use */
long certverifyresult; /* result from the certificate verification */
long verifypeer; /* set TRUE if this is desired */
char *CApath; /* DOES NOT WORK ON WINDOWS */
char *CAfile; /* cerficate to verify peer against */
#ifdef USE_SSLEAY
/* these ones requires specific SSL-types */
SSL_CTX* ctx;
SSL* handle;
X509* server_cert;
#endif /* USE_SSLEAY */
};
/* /*
* As of April 11, 2000 we're now trying to split up the urldata struct in * As of April 11, 2000 we're now trying to split up the urldata struct in
* three different parts: * three different parts:
@ -370,6 +412,9 @@ struct ssldata {
* 3 - Request-specific. Variables that are of interest for this particular * 3 - Request-specific. Variables that are of interest for this particular
* transfer being made right now. * transfer being made right now.
* *
* In Febrary 2001, this is being done stricter. The 'connectdata' struct
* MUST have all the connection oriented stuff as we may now have several
* simultaneous connections and connection structs in memory.
*/ */
struct UrlData { struct UrlData {
@ -381,7 +426,7 @@ struct UrlData {
char *errorbuffer; /* store failure messages in here */ char *errorbuffer; /* store failure messages in here */
/*************** Session - specific items ************/ /*************** Session - specific items ************/
char *proxy; /* if proxy, set it here, set CONF_PROXY to use this */ char *proxy; /* if proxy, set it here */
char *proxyuserpwd; /* Proxy <user:password>, if used */ char *proxyuserpwd; /* Proxy <user:password>, if used */
long proxyport; /* If non-zero, use this port number by default. If the long proxyport; /* If non-zero, use this port number by default. If the
proxy string features a ":[port]" that one will override proxy string features a ":[port]" that one will override
@ -391,33 +436,16 @@ struct UrlData {
long header_size; /* size of read header(s) in bytes */ long header_size; /* size of read header(s) in bytes */
long request_size; /* the amount of bytes sent in the request(s) */ long request_size; /* the amount of bytes sent in the request(s) */
/*************** Request - specific items ************/
union {
struct HTTP *http;
struct HTTP *gopher; /* alias, just for the sake of being more readable */
struct HTTP *https; /* alias, just for the sake of being more readable */
struct FTP *ftp;
#if 0 /* no need for special ones for these: */
struct TELNET *telnet;
struct FILE *file;
struct LDAP *ldap;
struct DICT *dict;
#endif
void *generic;
} proto;
FILE *out; /* the fetched file goes here */ FILE *out; /* the fetched file goes here */
FILE *in; /* the uploaded file is read from here */ FILE *in; /* the uploaded file is read from here */
FILE *writeheader; /* write the header to this is non-NULL */ FILE *writeheader; /* write the header to this is non-NULL */
char *url; /* what to get */ char *url; /* what to get */
char *freethis; /* if non-NULL, an allocated string for the URL */ char *freethis; /* if non-NULL, an allocated string for the URL */
char *hostname; /* hostname to connect, as parsed from url */ long port; /* which port to use (if non-protocol bind) */
long port; /* which port to use (if non-protocol bind) set
CONF_PORT to use this */
unsigned short remote_port; /* what remote port to connect to, not the proxy unsigned short remote_port; /* what remote port to connect to, not the proxy
port! */ port! */
struct Configbits bits; /* new-style (v7) flag data */ struct Configbits bits; /* new-style (v7) flag data */
struct ssl_config_data ssl; /* this is for ssl-stuff */
char *userpwd; /* <user:password>, if used */ char *userpwd; /* <user:password>, if used */
char *range; /* range, if used. See README for detailed specification on char *range; /* range, if used. See README for detailed specification on
@ -462,10 +490,6 @@ struct UrlData {
long maxdownload; /* in bytes, the maximum amount of data to fetch, 0 long maxdownload; /* in bytes, the maximum amount of data to fetch, 0
means unlimited */ means unlimited */
/* fields only set and used within _urlget() */
int firstsocket; /* the main socket to use */
int secondarysocket; /* for i.e ftp transfers */
char buffer[BUFSIZE+1]; /* buffer with size BUFSIZE */ char buffer[BUFSIZE+1]; /* buffer with size BUFSIZE */
double current_speed; /* the ProgressShow() funcion sets this */ double current_speed; /* the ProgressShow() funcion sets this */
@ -488,12 +512,13 @@ struct UrlData {
struct CookieInfo *cookies; struct CookieInfo *cookies;
struct ssldata ssl; /* this is for ssl-stuff */
long crlf; long crlf;
struct curl_slist *quote; /* before the transfer */ struct curl_slist *quote; /* before the transfer */
struct curl_slist *postquote; /* after the transfer */ struct curl_slist *postquote; /* after the transfer */
/* Telnet negotiation options */
struct curl_slist *telnet_options; /* linked list of telnet options */
TimeCond timecondition; /* kind of comparison */ TimeCond timecondition; /* kind of comparison */
time_t timevalue; /* what time to compare with */ time_t timevalue; /* what time to compare with */
@ -504,12 +529,6 @@ struct UrlData {
char *headerbuff; /* allocated buffer to store headers in */ char *headerbuff; /* allocated buffer to store headers in */
int headersize; /* size of the allocation */ int headersize; /* size of the allocation */
#if 0
/* this was removed in libcurl 7.4 */
char *writeinfo; /* if non-NULL describes what to output on a successful
completion */
#endif
struct Progress progress; /* for all the progress meter data */ struct Progress progress; /* for all the progress meter data */
#define MAX_CURL_USER_LENGTH 128 #define MAX_CURL_USER_LENGTH 128
@ -541,6 +560,13 @@ struct UrlData {
#endif #endif
struct timeval keeps_speed; /* this should be request-specific */ struct timeval keeps_speed; /* this should be request-specific */
/* 'connects' will be an allocated array with pointers. If the pointer is
set, it holds an allocated connection. */
struct connectdata **connects;
size_t numconnects; /* size of the 'connects' array */
curl_closepolicy closepolicy;
}; };
#define LIBCURL_NAME "libcurl" #define LIBCURL_NAME "libcurl"

View File

@ -102,16 +102,13 @@ typedef enum {
#define CONF_NOBODY (1<<11) /* use HEAD to get http document */ #define CONF_NOBODY (1<<11) /* use HEAD to get http document */
#define CONF_FAILONERROR (1<<12) /* no output on http error codes >= 300 */ #define CONF_FAILONERROR (1<<12) /* no output on http error codes >= 300 */
#define CONF_UPLOAD (1<<14) /* this is an upload */ #define CONF_UPLOAD (1<<14) /* this is an upload */
#define CONF_POST (1<<15) /* HTTP POST method */
#define CONF_FTPLISTONLY (1<<16) /* Use NLST when listing ftp dir */ #define CONF_FTPLISTONLY (1<<16) /* Use NLST when listing ftp dir */
#define CONF_FTPAPPEND (1<<20) /* Append instead of overwrite on upload! */ #define CONF_FTPAPPEND (1<<20) /* Append instead of overwrite on upload! */
#define CONF_NETRC (1<<22) /* read user+password from .netrc */ #define CONF_NETRC (1<<22) /* read user+password from .netrc */
#define CONF_FOLLOWLOCATION (1<<23) /* use Location: Luke! */ #define CONF_FOLLOWLOCATION (1<<23) /* use Location: Luke! */
#define CONF_GETTEXT (1<<24) /* use ASCII/text for transfer */ #define CONF_GETTEXT (1<<24) /* use ASCII/text for transfer */
#define CONF_HTTPPOST (1<<25) /* multipart/form-data HTTP POST */ #define CONF_HTTPPOST (1<<25) /* multipart/form-data HTTP POST */
#if 0
#define CONF_PUT (1<<27) /* PUT the input file */
#endif
#define CONF_MUTE (1<<28) /* force NOPROGRESS */ #define CONF_MUTE (1<<28) /* force NOPROGRESS */
#ifndef HAVE_STRDUP #ifndef HAVE_STRDUP
@ -279,6 +276,7 @@ static void help(void)
" -r/--range <range> Retrieve a byte range from a HTTP/1.1 or FTP server\n" " -r/--range <range> Retrieve a byte range from a HTTP/1.1 or FTP server\n"
" -s/--silent Silent mode. Don't output anything\n" " -s/--silent Silent mode. Don't output anything\n"
" -S/--show-error Show error. With -s, make curl show errors when they occur\n" " -S/--show-error Show error. With -s, make curl show errors when they occur\n"
" -t/--telnet-option <OPT=val> Set telnet option\n"
" -T/--upload-file <file> Transfer/upload <file> to remote site\n" " -T/--upload-file <file> Transfer/upload <file> to remote site\n"
" --url <URL> Another way to specify URL to work with\n" " --url <URL> Another way to specify URL to work with\n"
" -u/--user <user[:password]> Specify user and password to use\n" " -u/--user <user[:password]> Specify user and password to use\n"
@ -366,6 +364,8 @@ struct Configurable {
struct HttpPost *httppost; struct HttpPost *httppost;
struct HttpPost *last_post; struct HttpPost *last_post;
struct curl_slist *telnet_options;
HttpReq httpreq; HttpReq httpreq;
}; };
@ -565,7 +565,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"r", "range", TRUE}, {"r", "range", TRUE},
{"s", "silent", FALSE}, {"s", "silent", FALSE},
{"S", "show-error", FALSE}, {"S", "show-error", FALSE},
{"t", "upload", FALSE}, {"t", "telnet-options", TRUE},
{"T", "upload-file", TRUE}, {"T", "upload-file", TRUE},
{"u", "user", TRUE}, {"u", "user", TRUE},
{"U", "proxy-user", TRUE}, {"U", "proxy-user", TRUE},
@ -785,8 +785,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
else else
config->postfields=postdata; config->postfields=postdata;
} }
if(config->postfields)
config->conf |= CONF_POST;
if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq)) if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq))
return PARAM_BAD_USE; return PARAM_BAD_USE;
break; break;
@ -959,9 +958,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
config->showerror ^= TRUE; /* toggle on if used with -s */ config->showerror ^= TRUE; /* toggle on if used with -s */
break; break;
case 't': case 't':
/* we are uploading */ /* Telnet options */
config->conf ^= CONF_UPLOAD; config->telnet_options = curl_slist_append(config->telnet_options, nextarg);
fprintf(stderr, "-t is a deprecated switch, use '-T -' instead!\n");
break; break;
case 'T': case 'T':
/* we are uploading */ /* we are uploading */
@ -1743,7 +1741,6 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_FAILONERROR, curl_easy_setopt(curl, CURLOPT_FAILONERROR,
config->conf&CONF_FAILONERROR); config->conf&CONF_FAILONERROR);
curl_easy_setopt(curl, CURLOPT_UPLOAD, config->conf&CONF_UPLOAD); curl_easy_setopt(curl, CURLOPT_UPLOAD, config->conf&CONF_UPLOAD);
curl_easy_setopt(curl, CURLOPT_POST, config->conf&CONF_POST);
curl_easy_setopt(curl, CURLOPT_FTPLISTONLY, curl_easy_setopt(curl, CURLOPT_FTPLISTONLY,
config->conf&CONF_FTPLISTONLY); config->conf&CONF_FTPLISTONLY);
curl_easy_setopt(curl, CURLOPT_FTPAPPEND, config->conf&CONF_FTPAPPEND); curl_easy_setopt(curl, CURLOPT_FTPAPPEND, config->conf&CONF_FTPAPPEND);
@ -1751,9 +1748,6 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,
config->conf&CONF_FOLLOWLOCATION); config->conf&CONF_FOLLOWLOCATION);
curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, config->conf&CONF_GETTEXT); curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, config->conf&CONF_GETTEXT);
#if 0
curl_easy_setopt(curl, CURLOPT_PUT, config->conf&CONF_PUT);
#endif
curl_easy_setopt(curl, CURLOPT_MUTE, config->conf&CONF_MUTE); curl_easy_setopt(curl, CURLOPT_MUTE, config->conf&CONF_MUTE);
curl_easy_setopt(curl, CURLOPT_USERPWD, config->userpwd); curl_easy_setopt(curl, CURLOPT_USERPWD, config->userpwd);
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd); curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
@ -1824,6 +1818,9 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar);
} }
/* new in libcurl 7.6.2: */
curl_easy_setopt(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
res = curl_easy_perform(curl); res = curl_easy_perform(curl);
if(config->writeout) { if(config->writeout) {

View File

@ -1,3 +1,3 @@
#define CURL_NAME "curl" #define CURL_NAME "curl"
#define CURL_VERSION "7.6.1" #define CURL_VERSION "7.7-alpha1"
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") " #define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "

View File

@ -2,5 +2,6 @@ HTTP/1.1 301 This is a weirdo text message
Date: Thu, 09 Nov 2010 14:49:00 GMT Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake Server: test-server/fake
Location: data/110002.txt?coolsite=yes Location: data/110002.txt?coolsite=yes
Connection: close
This server reply is for testing a simple Location: following This server reply is for testing a simple Location: following