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
** 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
Daniel (9 February 2001)

View File

@ -20,6 +20,7 @@ Misc
- compiles on win32
- redirectable stderr
- use selected network interface for outgoing traffic
- IPv6 support
HTTP
- GET
@ -28,7 +29,7 @@ HTTP
- POST
- multipart POST
- authentication
- resume
- resume (both GET and PUT)
- follow redirects
- maximum amount of redirects to follow
- 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.
If this option is used twice, the second will again disable show error.
.IP "-t/--upload"
.B Deprecated. Use '-T -' instead.
Transfer the stdin data to the specified file. Curl will read
everything from stdin until EOF and store with the supplied name. If
this is used on a http(s) server, the PUT command will be used.
.IP "-t/--telnet-option <OPT=val>"
Pass options to the telnet protocol. Supported options are:
TTYPE=<term> Sets the terminal type.
XDISPLOC=<X display> Sets the X display location.
NEW_ENV=<var,val> Sets an environment variable.
.IP "-T/--upload-file <file>"
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
@ -758,7 +761,7 @@ If you do find bugs, mail them to curl-bug@haxx.se.
- Lars J. Aas <larsa@sim.no>
- Jörn Hartroth <Joern.Hartroth@computer.org>
- Matthew Clarke <clamat@van.maves.ca>
- Linus Nielsen <Linus.Nielsen@haxx.se>
- Linus Nielsen Feltzing <linus@haxx.se>
- Felix von Leitner <felix@convergence.de>
- Dan Zitter <dzitter@zitter.net>
- 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_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
} CURLcode;
@ -406,6 +409,9 @@ typedef enum {
document! Pass a NULL to shut it off. */
CINIT(FILETIME, OBJECTPOINT, 69),
/* This points to a linked list of telnet options */
CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
CURLOPT_LASTENTRY /* the last unusued */
} CURLoption;
@ -452,8 +458,8 @@ char *curl_getenv(char *variable);
char *curl_version(void);
/* This is the version number */
#define LIBCURL_VERSION "7.6.1"
#define LIBCURL_VERSION_NUM 0x070601
#define LIBCURL_VERSION "7.7-alpha1"
#define LIBCURL_VERSION_NUM 0x070000
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
struct curl_slist {
@ -520,6 +526,20 @@ typedef enum {
*/
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
}
#endif

View File

@ -141,7 +141,7 @@ CURLcode Curl_dict(struct connectdata *conn)
nth = atoi(nthdef);
}
Curl_sendf(data->firstsocket, conn,
Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"MATCH "
"%s " /* database */
@ -154,7 +154,7 @@ CURLcode Curl_dict(struct connectdata *conn)
word
);
result = Curl_Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */
if(result)
@ -191,7 +191,7 @@ CURLcode Curl_dict(struct connectdata *conn)
nth = atoi(nthdef);
}
Curl_sendf(data->firstsocket, conn,
Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"DEFINE "
"%s " /* database */
@ -202,7 +202,7 @@ CURLcode Curl_dict(struct connectdata *conn)
word
);
result = Curl_Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */
if(result)
@ -220,13 +220,13 @@ CURLcode Curl_dict(struct connectdata *conn)
if (ppath[i] == ':')
ppath[i] = ' ';
}
Curl_sendf(data->firstsocket, conn,
Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"%s\n"
"QUIT\n",
ppath);
result = Curl_Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL);
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,
struct connectdata *conn,
int sock)
{
fd_set rdset;
@ -199,7 +200,7 @@ static CURLcode AllowServerConnect(struct UrlData *data,
}
infof(data, "Connection accepted from server\n");
data->secondarysocket = s;
conn->secondarysocket = s;
}
break;
}
@ -362,7 +363,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY;
memset(ftp, 0, sizeof(struct FTP));
data->proto.ftp = ftp;
conn->proto.ftp = ftp;
/* get some initial data into the ftp struct */
ftp->bytecountp = &conn->bytecount;
@ -371,14 +372,14 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
if (data->bits.tunnel_thru_httpproxy) {
/* We want "seamless" FTP operations through HTTP proxy tunnel */
result = Curl_ConnectHTTPProxyTunnel(conn, data->firstsocket,
data->hostname, data->remote_port);
result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket,
conn->hostname, conn->remote_port);
if(CURLE_OK != result)
return result;
}
/* 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)
return CURLE_OPERATION_TIMEOUTED;
@ -398,7 +399,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
set a valid 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)
infof(data, "Logging in with password in cleartext!\n");
@ -408,10 +409,10 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
#endif
/* send USER */
ftpsendf(data->firstsocket, conn, "USER %s", ftp->user);
ftpsendf(conn->firstsocket, conn, "USER %s", ftp->user);
/* wait for feedback */
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@ -424,8 +425,8 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
else if(ftpcode == 331) {
/* 331 Password required for ...
(the server requires to send the user's password too) */
ftpsendf(data->firstsocket, conn, "PASS %s", ftp->passwd);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
ftpsendf(conn->firstsocket, conn, "PASS %s", ftp->passwd);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@ -477,7 +478,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
CURLcode Curl_ftp_done(struct connectdata *conn)
{
struct UrlData *data = conn->data;
struct FTP *ftp = data->proto.ftp;
struct FTP *ftp = conn->proto.ftp;
size_t nread;
char *buf = data->buffer; /* this is our buffer */
struct curl_slist *qitem; /* QUOTE item */
@ -502,16 +503,16 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
}
}
#ifdef KRB4
sec_fflush_fd(conn, data->secondarysocket);
sec_fflush_fd(conn, conn->secondarysocket);
#endif
/* shut down the socket to inform the server we're done */
sclose(data->secondarysocket);
data->secondarysocket = -1;
sclose(conn->secondarysocket);
conn->secondarysocket = -1;
if(!data->bits.no_body) {
/* now let's see what the server says about the transfer we
just performed: */
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@ -529,9 +530,9 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
while (qitem) {
/* Send string */
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)
return CURLE_OPERATION_TIMEOUTED;
@ -571,7 +572,7 @@ CURLcode _ftp(struct connectdata *conn)
struct curl_slist *qitem; /* QUOTE item */
/* 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;
int ftpcode; /* for ftp status */
@ -583,9 +584,9 @@ CURLcode _ftp(struct connectdata *conn)
while (qitem) {
/* Send string */
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)
return CURLE_OPERATION_TIMEOUTED;
@ -601,8 +602,8 @@ CURLcode _ftp(struct connectdata *conn)
/* change directory first! */
if(ftp->dir && ftp->dir[0]) {
ftpsendf(data->firstsocket, conn, "CWD %s", ftp->dir);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
ftpsendf(conn->firstsocket, conn, "CWD %s", ftp->dir);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@ -615,9 +616,9 @@ CURLcode _ftp(struct connectdata *conn)
if(data->bits.get_filetime && ftp->file) {
/* 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 */
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)
return CURLE_OPERATION_TIMEOUTED;
@ -651,10 +652,10 @@ CURLcode _ftp(struct connectdata *conn)
/* Some servers return different sizes for different modes, and thus we
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");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@ -665,9 +666,9 @@ CURLcode _ftp(struct connectdata *conn)
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)
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.
*/
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;
if (getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL, 0,
@ -819,7 +820,7 @@ CURLcode _ftp(struct connectdata *conn)
if (q)
*q = '\0';
}
ftpsendf(data->firstsocket, conn, "%s |%d|%s|%s|", *modep, eprtaf,
ftpsendf(conn->firstsocket, conn, "%s |%d|%s|%s|", *modep, eprtaf,
portmsgbuf, tmp);
} else if (strcmp(*modep, "LPRT") == 0 || strcmp(*modep, "PORT") == 0) {
int i;
@ -856,10 +857,10 @@ CURLcode _ftp(struct connectdata *conn)
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)
return CURLE_OPERATION_TIMEOUTED;
@ -909,7 +910,7 @@ again:;
/* we set the secondary socket variable to this for now, it
is only so that the cleanup function will close it in case
we fail before the true secondary stuff is made */
data->secondarysocket = portsock;
conn->secondarysocket = portsock;
memset((char *)&sa, 0, sizeof(sa));
memcpy((char *)&sa.sin_addr,
@ -971,13 +972,13 @@ again:;
sscanf( inet_ntoa(in), "%hu.%hu.%hu.%hu",
&ip[0], &ip[1], &ip[2], &ip[3]);
#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],
porttouse >> 8,
porttouse & 255);
}
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@ -998,8 +999,8 @@ again:;
int modeoff;
for (modeoff = 0; mode[modeoff]; modeoff++) {
ftpsendf(data->firstsocket, conn, mode[modeoff]);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
ftpsendf(conn->firstsocket, conn, mode[modeoff]);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@ -1081,15 +1082,15 @@ again:;
}
#ifdef ENABLE_IPV6
data->secondarysocket = -1;
conn->secondarysocket = -1;
for (ai = res; ai; ai = ai->ai_next) {
/* XXX for now, we can do IPv4 only */
if (ai->ai_family != AF_INET)
continue;
data->secondarysocket = socket(ai->ai_family, ai->ai_socktype,
conn->secondarysocket = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol);
if (data->secondarysocket < 0)
if (conn->secondarysocket < 0)
continue;
if(data->bits.verbose) {
@ -1114,21 +1115,21 @@ again:;
}
}
if (connect(data->secondarysocket, ai->ai_addr, ai->ai_addrlen) < 0) {
close(data->secondarysocket);
data->secondarysocket = -1;
if (connect(conn->secondarysocket, ai->ai_addr, ai->ai_addrlen) < 0) {
close(conn->secondarysocket);
conn->secondarysocket = -1;
continue;
}
break;
}
if (data->secondarysocket < 0) {
if (conn->secondarysocket < 0) {
failf(data, strerror(errno));
return CURLE_FTP_CANT_RECONNECT;
}
#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));
memcpy((char *)&(serv_addr.sin_addr), he->h_addr, he->h_length);
@ -1202,7 +1203,7 @@ again:;
if(hostdataptr)
free(hostdataptr);
if (connect(data->secondarysocket, (struct sockaddr *) &serv_addr,
if (connect(conn->secondarysocket, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0) {
switch(errno) {
#ifdef ECONNREFUSED
@ -1226,7 +1227,7 @@ again:;
if (data->bits.tunnel_thru_httpproxy) {
/* We want "seamless" FTP operations through HTTP proxy tunnel */
result = Curl_ConnectHTTPProxyTunnel(conn, data->secondarysocket,
result = Curl_ConnectHTTPProxyTunnel(conn, conn->secondarysocket,
newhost, newport);
if(CURLE_OK != result)
return result;
@ -1241,10 +1242,10 @@ again:;
if(data->bits.upload) {
/* 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");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@ -1273,9 +1274,9 @@ again:;
/* we could've got a specified offset from the command line,
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)
return CURLE_OPERATION_TIMEOUTED;
@ -1332,11 +1333,11 @@ again:;
/* Send everything on data->in to the socket */
if(data->bits.ftp_append)
/* 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
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)
return CURLE_OPERATION_TIMEOUTED;
@ -1347,7 +1348,7 @@ again:;
}
if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock);
result = AllowServerConnect(data, conn, portsock);
if( result )
return result;
}
@ -1360,7 +1361,7 @@ again:;
Curl_pgrsSetUploadSize(data, data->infilesize);
result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */
data->secondarysocket, bytecountp);
conn->secondarysocket, bytecountp);
if(result)
return result;
@ -1414,9 +1415,9 @@ again:;
dirlist = TRUE;
/* 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)
return CURLE_OPERATION_TIMEOUTED;
@ -1429,16 +1430,16 @@ again:;
better used since the LIST command output is not specified or
standard in any way */
ftpsendf(data->firstsocket, conn, "%s",
ftpsendf(conn->firstsocket, conn, "%s",
data->customrequest?data->customrequest:
(data->bits.ftp_list_only?"NLST":"LIST"));
}
else {
/* 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");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
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
* 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)
return CURLE_OPERATION_TIMEOUTED;
@ -1501,9 +1502,9 @@ again:;
infof(data, "Instructs server to resume from offset %d\n",
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)
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)
return CURLE_OPERATION_TIMEOUTED;
@ -1580,7 +1581,7 @@ again:;
size = downloadsize;
if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock);
result = AllowServerConnect(data, conn, portsock);
if( result )
return result;
}
@ -1588,7 +1589,7 @@ again:;
infof(data, "Getting file with size: %d\n", size);
/* FTP download: */
result=Curl_Transfer(conn, data->secondarysocket, size, FALSE,
result=Curl_Transfer(conn, conn->secondarysocket, size, FALSE,
bytecountp,
-1, NULL); /* no upload here */
if(result)
@ -1617,7 +1618,7 @@ CURLcode Curl_ftp(struct connectdata *conn)
int dirlength=0; /* 0 forces strlen() */
/* 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
it */

View File

@ -325,21 +325,21 @@ CURLcode Curl_http_connect(struct connectdata *conn)
if (conn->protocol & PROT_HTTPS) {
if (data->bits.httpproxy) {
/* HTTPS through a proxy can only be done with a tunnel */
result = Curl_ConnectHTTPProxyTunnel(conn, data->firstsocket,
data->hostname, data->remote_port);
result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket,
conn->hostname, conn->remote_port);
if(CURLE_OK != result)
return result;
}
/* now, perform the SSL initialization for this socket */
if(Curl_SSLConnect(data))
if(Curl_SSLConnect(conn))
return CURLE_SSL_CONNECT_ERROR;
}
if(data->bits.user_passwd && !data->bits.this_is_a_follow) {
/* Authorization: is requested, this is not a followed location, get the
original host name */
data->auth_host = strdup(data->hostname);
data->auth_host = strdup(conn->hostname);
}
return CURLE_OK;
@ -361,7 +361,7 @@ CURLcode Curl_http_done(struct connectdata *conn)
struct HTTP *http;
data=conn->data;
http=data->proto.http;
http=conn->proto.http;
if(data->bits.http_formpost) {
*bytecount = http->readbytecount + http->writebytecount;
@ -394,7 +394,7 @@ CURLcode Curl_http(struct connectdata *conn)
if(!http)
return CURLE_OUT_OF_MEMORY;
memset(http, 0, sizeof(struct HTTP));
data->proto.http = http;
conn->proto.http = http;
if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
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 */
if(!data->bits.this_is_a_follow ||
!data->auth_host ||
strequal(data->auth_host, data->hostname)) {
strequal(data->auth_host, conn->hostname)) {
sprintf(data->buffer, "%s:%s", data->user, data->passwd);
if(Curl_base64_encode(data->buffer, strlen(data->buffer),
&authorization) >= 0) {
@ -690,10 +690,10 @@ CURLcode Curl_http(struct connectdata *conn)
Curl_pgrsSetUploadSize(data, http->postsize);
data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer);
result = Curl_Transfer(conn, data->firstsocket, -1, TRUE,
add_buffer_send(conn->firstsocket, conn, req_buffer);
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->readbytecount,
data->firstsocket,
conn->firstsocket,
&http->writebytecount);
if(result) {
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 */
data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer);
add_buffer_send(conn->firstsocket, conn, req_buffer);
/* prepare for transfer */
result = Curl_Transfer(conn, data->firstsocket, -1, TRUE,
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->readbytecount,
data->firstsocket,
conn->firstsocket,
&http->writebytecount);
if(result)
return result;
@ -762,10 +762,10 @@ CURLcode Curl_http(struct connectdata *conn)
/* issue the request */
data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer);
add_buffer_send(conn->firstsocket, conn, req_buffer);
/* 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 */
}
if(result)

View File

@ -290,7 +290,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
size_t nread;
int l = sizeof(local_addr);
if(getsockname(conn->data->firstsocket,
if(getsockname(conn->firstsocket,
(struct sockaddr *)LOCAL_ADDR, &l) < 0)
perror("getsockname()");
@ -339,9 +339,9 @@ krb4_auth(void *app_data, struct connectdata *conn)
return AUTH_CONTINUE;
}
/*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 */
nread = Curl_GetFTPResponse(conn->data->firstsocket,
nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL);
if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1;
@ -409,10 +409,10 @@ void krb_kauth(struct connectdata *conn)
save = set_command_prot(conn, prot_private);
/*ret = command("SITE KAUTH %s", name);***/
Curl_ftpsendf(conn->data->firstsocket, conn,
Curl_ftpsendf(conn->firstsocket, conn,
"SITE KAUTH %s", conn->data->user);
/* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, conn->data->buffer,
nread = Curl_GetFTPResponse(conn->firstsocket, conn->data->buffer,
conn, NULL);
if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/;
@ -486,10 +486,10 @@ void krb_kauth(struct connectdata *conn)
}
memset (tktcopy.dat, 0, tktcopy.length);
/*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);
/* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, conn->data->buffer,
nread = Curl_GetFTPResponse(conn->firstsocket, conn->data->buffer,
conn, NULL);
if(nread < 0)
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, char *, char *), ldap_entry2html);
server = ldap_open(data->hostname, data->port);
server = ldap_open(conn->hostname, conn->port);
if (server == NULL) {
failf(data, "LDAP: Cannot connect to %s:%d",
data->hostname, data->port);
conn->hostname, conn->port);
status = CURLE_COULDNT_CONNECT;
} else {
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){
Curl_ftpsendf(conn->data->firstsocket, conn,
Curl_ftpsendf(conn->firstsocket, conn,
"PBSZ %u", s);
/* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket,
nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL);
if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1;
@ -501,10 +501,10 @@ sec_prot_internal(struct connectdata *conn, int level)
conn->buffer_size = s;
}
Curl_ftpsendf(conn->data->firstsocket, conn,
Curl_ftpsendf(conn->firstsocket, conn,
"PROT %c", level["CSEP"]);
/* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket,
nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL);
if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1;
@ -610,10 +610,10 @@ sec_login(struct connectdata *conn)
}
infof(data, "Trying %s...\n", (*m)->name);
/*ret = command("AUTH %s", (*m)->name);***/
Curl_ftpsendf(conn->data->firstsocket, conn,
Curl_ftpsendf(conn->firstsocket, conn,
"AUTH %s", (*m)->name);
/* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket,
nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL);
if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1;

View File

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

View File

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

View File

@ -22,5 +22,6 @@
*
* $Id$
*****************************************************************************/
int Curl_SSLConnect (struct UrlData *data);
#include "urldata.h"
int Curl_SSLConnect(struct connectdata *conn);
#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) &&
sscanf (p+14, ": %ld", &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)) {
if (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)) {
failf(data,"Maximum (%d) redirects followed", data->maxredirs);
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect);
#endif
res=CURLE_TOO_MANY_REDIRECTS;
break;
}
@ -772,11 +784,15 @@ CURLcode curl_transfer(CURL *curl)
*/
break;
}
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect);
#endif
continue;
}
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect);
#endif
}
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
/* 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
* unique for an entire connection.
@ -145,6 +200,9 @@ struct connectdata {
Handle handle; /* struct identifier */
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 */
ConnState state; /* for state dependent actions */
@ -166,17 +224,27 @@ struct connectdata {
struct hostent *hp;
struct sockaddr_in serv_addr;
#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 *name; /* host name pointer to fool around with */
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;
long bytecount;
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
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
be protocol dependent */
CURLcode (*curl_do)(struct connectdata *connect);
@ -205,6 +273,7 @@ struct connectdata {
the same we read from. -1 disables */
long *writebytecountp; /* return number of bytes written or NULL */
#ifdef KRB4
enum protection_level command_prot;
@ -218,6 +287,24 @@ struct connectdata {
void *app_data;
#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 {
@ -253,35 +340,6 @@ struct Progress {
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 {
HTTPREQ_NONE, /* first in list */
HTTPREQ_GET,
@ -338,22 +396,6 @@ typedef enum {
CURLI_LAST
} 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
* three different parts:
@ -370,6 +412,9 @@ struct ssldata {
* 3 - Request-specific. Variables that are of interest for this particular
* 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 {
@ -381,7 +426,7 @@ struct UrlData {
char *errorbuffer; /* store failure messages in here */
/*************** 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 */
long proxyport; /* If non-zero, use this port number by default. If the
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 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 *in; /* the uploaded file is read from here */
FILE *writeheader; /* write the header to this is non-NULL */
char *url; /* what to get */
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) set
CONF_PORT to use this */
long port; /* which port to use (if non-protocol bind) */
unsigned short remote_port; /* what remote port to connect to, not the proxy
port! */
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 *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
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 */
double current_speed; /* the ProgressShow() funcion sets this */
@ -488,12 +512,13 @@ struct UrlData {
struct CookieInfo *cookies;
struct ssldata ssl; /* this is for ssl-stuff */
long crlf;
struct curl_slist *quote; /* before 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 */
time_t timevalue; /* what time to compare with */
@ -504,12 +529,6 @@ struct UrlData {
char *headerbuff; /* allocated buffer to store headers in */
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 */
#define MAX_CURL_USER_LENGTH 128
@ -541,6 +560,13 @@ struct UrlData {
#endif
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"

View File

@ -102,16 +102,13 @@ typedef enum {
#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_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_FTPAPPEND (1<<20) /* Append instead of overwrite on upload! */
#define CONF_NETRC (1<<22) /* read user+password from .netrc */
#define CONF_FOLLOWLOCATION (1<<23) /* use Location: Luke! */
#define CONF_GETTEXT (1<<24) /* use ASCII/text for transfer */
#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 */
#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"
" -s/--silent Silent mode. Don't output anything\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"
" --url <URL> Another way to specify URL to work with\n"
" -u/--user <user[:password]> Specify user and password to use\n"
@ -366,6 +364,8 @@ struct Configurable {
struct HttpPost *httppost;
struct HttpPost *last_post;
struct curl_slist *telnet_options;
HttpReq httpreq;
};
@ -565,7 +565,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"r", "range", TRUE},
{"s", "silent", FALSE},
{"S", "show-error", FALSE},
{"t", "upload", FALSE},
{"t", "telnet-options", TRUE},
{"T", "upload-file", TRUE},
{"u", "user", TRUE},
{"U", "proxy-user", TRUE},
@ -785,8 +785,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
else
config->postfields=postdata;
}
if(config->postfields)
config->conf |= CONF_POST;
if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq))
return PARAM_BAD_USE;
break;
@ -959,9 +958,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
config->showerror ^= TRUE; /* toggle on if used with -s */
break;
case 't':
/* we are uploading */
config->conf ^= CONF_UPLOAD;
fprintf(stderr, "-t is a deprecated switch, use '-T -' instead!\n");
/* Telnet options */
config->telnet_options = curl_slist_append(config->telnet_options, nextarg);
break;
case 'T':
/* we are uploading */
@ -1743,7 +1741,6 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_FAILONERROR,
config->conf&CONF_FAILONERROR);
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,
config->conf&CONF_FTPLISTONLY);
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,
config->conf&CONF_FOLLOWLOCATION);
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_USERPWD, config->userpwd);
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);
}
/* new in libcurl 7.6.2: */
curl_easy_setopt(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
res = curl_easy_perform(curl);
if(config->writeout) {

View File

@ -1,3 +1,3 @@
#define CURL_NAME "curl"
#define CURL_VERSION "7.6.1"
#define CURL_VERSION "7.7-alpha1"
#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
Server: test-server/fake
Location: data/110002.txt?coolsite=yes
Connection: close
This server reply is for testing a simple Location: following