New Curl version 7.10.3

This commit is contained in:
Andy Cedilnik 2003-01-14 09:12:37 -05:00
parent 6c61762b0f
commit 587b067880
27 changed files with 1622 additions and 1193 deletions

View File

@ -2,7 +2,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 1.5)
PROJECT(LIBCURL C)
SET(PACKAGE "curl")
SET(VERSION "7.10.2")
SET(VERSION "7.10.3")
SET(PACKAGE_TARNAME " ")
SET(OPERATING_SYSTEM ${CMAKE_SYSTEM_NAME})

View File

@ -61,6 +61,8 @@ static void decodeQuantum(unsigned char *dest, char *src)
x = (x << 6) + 62;
else if(src[i] == '/')
x = (x << 6) + 63;
else if(src[i] == '=')
x = (x << 6);
}
dest[2] = (unsigned char)(x & 255); x >>= 8;
@ -78,6 +80,7 @@ static void base64Decode(unsigned char *dest, char *src, int *rawLength)
int length = 0;
int equalsTerm = 0;
int i;
int numQuantums;
unsigned char lastQuantum[3];
while((src[length] != '=') && src[length])
@ -85,16 +88,18 @@ static void base64Decode(unsigned char *dest, char *src, int *rawLength)
while(src[length+equalsTerm] == '=')
equalsTerm++;
numQuantums = (length + equalsTerm) / 4;
if(rawLength)
*rawLength = (length * 3 / 4) - equalsTerm;
*rawLength = (numQuantums * 3) - equalsTerm;
for(i = 0; i < length/4 - 1; i++) {
for(i = 0; i < numQuantums - 1; i++) {
decodeQuantum(dest, src);
dest += 3; src += 4;
}
decodeQuantum(lastQuantum, src);
for(i = 0; i < 3 - equalsTerm; i++) dest[i] = lastQuantum[i];
for(i = 0; i < 3 - equalsTerm; i++)
dest[i] = lastQuantum[i];
}
@ -194,20 +199,21 @@ int Curl_base64_decode(const char *str, void *data)
#define TEST_NEED_SUCK
void *suck(int *);
int main(int argc, char **argv, char **envp) {
char *base64;
int base64Len;
unsigned char *data;
int dataLen;
int main(int argc, char **argv, char **envp)
{
char *base64;
int base64Len;
unsigned char *data;
int dataLen;
data = (unsigned char *)suck(&dataLen);
base64Len = Curl_base64_encode(data, dataLen, &base64);
data = (unsigned char *)suck(&dataLen);
base64Len = Curl_base64_encode(data, dataLen, &base64);
fprintf(stderr, "%d\n", base64Len);
fprintf(stdout, "%s", base64);
free(base64); free(data);
return 0;
fprintf(stderr, "%d\n", base64Len);
fprintf(stdout, "%s", base64);
free(base64); free(data);
return 0;
}
#endif
@ -220,47 +226,47 @@ int main(int argc, char **argv, char **envp) {
#define TEST_NEED_SUCK
void *suck(int *);
int main(int argc, char **argv, char **envp) {
char *base64;
int base64Len;
unsigned char *data;
int dataLen;
int main(int argc, char **argv, char **envp)
{
char *base64;
int base64Len;
unsigned char *data;
int dataLen;
base64 = (char *)suck(&base64Len);
data = (unsigned char *)malloc(base64Len * 3/4 + 8);
dataLen = Curl_base64_decode(base64, data);
fprintf(stderr, "%d\n", dataLen);
fwrite(data,1,dataLen,stdout);
free(base64); free(data);
return 0;
base64 = (char *)suck(&base64Len);
data = (unsigned char *)malloc(base64Len * 3/4 + 8);
dataLen = Curl_base64_decode(base64, data);
fprintf(stderr, "%d\n", dataLen);
fwrite(data,1,dataLen,stdout);
free(base64); free(data);
return 0;
}
#endif
#ifdef TEST_NEED_SUCK
/* this function 'sucks' in as much as possible from stdin */
void *suck(int *lenptr) {
int cursize = 8192;
unsigned char *buf = NULL;
int lastread;
int len = 0;
void *suck(int *lenptr)
{
int cursize = 8192;
unsigned char *buf = NULL;
int lastread;
int len = 0;
do {
cursize *= 2;
buf = (unsigned char *)realloc(buf, cursize);
memset(buf + len, 0, cursize - len);
lastread = fread(buf + len, 1, cursize - len, stdin);
len += lastread;
} while(!feof(stdin));
lenptr[0] = len;
return (void *)buf;
do {
cursize *= 2;
buf = (unsigned char *)realloc(buf, cursize);
memset(buf + len, 0, cursize - len);
lastread = fread(buf + len, 1, cursize - len, stdin);
len += lastread;
} while(!feof(stdin));
lenptr[0] = len;
return (void *)buf;
}
#endif
/*
* local variables:
* eval: (load-file "../curl-mode.el")

View File

@ -176,10 +176,9 @@ int waitconnect(int sockfd, /* socket */
/* timeout, no connect today */
return 1;
if(FD_ISSET(sockfd, &errfd)) {
if(FD_ISSET(sockfd, &errfd))
/* error condition caught */
return 2;
}
/* we have a connect! */
return 0;
@ -380,6 +379,11 @@ CURLcode Curl_is_connected(struct connectdata *conn,
return CURLE_OPERATION_TIMEOUTED;
}
}
if(conn->bits.tcpconnect) {
/* we are connected already! */
*connected = TRUE;
return CURLE_OK;
}
/* check for connect without timeout as we want to return immediately */
rc = waitconnect(sockfd, 0);
@ -646,6 +650,15 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
}
}
/* The '1 == rc' comes from the waitconnect(), and not from connect().
We can be sure of this since connect() cannot return 1. */
if((1 == rc) && (data->state.used_interface == Curl_if_multi)) {
/* Timeout when running the multi interface, we return here with a
CURLE_OK return code. */
rc = 0;
break;
}
if(0 == rc) {
int err = socketerror(sockfd);
if ((0 == err) || (EISCONN == err)) {
@ -658,12 +671,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
}
if(0 != rc) {
if(data->state.used_interface == Curl_if_multi) {
/* When running the multi interface, we bail out here */
rc = 0;
break;
}
/* get a new timeout for next attempt */
after = Curl_tvnow();
timeout_ms -= Curl_tvdiff(after, before);

View File

@ -66,9 +66,9 @@ struct curl_httppost {
char *contents; /* pointer to allocated data contents */
long contentslength; /* length of contents field */
/* CMC: Added support for buffer uploads */
char *buffer; /* pointer to allocated buffer contents */
long bufferlength; /* length of buffer field */
/* CMC: Added support for buffer uploads */
char *buffer; /* pointer to allocated buffer contents */
long bufferlength; /* length of buffer field */
char *contenttype; /* Content-Type */
struct curl_slist* contentheader; /* list of extra headers for this form */
@ -96,7 +96,9 @@ typedef int (*curl_progress_callback)(void *clientp,
double ultotal,
double ulnow);
#define CURL_MAX_WRITE_SIZE 20480
/* Tests have proven that 20K is a very bad buffer size for uploads on
Windows, while 16K for some odd reason performed a lot better. */
#define CURL_MAX_WRITE_SIZE 16384
typedef size_t (*curl_write_callback)(char *buffer,
size_t size,
@ -160,7 +162,7 @@ typedef enum {
CURLE_FTP_COULDNT_RETR_FILE, /* 19 */
CURLE_FTP_WRITE_ERROR, /* 20 */
CURLE_FTP_QUOTE_ERROR, /* 21 */
CURLE_HTTP_NOT_FOUND, /* 22 */
CURLE_HTTP_RETURNED_ERROR, /* 22 */
CURLE_WRITE_ERROR, /* 23 */
CURLE_MALFORMAT_USER, /* 24 - user name is illegally specified */
CURLE_FTP_COULDNT_STOR_FILE, /* 25 - failed FTP upload */
@ -207,6 +209,7 @@ typedef enum {
/* Make a spelling correction for the operation timed-out define */
#define CURLE_OPERATION_TIMEDOUT CURLE_OPERATION_TIMEOUTED
#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
typedef enum {
CURLPROXY_HTTP = 0,
@ -610,6 +613,11 @@ typedef enum {
the response to be compressed. */
CINIT(ENCODING, OBJECTPOINT, 102),
/* Set pointer to private data */
CINIT(PRIVATE, OBJECTPOINT, 103),
/* Set aliases for HTTP 200 in the HTTP Response header */
CINIT(HTTP200ALIASES, OBJECTPOINT, 104),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@ -803,8 +811,8 @@ CURLcode curl_global_init(long flags);
void curl_global_cleanup(void);
/* This is the version number */
#define LIBCURL_VERSION "7.10.2"
#define LIBCURL_VERSION_NUM 0x070a02
#define LIBCURL_VERSION "7.10.3"
#define LIBCURL_VERSION_NUM 0x070a03
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
struct curl_slist {
@ -861,16 +869,13 @@ typedef enum {
CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19,
CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20,
CURLINFO_PRIVATE = CURLINFO_STRING + 21,
/* Fill in new entries here! */
CURLINFO_LASTONE = 21
CURLINFO_LASTONE = 22
} CURLINFO;
/* unfortunately, the easy.h and multi.h include files need options and info
stuff before they can be included! */
#include "easy.h" /* nothing in curl is fun without the easy stuff */
#include "multi.h"
typedef enum {
CURLCLOSEPOLICY_NONE, /* first, never use this */
@ -894,35 +899,56 @@ typedef enum {
* Setup defines, protos etc for the sharing stuff.
*/
/* Different types of locks that a share can aquire */
/* Different data locks for a single share */
typedef enum {
CURL_LOCK_TYPE_NONE = 0,
CURL_LOCK_TYPE_COOKIE = 1<<0,
CURL_LOCK_TYPE_DNS = 1<<1,
CURL_LOCK_TYPE_SSL_SESSION = 2<<1,
CURL_LOCK_TYPE_CONNECT = 2<<2,
CURL_LOCK_TYPE_LAST
} curl_lock_type;
CURL_LOCK_DATA_NONE = 0,
CURL_LOCK_DATA_COOKIE = 1,
CURL_LOCK_DATA_DNS = 2,
CURL_LOCK_DATA_SSL_SESSION = 3,
CURL_LOCK_DATA_CONNECT = 4,
CURL_LOCK_DATA_LAST
} curl_lock_data;
typedef void (*curl_lock_function)(CURL *, curl_lock_type, void *);
typedef void (*curl_unlock_function)(CURL *, curl_lock_type, void *);
/* Different lock access types */
typedef enum {
CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */
CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */
CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */
CURL_LOCK_ACCESS_LAST /* never use */
} curl_lock_access;
typedef struct {
unsigned int specifier;
unsigned int locked;
unsigned int dirty;
curl_lock_function lockfunc;
curl_unlock_function unlockfunc;
void *clientdata;
} curl_share;
typedef void (*curl_lock_function)(CURL *handle,
curl_lock_data data,
curl_lock_access access,
void *userptr);
typedef void (*curl_unlock_function)(CURL *handle,
curl_lock_data data,
void *userptr);
curl_share *curl_share_init (void);
CURLcode curl_share_setopt (curl_share *, curl_lock_type, int);
CURLcode curl_share_set_lock_function (curl_share *, curl_lock_function);
CURLcode curl_share_set_unlock_function (curl_share *, curl_unlock_function);
CURLcode curl_share_set_lock_data (curl_share *, void *);
CURLcode curl_share_destroy (curl_share *);
typedef void CURLSH;
typedef enum {
CURLSHE_OK, /* all is fine */
CURLSHE_BAD_OPTION, /* 1 */
CURLSHE_IN_USE, /* 2 */
CURLSHE_INVALID, /* 3 */
CURLSHE_LAST /* never use */
} CURLSHcode;
typedef enum {
CURLSHOPT_NONE, /* don't use */
CURLSHOPT_SHARE, /* specify a data type to share */
CURLSHOPT_UNSHARE, /* specify shich data type to stop sharing */
CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */
CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */
CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock
callback functions */
CURLSHOPT_LAST /* never use */
} CURLSHoption;
CURLSH *curl_share_init(void);
CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
CURLSHcode curl_share_cleanup(CURLSH *);
/****************************************************************************
* Structures for querying information about the curl library at runtime.
@ -965,4 +991,9 @@ curl_version_info_data *curl_version_info(CURLversion);
}
#endif
/* unfortunately, the easy.h and multi.h include files need options and info
stuff before they can be included! */
#include "easy.h" /* nothing in curl is fun without the easy stuff */
#include "multi.h"
#endif /* __CURL_CURL_H */

View File

@ -233,15 +233,17 @@ CURLcode curl_easy_perform(CURL *curl)
{
struct SessionHandle *data = (struct SessionHandle *)curl;
if (!data->hostcache) {
if (Curl_global_host_cache_use(data)) {
data->hostcache = Curl_global_host_cache_get();
}
else {
data->hostcache = Curl_hash_alloc(7, Curl_freeaddrinfo);
if (Curl_global_host_cache_use(data) && data->hostcache != Curl_global_host_cache_get()) {
if (data->hostcache) {
Curl_hash_destroy(data->hostcache);
}
data->hostcache = Curl_global_host_cache_get();
}
if (!data->hostcache) {
data->hostcache = Curl_hash_alloc(7, Curl_freednsinfo);
}
return Curl_perform(data);
}

View File

@ -41,6 +41,7 @@ char *curl_escape(const char *string, int length)
{
int alloc = (length?length:(int)strlen(string))+1;
char *ns = malloc(alloc);
char *testing_ptr = NULL;
unsigned char in;
int newlen = alloc;
int index=0;
@ -55,9 +56,14 @@ char *curl_escape(const char *string, int length)
newlen += 2; /* the size grows with two, since this'll become a %XX */
if(newlen > alloc) {
alloc *= 2;
ns = realloc(ns, alloc);
if(!ns)
testing_ptr = realloc(ns, alloc);
if(!testing_ptr) {
free( ns );
return NULL;
}
else {
ns = testing_ptr;
}
}
sprintf(&ns[index], "%%%02X", in);
@ -80,6 +86,10 @@ char *curl_unescape(const char *string, int length)
unsigned char in;
int index=0;
unsigned int hex;
if( !ns ) {
return NULL;
}
while(--alloc > 0) {
in = *string;
@ -97,7 +107,6 @@ char *curl_unescape(const char *string, int length)
}
ns[index]=0; /* terminate it */
return ns;
}
void curl_free(void *p)

View File

@ -1319,7 +1319,7 @@ int Curl_FormReader(char *buffer,
wantedsize = size * nitems;
if(!form->data)
return -1; /* nothing, error, empty */
return 0; /* nothing, error, empty */
do {

View File

@ -173,9 +173,9 @@ static CURLcode AllowServerConnect(struct SessionHandle *data,
* response and extract the relevant return code for the invoking function.
*/
int Curl_GetFTPResponse(char *buf,
struct connectdata *conn,
int *ftpcode)
CURLcode Curl_GetFTPResponse(int *nreadp, /* return number of bytes read */
struct connectdata *conn,
int *ftpcode) /* return the ftp-code */
{
/* Brand new implementation.
* We cannot read just one byte per read() and then go back to select()
@ -185,28 +185,21 @@ int Curl_GetFTPResponse(char *buf,
* line in a response or continue reading. */
int sockfd = conn->firstsocket;
int nread; /* total size read */
int perline; /* count bytes per line */
bool keepon=TRUE;
ssize_t gotbytes;
char *ptr;
int timeout = 3600; /* default timeout in seconds */
int timeout; /* timeout in seconds */
struct timeval interval;
fd_set rkeepfd;
fd_set readfd;
struct SessionHandle *data = conn->data;
char *line_start;
int code=0; /* default "error code" to return */
#define SELECT_OK 0
#define SELECT_ERROR 1 /* select() problems */
#define SELECT_TIMEOUT 2 /* took too long */
#define SELECT_MEMORY 3 /* no available memory */
#define SELECT_CALLBACK 4 /* aborted by callback */
int error = SELECT_OK;
int code=0; /* default ftp "error code" to return */
char *buf = data->state.buffer;
CURLcode result = CURLE_OK;
struct FTP *ftp = conn->proto.ftp;
struct timeval now = Curl_tvnow();
if (ftpcode)
*ftpcode = 0; /* 0 for errors */
@ -221,20 +214,25 @@ int Curl_GetFTPResponse(char *buf,
ptr=buf;
line_start = buf;
nread=0;
*nreadp=0;
perline=0;
keepon=TRUE;
while((nread<BUFSIZE) && (keepon && !error)) {
while((*nreadp<BUFSIZE) && (keepon && !result)) {
/* check and reset timeout value every lap */
if(data->set.timeout) {
if(data->set.timeout)
/* if timeout is requested, find out how much remaining time we have */
timeout = data->set.timeout - /* timeout time */
Curl_tvdiff(Curl_tvnow(), conn->now)/1000; /* spent time */
if(timeout <=0 ) {
failf(data, "Transfer aborted due to timeout");
return -SELECT_TIMEOUT; /* already too little time */
}
else
/* Even without a requested timeout, we only wait response_time
seconds for the full response to arrive before we bail out */
timeout = ftp->response_time -
Curl_tvdiff(Curl_tvnow(), now)/1000; /* spent time */
if(timeout <=0 ) {
failf(data, "Transfer aborted due to timeout");
return CURLE_OPERATION_TIMEDOUT; /* already too little time */
}
if(!ftp->cache) {
@ -244,19 +242,18 @@ int Curl_GetFTPResponse(char *buf,
switch (select (sockfd+1, &readfd, NULL, NULL, &interval)) {
case -1: /* select() error, stop reading */
error = SELECT_ERROR;
failf(data, "Transfer aborted due to select() error");
result = CURLE_RECV_ERROR;
failf(data, "Transfer aborted due to select() error: %d", errno);
break;
case 0: /* timeout */
error = SELECT_TIMEOUT;
result = CURLE_OPERATION_TIMEDOUT;
failf(data, "Transfer aborted due to timeout");
break;
default:
error = SELECT_OK;
break;
}
}
if(SELECT_OK == error) {
if(CURLE_OK == result) {
/*
* This code previously didn't use the kerberos sec_read() code
* to read, but when we use Curl_read() it may do so. Do confirm
@ -272,8 +269,7 @@ int Curl_GetFTPResponse(char *buf,
ftp->cache_size = 0; /* zero the size just in case */
}
else {
int res = Curl_read(conn, sockfd, ptr,
BUFSIZE-nread, &gotbytes);
int res = Curl_read(conn, sockfd, ptr, BUFSIZE-*nreadp, &gotbytes);
if(res < 0)
/* EWOULDBLOCK */
continue; /* go looping again */
@ -286,7 +282,7 @@ int Curl_GetFTPResponse(char *buf,
;
else if(gotbytes <= 0) {
keepon = FALSE;
error = SELECT_ERROR;
result = CURLE_RECV_ERROR;
failf(data, "Connection aborted");
}
else {
@ -295,7 +291,7 @@ int Curl_GetFTPResponse(char *buf,
* line */
int i;
nread += gotbytes;
*nreadp += gotbytes;
for(i = 0; i < gotbytes; ptr++, i++) {
perline++;
if(*ptr=='\n') {
@ -315,7 +311,7 @@ int Curl_GetFTPResponse(char *buf,
result = Curl_client_write(data, CLIENTWRITE_HEADER,
line_start, perline);
if(result)
return -SELECT_CALLBACK;
return result;
#define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \
isdigit((int)line[2]) && (' ' == line[3]))
@ -350,13 +346,13 @@ int Curl_GetFTPResponse(char *buf,
if(ftp->cache)
memcpy(ftp->cache, line_start, ftp->cache_size);
else
return -SELECT_MEMORY; /**BANG**/
return CURLE_OUT_OF_MEMORY; /**BANG**/
}
} /* there was data */
} /* if(no error) */
} /* while there's buffer left and loop is requested */
if(!error)
if(!result)
code = atoi(buf);
#ifdef KRB4
@ -378,13 +374,10 @@ int Curl_GetFTPResponse(char *buf,
}
#endif
if(error)
return -error;
if(ftpcode)
*ftpcode=code; /* return the initial number like this */
return nread; /* total amount of bytes read */
return result;
}
/*
@ -417,6 +410,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
/* no need to duplicate them, the data struct won't change */
ftp->user = data->state.user;
ftp->passwd = data->state.passwd;
ftp->response_time = 3600; /* set default response time-out */
if (data->set.tunnel_thru_httpproxy) {
/* We want "seamless" FTP operations through HTTP proxy tunnel */
@ -436,9 +430,9 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
/* The first thing we do is wait for the "220*" line: */
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(result)
return result;
if(ftpcode != 220) {
failf(data, "This doesn't seem like a nice ftp-server response");
@ -467,9 +461,9 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
FTPSENDF(conn, "USER %s", ftp->user);
/* wait for feedback */
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(result)
return result;
if(ftpcode == 530) {
/* 530 User ... access denied
@ -481,9 +475,9 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
/* 331 Password required for ...
(the server requires to send the user's password too) */
FTPSENDF(conn, "PASS %s", ftp->passwd);
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(result)
return result;
if(ftpcode == 530) {
/* 530 Login incorrect.
@ -516,8 +510,11 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
/* we may need to issue a KAUTH here to have access to the files
* do it if user supplied a password
*/
if(data->state.passwd && *data->state.passwd)
Curl_krb_kauth(conn);
if(data->state.passwd && *data->state.passwd) {
result = Curl_krb_kauth(conn);
if(result)
return result;
}
#endif
}
else {
@ -529,9 +526,9 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
FTPSENDF(conn, "PWD", NULL);
/* wait for feedback */
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(result)
return result;
if(ftpcode == 257) {
char *dir = (char *)malloc(nread+1);
@ -544,7 +541,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
The directory name can contain any character; embedded double-quotes
should be escaped by double-quotes (the "quote-doubling" convention).
*/
if('\"' == *ptr) {
if(dir && ('\"' == *ptr)) {
/* it started good */
ptr++;
while(ptr && *ptr) {
@ -570,6 +567,8 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
}
else {
/* couldn't get the path */
free(dir);
infof(data, "Failed to figure out path\n");
}
}
@ -594,7 +593,6 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
struct SessionHandle *data = conn->data;
struct FTP *ftp = conn->proto.ftp;
ssize_t nread;
char *buf = data->state.buffer; /* this is our buffer */
int ftpcode;
CURLcode result=CURLE_OK;
@ -633,11 +631,24 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
conn->secondarysocket = -1;
if(!ftp->no_transfer) {
/* now let's see what the server says about the transfer we just
performed: */
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
/* Let's see what the server says about the transfer we just performed,
but lower the timeout as sometimes this connection has died while
the data has been transfered. This happens when doing through NATs
etc that abandon old silent connections.
*/
ftp->response_time = 60; /* give it only a minute for now */
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
ftp->response_time = 3600; /* set this back to one hour waits */
if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) {
failf(data, "control connection looks dead");
return result;
}
if(result)
return result;
if(!ftp->dont_check) {
/* 226 Transfer complete, 250 Requested file action okay, completed. */
@ -680,9 +691,9 @@ CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
if (item->data) {
FTPSENDF(conn, "%s", item->data);
nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, &ftpcode);
if (nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if (result)
return result;
if (ftpcode >= 400) {
failf(conn->data, "QUOT string not accepted: %s", item->data);
@ -711,9 +722,9 @@ CURLcode ftp_cwd(struct connectdata *conn, char *path)
CURLcode result;
FTPSENDF(conn, "CWD %s", path);
nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, &ftpcode);
if (nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if (result)
return result;
if (ftpcode != 250) {
failf(conn->data, "Couldn't cd to %s", path);
@ -741,26 +752,34 @@ CURLcode ftp_getfiletime(struct connectdata *conn, char *file)
again a grey area as the MDTM is not kosher RFC959 */
FTPSENDF(conn, "MDTM %s", file);
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(result)
return result;
if(ftpcode == 213) {
/* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
last .sss part is optional and means fractions of a second */
int year, month, day, hour, minute, second;
if(6 == sscanf(buf+4, "%04d%02d%02d%02d%02d%02d",
&year, &month, &day, &hour, &minute, &second)) {
/* we have a time, reformat it */
time_t secs=time(NULL);
sprintf(buf, "%04d%02d%02d %02d:%02d:%02d",
year, month, day, hour, minute, second);
/* now, convert this into a time() value: */
conn->data->info.filetime = curl_getdate(buf, &secs);
}
else {
infof(conn->data, "unsupported MDTM reply format\n");
switch(ftpcode) {
case 213:
{
/* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
last .sss part is optional and means fractions of a second */
int year, month, day, hour, minute, second;
if(6 == sscanf(buf+4, "%04d%02d%02d%02d%02d%02d",
&year, &month, &day, &hour, &minute, &second)) {
/* we have a time, reformat it */
time_t secs=time(NULL);
sprintf(buf, "%04d%02d%02d %02d:%02d:%02d",
year, month, day, hour, minute, second);
/* now, convert this into a time() value: */
conn->data->info.filetime = curl_getdate(buf, &secs);
}
}
break;
default:
infof(conn->data, "unsupported MDTM reply format\n");
break;
case 550: /* "No such file or directory" */
failf(conn->data, "Given file does not exist");
result = CURLE_FTP_COULDNT_RETR_FILE;
break;
}
return result;
}
@ -778,14 +797,13 @@ static CURLcode ftp_transfertype(struct connectdata *conn,
struct SessionHandle *data = conn->data;
int ftpcode;
ssize_t nread;
char *buf=data->state.buffer;
CURLcode result;
FTPSENDF(conn, "TYPE %s", ascii?"A":"I");
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(result)
return result;
if(ftpcode != 200) {
failf(data, "Couldn't set %s mode",
@ -814,9 +832,9 @@ CURLcode ftp_getsize(struct connectdata *conn, char *file,
CURLcode result;
FTPSENDF(conn, "SIZE %s", file);
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(result)
return result;
if(ftpcode == 213) {
/* get the size from the ascii string: */
@ -975,7 +993,6 @@ CURLcode ftp_use_port(struct connectdata *conn)
struct SessionHandle *data=conn->data;
int portsock=-1;
ssize_t nread;
char *buf = data->state.buffer; /* this is our buffer */
int ftpcode; /* receive FTP response codes in this */
CURLcode result;
@ -1155,9 +1172,9 @@ CURLcode ftp_use_port(struct connectdata *conn)
return result;
}
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(result)
return result;
if (ftpcode != 200) {
failf(data, "Server does not grok %s", *modep);
@ -1301,9 +1318,9 @@ CURLcode ftp_use_port(struct connectdata *conn)
return result;
}
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(result)
return result;
if(ftpcode != 200) {
failf(data, "Server does not grok PORT, try without it!");
@ -1375,9 +1392,9 @@ CURLcode ftp_use_pasv(struct connectdata *conn,
result = Curl_ftpsendf(conn, "%s", mode[modeoff]);
if(result)
return result;
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(result)
return result;
if (ftpcode == results[modeoff])
break;
}
@ -1522,7 +1539,7 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
ssize_t nread;
int ftpcode; /* for ftp status */
/* the ftp struct is already inited in ftp_connect() */
/* the ftp struct is already inited in Curl_ftp_connect() */
struct FTP *ftp = conn->proto.ftp;
long *bytecountp = ftp->bytecountp;
@ -1582,8 +1599,8 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
readthisamountnow = BUFSIZE;
actuallyread =
data->set.fread(data->state.buffer, 1, readthisamountnow,
data->set.in);
conn->fread(data->state.buffer, 1, readthisamountnow,
conn->fread_in);
passed += actuallyread;
if(actuallyread != readthisamountnow) {
@ -1614,7 +1631,7 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
}
}
/* Send everything on data->set.in to the socket */
/* Send everything on data->state.in to the socket */
if(data->set.ftp_append) {
/* we append onto the file instead of rewriting it */
FTPSENDF(conn, "APPE %s", ftp->file);
@ -1623,9 +1640,9 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
FTPSENDF(conn, "STOR %s", ftp->file);
}
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(result)
return result;
if(ftpcode>=400) {
failf(data, "Failed FTP upload:%s", buf+3);
@ -1799,9 +1816,9 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
FTPSENDF(conn, "REST %d", conn->resume_from);
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(result)
return result;
if(ftpcode != 350) {
failf(data, "Couldn't use REST: %s", buf+4);
@ -1812,9 +1829,9 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
FTPSENDF(conn, "RETR %s", ftp->file);
}
nread = Curl_GetFTPResponse(buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(result)
return result;
if((ftpcode == 150) || (ftpcode == 125)) {
@ -1919,7 +1936,7 @@ CURLcode ftp_perform(struct connectdata *conn,
struct SessionHandle *data=conn->data;
char *buf = data->state.buffer; /* this is our buffer */
/* the ftp struct is already inited in ftp_connect() */
/* the ftp struct is already inited in Curl_ftp_connect() */
struct FTP *ftp = conn->proto.ftp;
/* Send any QUOTE strings? */
@ -1980,7 +1997,7 @@ CURLcode ftp_perform(struct connectdata *conn,
well, we "emulate" a HTTP-style header in our output. */
#ifdef HAVE_STRFTIME
if(data->set.get_filetime && data->info.filetime) {
if(data->set.get_filetime && (data->info.filetime>=0) ) {
struct tm *tm;
#ifdef HAVE_LOCALTIME_R
struct tm buffer;

View File

@ -29,8 +29,8 @@ CURLcode Curl_ftp_done(struct connectdata *conn);
CURLcode Curl_ftp_connect(struct connectdata *conn);
CURLcode Curl_ftp_disconnect(struct connectdata *conn);
CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
int Curl_GetFTPResponse(char *buf, struct connectdata *conn,
int *ftpcode);
CURLcode Curl_GetFTPResponse(int *nread, struct connectdata *conn,
int *ftpcode);
CURLcode Curl_ftp_nextconnect(struct connectdata *conn);
#endif

View File

@ -158,6 +158,9 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
case CURLINFO_CONTENT_TYPE:
*param_charp = data->info.contenttype;
break;
case CURLINFO_PRIVATE:
*param_charp = data->set.private?data->set.private:(char *)"";
break;
default:
return CURLE_BAD_FUNCTION_ARGUMENT;
}

View File

@ -88,7 +88,7 @@ static Curl_addrinfo *my_getaddrinfo(struct SessionHandle *data,
void Curl_global_host_cache_init(void)
{
if (!host_cache_initialized) {
Curl_hash_init(&hostname_cache, 7, Curl_freeaddrinfo);
Curl_hash_init(&hostname_cache, 7, Curl_freednsinfo);
host_cache_initialized = 1;
}
}
@ -287,17 +287,25 @@ struct Curl_dns_entry *Curl_resolv(struct SessionHandle *data,
/*
* This is a wrapper function for freeing name information in a protocol
* independent way. This takes care of using the appropriate underlaying
* proper function.
* function.
*/
void Curl_freeaddrinfo(void *freethis)
void Curl_freeaddrinfo(Curl_addrinfo *p)
{
#ifdef ENABLE_IPV6
freeaddrinfo(p);
#else
free(p);
#endif
}
/*
* Free a cache dns entry.
*/
void Curl_freednsinfo(void *freethis)
{
struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis;
#ifdef ENABLE_IPV6
freeaddrinfo(p->addr);
#else
free(p->addr);
#endif
Curl_freeaddrinfo(p->addr);
free(p);
}
@ -623,16 +631,28 @@ static Curl_addrinfo *my_getaddrinfo(struct SessionHandle *data,
&h, /* DIFFERENCE */
&h_errnop);
/* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a
sudden this function seems to be setting EAGAIN if the given buffer
size is too small. Previous versions are known to return ERANGE for
the same. */
sudden this function returns EAGAIN if the given buffer size is too
small. Previous versions are known to return ERANGE for the same
problem.
This wouldn't be such a big problem if older versions wouldn't
sometimes return EAGAIN on a common failure case. Alas, we can't
assume that EAGAIN *or* ERANGE means ERANGE for any given version of
glibc.
For now, we do that and thus we may call the function repeatedly and
fail for older glibc versions that return EAGAIN, until we run out
of buffer size (step_size grows beyond CURL_NAMELOOKUP_SIZE).
If anyone has a better fix, please tell us!
*/
if((ERANGE == res) || (EAGAIN == res)) {
step_size+=200;
continue;
}
break;
} while(1);
} while(step_size <= CURL_NAMELOOKUP_SIZE);
if(!h) /* failure */
res=1;

View File

@ -65,7 +65,10 @@ struct Curl_dns_entry *Curl_resolv(struct SessionHandle *data,
void Curl_scan_cache_used(void *user, void *ptr);
/* free name info */
void Curl_freeaddrinfo(void *freethis);
void Curl_freeaddrinfo(Curl_addrinfo *freeaddr);
/* free cached name info */
void Curl_freednsinfo(void *freethis);
#ifdef MALLOCDEBUG
void curl_freeaddrinfo(struct addrinfo *freethis,

View File

@ -98,12 +98,65 @@
#include "memdebug.h"
#endif
/* fread() emulation to provide POST and/or request data */
static int readmoredata(char *buffer,
size_t size,
size_t nitems,
void *userp)
{
struct connectdata *conn = (struct connectdata *)userp;
struct HTTP *http = conn->proto.http;
int fullsize = size * nitems;
if(0 == http->postsize)
/* nothing to return */
return 0;
/* make sure that a HTTP request is never sent away chunked! */
conn->bits.forbidchunk= (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
if(http->postsize <= fullsize) {
memcpy(buffer, http->postdata, http->postsize);
fullsize = http->postsize;
if(http->backup.postsize) {
/* move backup data into focus and continue on that */
http->postdata = http->backup.postdata;
http->postsize = http->backup.postsize;
conn->fread = http->backup.fread;
conn->fread_in = http->backup.fread_in;
http->sending++; /* move one step up */
http->backup.postsize=0;
}
else
http->postsize = 0;
return fullsize;
}
memcpy(buffer, http->postdata, fullsize);
http->postdata += fullsize;
http->postsize -= fullsize;
return fullsize;
}
/* ------------------------------------------------------------------------- */
/*
* The add_buffer series of functions are used to build one large memory chunk
* from repeated function invokes. Used so that the entire HTTP request can
* be sent in one go.
*/
struct send_buffer {
char *buffer;
size_t size_max;
size_t size_used;
};
typedef struct send_buffer send_buffer;
static CURLcode
add_buffer(send_buffer *in, const void *inptr, size_t size);
@ -126,44 +179,66 @@ send_buffer *add_buffer_init(void)
* add_buffer_send() sends a buffer and frees all associated memory.
*/
static
CURLcode add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in,
long *bytes_written)
CURLcode add_buffer_send(send_buffer *in,
int sockfd,
struct connectdata *conn,
long *bytes_written) /* add the number of sent
bytes to this counter */
{
ssize_t amount;
CURLcode res;
char *ptr;
int size;
struct HTTP *http = conn->proto.http;
/* The looping below is required since we use non-blocking sockets, but due
to the circumstances we will just loop and try again and again etc */
ptr = in->buffer;
size = in->size_used;
do {
res = Curl_write(conn, sockfd, ptr, size, &amount);
if(CURLE_OK != res)
break;
res = Curl_write(conn, sockfd, ptr, size, &amount);
if(CURLE_OK == res) {
if(conn->data->set.verbose)
/* this data _may_ contain binary stuff */
Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, amount);
*bytes_written += amount;
if(amount != size) {
/* The whole request could not be sent in one system call. We must queue
it up and send it later when we get the chance. We must not loop here
and wait until it might work again. */
size -= amount;
ptr += amount;
/* backup the currently set pointers */
http->backup.fread = conn->fread;
http->backup.fread_in = conn->fread_in;
http->backup.postdata = http->postdata;
http->backup.postsize = http->postsize;
/* set the new pointers for the request-sending */
conn->fread = (curl_read_callback)readmoredata;
conn->fread_in = (void *)conn;
http->postdata = ptr;
http->postsize = size;
http->send_buffer = in;
http->sending = HTTPSEND_REQUEST;
return CURLE_OK;
}
else
break;
} while(1);
/* the full buffer was sent, clean up and return */
}
if(in->buffer)
free(in->buffer);
free(in);
*bytes_written += amount;
return res;
}
@ -223,21 +298,75 @@ CURLcode add_buffer(send_buffer *in, const void *inptr, size_t size)
/* end of the add_buffer functions */
/* ------------------------------------------------------------------------- */
/*
* Curl_compareheader()
*
* Returns TRUE if 'headerline' contains the 'header' with given 'content'.
* Pass headers WITH the colon.
*/
bool
Curl_compareheader(char *headerline, /* line to check */
const char *header, /* header keyword _with_ colon */
const char *content) /* content string to find */
{
/* RFC2616, section 4.2 says: "Each header field consists of a name followed
* by a colon (":") and the field value. Field names are case-insensitive.
* The field value MAY be preceded by any amount of LWS, though a single SP
* is preferred." */
size_t hlen = strlen(header);
size_t clen;
size_t len;
char *start;
char *end;
if(!strnequal(headerline, header, hlen))
return FALSE; /* doesn't start with header */
/* pass the header */
start = &headerline[hlen];
/* pass all white spaces */
while(*start && isspace((int)*start))
start++;
/* find the end of the header line */
end = strchr(start, '\r'); /* lines end with CRLF */
if(!end) {
/* in case there's a non-standard compliant line here */
end = strchr(start, '\n');
if(!end)
/* hm, there's no line ending here, use the zero byte! */
end = strchr(start, '\0');
}
len = end-start; /* length of the content part of the input line */
clen = strlen(content); /* length of the word to find */
/* find the content string in the rest of the line */
for(;len>=clen;len--, start++) {
if(strnequal(start, content, clen))
return TRUE; /* match! */
}
return FALSE; /* no match */
}
/*
* This function checks the linked list of custom HTTP headers for a particular
* header (prefix).
*/
static bool checkheaders(struct SessionHandle *data, const char *thisheader)
static char *checkheaders(struct SessionHandle *data, const char *thisheader)
{
struct curl_slist *head;
size_t thislen = strlen(thisheader);
for(head = data->set.headers; head; head=head->next) {
if(strnequal(head->data, thisheader, thislen)) {
return TRUE;
}
if(strnequal(head->data, thisheader, thislen))
return head->data;
}
return FALSE;
return NULL;
}
/*
@ -440,6 +569,10 @@ CURLcode Curl_http_connect(struct connectdata *conn)
if(conn->bits.user_passwd && !data->state.this_is_a_follow) {
/* Authorization: is requested, this is not a followed location, get the
original host name */
if (data->state.auth_host)
/* Free to avoid leaking memory on multiple requests*/
free(data->state.auth_host);
data->state.auth_host = strdup(conn->hostname);
}
@ -454,13 +587,21 @@ CURLcode Curl_http_done(struct connectdata *conn)
data=conn->data;
http=conn->proto.http;
/* set the proper values (possibly modified on POST) */
conn->fread = data->set.fread; /* restore */
conn->fread_in = data->set.in; /* restore */
if(http->send_buffer) {
send_buffer *buff = http->send_buffer;
free(buff->buffer);
free(buff);
}
if(HTTPREQ_POST_FORM == data->set.httpreq) {
conn->bytecount = http->readbytecount + http->writebytecount;
Curl_formclean(http->sendit); /* Now free that whole lot */
data->set.fread = http->storefread; /* restore */
data->set.in = http->in; /* restore */
}
else if(HTTPREQ_PUT == data->set.httpreq)
conn->bytecount = http->readbytecount + http->writebytecount;
@ -475,7 +616,6 @@ CURLcode Curl_http_done(struct connectdata *conn)
return CURLE_OK;
}
CURLcode Curl_http(struct connectdata *conn)
{
struct SessionHandle *data=conn->data;
@ -523,7 +663,7 @@ CURLcode Curl_http(struct connectdata *conn)
host due to a location-follow, we do some weirdo checks here */
if(!data->state.this_is_a_follow ||
!data->state.auth_host ||
strequal(data->state.auth_host, conn->hostname)) {
curl_strequal(data->state.auth_host, conn->hostname)) {
sprintf(data->state.buffer, "%s:%s",
data->state.user, data->state.passwd);
if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer),
@ -547,12 +687,30 @@ CURLcode Curl_http(struct connectdata *conn)
conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->set.cookie);
}
if(!conn->bits.upload_chunky && (data->set.httpreq != HTTPREQ_GET)) {
/* not a chunky transfer but data is to be sent */
char *ptr = checkheaders(data, "Transfer-Encoding:");
if(ptr) {
/* Some kind of TE is requested, check if 'chunked' is chosen */
if(Curl_compareheader(ptr, "Transfer-Encoding:", "chunked"))
/* we have been told explicitly to upload chunky so deal with it! */
conn->bits.upload_chunky = TRUE;
}
}
if(conn->bits.upload_chunky) {
/* RFC2616 section 4.4:
Messages MUST NOT include both a Content-Length header field and a
non-identity transfer-coding. If the message does include a non-
identity transfer-coding, the Content-Length MUST be ignored. */
if(!checkheaders(data, "Transfer-Encoding:")) {
te = "Transfer-Encoding: chunked\r\n";
}
/* else
our header was already added, what to do now? */
else {
/* The "Transfer-Encoding:" header was already added. */
te = "";
}
}
if(data->cookies) {
@ -847,16 +1005,16 @@ CURLcode Curl_http(struct connectdata *conn)
return CURLE_HTTP_POST_ERROR;
}
http->storefread = data->set.fread; /* backup */
http->in = data->set.in; /* backup */
data->set.fread = (curl_read_callback)
Curl_FormReader; /* set the read function to read from the
generated form data */
data->set.in = (FILE *)&http->form;
/* set the read function to read from the generated form data */
conn->fread = (curl_read_callback)Curl_FormReader;
conn->fread_in = &http->form;
add_bufferf(req_buffer,
"Content-Length: %d\r\n", http->postsize);
http->sending = HTTPSEND_BODY;
if(!conn->bits.upload_chunky)
/* only add Content-Length if not uploading chunked */
add_bufferf(req_buffer,
"Content-Length: %d\r\n", http->postsize);
if(!checkheaders(data, "Expect:")) {
/* if not disabled explicitly we add a Expect: 100-continue
@ -896,7 +1054,7 @@ CURLcode Curl_http(struct connectdata *conn)
Curl_pgrsSetUploadSize(data, http->postsize);
/* fire away the whole request to the server */
result = add_buffer_send(conn->firstsocket, conn, req_buffer,
result = add_buffer_send(req_buffer, conn->firstsocket, conn,
&data->info.request_size);
if(result)
failf(data, "Failed sending POST request");
@ -914,22 +1072,22 @@ CURLcode Curl_http(struct connectdata *conn)
case HTTPREQ_PUT: /* Let's PUT the data to the server! */
if(data->set.infilesize>0) {
if((data->set.infilesize>0) && !conn->bits.upload_chunky)
/* only add Content-Length if not uploading chunked */
add_bufferf(req_buffer,
"Content-Length: %d\r\n\r\n", /* file size */
"Content-Length: %d\r\n", /* file size */
data->set.infilesize );
}
else
add_bufferf(req_buffer, "\015\012");
add_bufferf(req_buffer, "\r\n");
/* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, data->set.infilesize);
/* this sends the buffer and frees all the buffer resources */
result = add_buffer_send(conn->firstsocket, conn, req_buffer,
result = add_buffer_send(req_buffer, conn->firstsocket, conn,
&data->info.request_size);
if(result)
failf(data, "Faied sending POST request");
failf(data, "Failed sending POST request");
else
/* prepare for transfer */
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
@ -943,14 +1101,20 @@ CURLcode Curl_http(struct connectdata *conn)
case HTTPREQ_POST:
/* this is the simple POST, using x-www-form-urlencoded style */
if(!checkheaders(data, "Content-Length:"))
/* we allow replacing this header, although it isn't very wise to
actually set your own */
add_bufferf(req_buffer,
"Content-Length: %d\r\n",
data->set.postfieldsize?
data->set.postfieldsize:
(data->set.postfields?strlen(data->set.postfields):0) );
if(!conn->bits.upload_chunky) {
/* We only set Content-Length and allow a custom Content-Length if
we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
if(!checkheaders(data, "Content-Length:"))
/* we allow replacing this header, although it isn't very wise to
actually set your own */
add_bufferf(req_buffer,
"Content-Length: %d\r\n",
data->set.postfieldsize?
data->set.postfieldsize:
(data->set.postfields?strlen(data->set.postfields):0) );
}
if(!checkheaders(data, "Content-Type:"))
add_bufferf(req_buffer,
@ -958,18 +1122,28 @@ CURLcode Curl_http(struct connectdata *conn)
add_buffer(req_buffer, "\r\n", 2);
/* and here comes the actual data */
if(data->set.postfieldsize && data->set.postfields) {
add_buffer(req_buffer, data->set.postfields,
data->set.postfieldsize);
}
else if(data->set.postfields)
add_bufferf(req_buffer,
"%s",
data->set.postfields );
/* and here we setup the pointers to the actual data */
if(data->set.postfields) {
if(data->set.postfieldsize)
http->postsize = data->set.postfieldsize;
else
http->postsize = strlen(data->set.postfields);
http->postdata = data->set.postfields;
/* issue the request */
result = add_buffer_send(conn->firstsocket, conn, req_buffer,
http->sending = HTTPSEND_BODY;
conn->fread = (curl_read_callback)readmoredata;
conn->fread_in = (void *)conn;
/* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, http->postsize);
}
else
/* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, data->set.infilesize);
/* issue the request, headers-only */
result = add_buffer_send(req_buffer, conn->firstsocket, conn,
&data->info.request_size);
if(result)
@ -978,15 +1152,15 @@ CURLcode Curl_http(struct connectdata *conn)
result =
Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->readbytecount,
data->set.postfields?-1:conn->firstsocket,
data->set.postfields?NULL:&http->writebytecount);
conn->firstsocket,
&http->writebytecount);
break;
default:
add_buffer(req_buffer, "\r\n", 2);
/* issue the request */
result = add_buffer_send(conn->firstsocket, conn, req_buffer,
result = add_buffer_send(req_buffer, conn->firstsocket, conn,
&data->info.request_size);
if(result)
@ -995,7 +1169,8 @@ CURLcode Curl_http(struct connectdata *conn)
/* HTTP GET/HEAD download: */
result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->readbytecount,
-1, NULL); /* nothing to upload */
http->postdata?conn->firstsocket:-1,
http->postdata?&http->writebytecount:NULL);
}
if(result)
return result;

View File

@ -24,6 +24,10 @@
* $Id$
***************************************************************************/
#ifndef CURL_DISABLE_HTTP
bool Curl_compareheader(char *headerline, /* line to check */
const char *header, /* header keyword _with_ colon */
const char *content); /* content string to find */
/* ftp can use this as well */
CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
int tunnelsocket,

View File

@ -29,5 +29,40 @@ extern char *Curl_if2ip(char *interface, char *buf, int buf_size);
#else
#define Curl_if2ip(a,b,c) NULL
#endif
#ifdef __INTERIX
/* Nedelcho Stanev's work-around for SFU 3.0 */
struct ifreq {
#define IFNAMSIZ 16
#define IFHWADDRLEN 6
union {
char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */
} ifr_ifrn;
union {
struct sockaddr ifru_addr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short ifru_flags;
int ifru_metric;
int ifru_mtu;
} ifr_ifru;
};
/* This define was added by Daniel to avoid an extra #ifdef INTERIX in the
C code. */
#define ifr_dstaddr ifr_addr
#define ifr_name ifr_ifrn.ifrn_name /* interface name */
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
#define ifr_flags ifr_ifru.ifru_flags /* flags */
#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
#define ifr_metric ifr_ifru.ifru_metric /* metric */
#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */
#endif /* interix */
#endif

View File

@ -202,6 +202,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
ssize_t nread;
int l = sizeof(conn->local_addr);
struct SessionHandle *data = conn->data;
CURLcode result;
if(getsockname(conn->firstsocket,
(struct sockaddr *)LOCAL_ADDR, &l) < 0)
@ -246,13 +247,15 @@ krb4_auth(void *app_data, struct connectdata *conn)
return AUTH_CONTINUE;
}
if(Curl_ftpsendf(conn, "ADAT %s", p))
result = Curl_ftpsendf(conn, "ADAT %s", p);
free(p);
if(result)
return -2;
nread = Curl_GetFTPResponse(data->state.buffer, conn, NULL);
if(nread < 0)
if(Curl_GetFTPResponse(&nread, conn, NULL))
return -1;
free(p);
if(data->state.buffer[0] != '2'){
Curl_failf(data, "Server didn't accept auth data");
@ -299,7 +302,7 @@ struct Curl_sec_client_mech Curl_krb4_client_mech = {
krb4_decode
};
void Curl_krb_kauth(struct connectdata *conn)
CURLcode Curl_krb_kauth(struct connectdata *conn)
{
des_cblock key;
des_key_schedule schedule;
@ -309,18 +312,19 @@ void Curl_krb_kauth(struct connectdata *conn)
char passwd[100];
int tmp;
ssize_t nread;
int save;
CURLcode result;
save = Curl_set_command_prot(conn, prot_private);
if(Curl_ftpsendf(conn, "SITE KAUTH %s", conn->data->state.user))
return;
result = Curl_ftpsendf(conn, "SITE KAUTH %s", conn->data->state.user);
nread = Curl_GetFTPResponse(conn->data->state.buffer,
conn, NULL);
if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/;
if(result)
return result;
result = Curl_GetFTPResponse(&nread, conn, NULL);
if(result)
return result;
if(conn->data->state.buffer[0] != '3'){
Curl_set_command_prot(conn, save);
@ -331,7 +335,7 @@ void Curl_krb_kauth(struct connectdata *conn)
if(!p) {
Curl_failf(conn->data, "Bad reply from server");
Curl_set_command_prot(conn, save);
return;
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
p += 2;
@ -339,7 +343,7 @@ void Curl_krb_kauth(struct connectdata *conn)
if(tmp < 0) {
Curl_failf(conn->data, "Failed to decode base64 in reply.\n");
Curl_set_command_prot(conn, save);
return;
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
tkt.length = tmp;
tktcopy.length = tkt.length;
@ -348,7 +352,7 @@ void Curl_krb_kauth(struct connectdata *conn)
if(!p) {
Curl_failf(conn->data, "Bad reply from server");
Curl_set_command_prot(conn, save);
return;
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
name = p + 2;
for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@ -376,19 +380,21 @@ void Curl_krb_kauth(struct connectdata *conn)
if(Curl_base64_encode(tktcopy.dat, tktcopy.length, &p) < 0) {
failf(conn->data, "Out of memory base64-encoding.");
Curl_set_command_prot(conn, save);
return;
return CURLE_OUT_OF_MEMORY;
}
memset (tktcopy.dat, 0, tktcopy.length);
if(Curl_ftpsendf(conn, "SITE KAUTH %s %s", name, p))
return;
nread = Curl_GetFTPResponse(conn->data->state.buffer,
conn, NULL);
if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/;
result = Curl_ftpsendf(conn, "SITE KAUTH %s %s", name, p);
free(p);
if(result)
return result;
result = Curl_GetFTPResponse(&nread, conn, NULL);
if(result)
return result;
Curl_set_command_prot(conn, save);
return CURLE_OK;
}
#endif /* KRB4 */

View File

@ -22,6 +22,6 @@
*
* $Id$
***************************************************************************/
void Curl_krb_kauth(struct connectdata *conn);
CURLcode Curl_krb_kauth(struct connectdata *conn);
#endif

View File

@ -313,9 +313,8 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
easy->easy_handle->hostcache = Curl_global_host_cache_get();
}
else {
if (multi->hostcache == NULL) {
multi->hostcache = Curl_hash_alloc(7, Curl_freeaddrinfo);
}
if (multi->hostcache == NULL)
multi->hostcache = Curl_hash_alloc(7, Curl_freednsinfo);
easy->easy_handle->hostcache = multi->hostcache;
}

View File

@ -278,32 +278,6 @@ Curl_sec_write(struct connectdata *conn, int fd, char *buffer, int length)
return tx;
}
int
Curl_sec_vfprintf2(struct connectdata *conn, FILE *f, const char *fmt, va_list ap)
{
char *buf;
int ret;
if(conn->data_prot == prot_clear)
return vfprintf(f, fmt, ap);
else {
buf = aprintf(fmt, ap);
ret = buffer_write(&conn->out_buffer, buf, strlen(buf));
free(buf);
return ret;
}
}
int
Curl_sec_fprintf2(struct connectdata *conn, FILE *f, const char *fmt, ...)
{
int ret;
va_list ap;
va_start(ap, fmt);
ret = Curl_sec_vfprintf2(conn, f, fmt, ap);
va_end(ap);
return ret;
}
int
Curl_sec_putc(struct connectdata *conn, int c, FILE *F)
{
@ -313,7 +287,8 @@ Curl_sec_putc(struct connectdata *conn, int c, FILE *F)
buffer_write(&conn->out_buffer, &ch, 1);
if(c == '\n' || conn->out_buffer.index >= 1024 /* XXX */) {
Curl_sec_write(conn, fileno(F), conn->out_buffer.data, conn->out_buffer.index);
Curl_sec_write(conn, fileno(F), conn->out_buffer.data,
conn->out_buffer.index);
conn->out_buffer.index = 0;
}
return c;
@ -346,53 +321,6 @@ Curl_sec_read_msg(struct connectdata *conn, char *s, int level)
return code;
}
/* modified to return how many bytes written, or -1 on error ***/
int
Curl_sec_vfprintf(struct connectdata *conn, FILE *f, const char *fmt, va_list ap)
{
int ret = 0;
char *buf;
void *enc;
int len;
if(!conn->sec_complete)
return vfprintf(f, fmt, ap);
buf = aprintf(fmt, ap);
len = (conn->mech->encode)(conn->app_data, buf, strlen(buf),
conn->command_prot, &enc,
conn);
free(buf);
if(len < 0) {
failf(conn->data, "Failed to encode command.");
return -1;
}
if(Curl_base64_encode(enc, len, &buf) < 0){
failf(conn->data, "Out of memory base64-encoding.");
return -1;
}
if(conn->command_prot == prot_safe)
ret = fprintf(f, "MIC %s", buf);
else if(conn->command_prot == prot_private)
ret = fprintf(f, "ENC %s", buf);
else if(conn->command_prot == prot_confidential)
ret = fprintf(f, "CONF %s", buf);
free(buf);
return ret;
}
int
Curl_sec_fprintf(struct connectdata *conn, FILE *f, const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = Curl_sec_vfprintf(conn, f, fmt, ap);
va_end(ap);
return ret;
}
enum protection_level
Curl_set_command_prot(struct connectdata *conn, enum protection_level level)
{
@ -414,14 +342,14 @@ sec_prot_internal(struct connectdata *conn, int level)
}
if(level){
int code;
if(Curl_ftpsendf(conn, "PBSZ %u", s))
return -1;
nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, NULL);
if(nread < 0)
if(Curl_GetFTPResponse(&nread, conn, &code))
return -1;
if(conn->data->state.buffer[0] != '2'){
if(code/100 != '2'){
failf(conn->data, "Failed to set protection buffer size.");
return -1;
}
@ -437,8 +365,7 @@ sec_prot_internal(struct connectdata *conn, int level)
if(Curl_ftpsendf(conn, "PROT %c", level["CSEP"]))
return -1;
nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, NULL);
if(nread < 0)
if(Curl_GetFTPResponse(&nread, conn, NULL))
return -1;
if(conn->data->state.buffer[0] != '2'){
@ -496,8 +423,7 @@ Curl_sec_login(struct connectdata *conn)
if(Curl_ftpsendf(conn, "AUTH %s", (*m)->name))
return -1;
nread = Curl_GetFTPResponse(conn->data->state.buffer, conn, &ftpcode);
if(nread < 0)
if(Curl_GetFTPResponse(&nread, conn, &ftpcode))
return -1;
if(conn->data->state.buffer[0] != '3'){

View File

@ -154,9 +154,19 @@ void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
vsnprintf(data->set.errorbuffer, CURL_ERROR_SIZE, fmt, ap);
data->state.errorbuf = TRUE; /* wrote error string */
if(data->set.verbose)
Curl_debug(data, CURLINFO_TEXT, data->set.errorbuffer,
strlen(data->set.errorbuffer));
if(data->set.verbose) {
int len = strlen(data->set.errorbuffer);
bool doneit=FALSE;
if(len < CURL_ERROR_SIZE) {
doneit = TRUE;
data->set.errorbuffer[len] = '\n';
data->set.errorbuffer[++len] = '\0';
}
Curl_debug(data, CURLINFO_TEXT, data->set.errorbuffer, len);
if(doneit)
/* cut off the newline again */
data->set.errorbuffer[--len]=0;
}
}
va_end(ap);
}
@ -235,6 +245,9 @@ CURLcode Curl_write(struct connectdata *conn, int sockfd,
/* this is basicly the EWOULDBLOCK equivalent */
*written = 0;
return CURLE_OK;
case SSL_ERROR_SYSCALL:
failf(conn->data, "SSL_write() returned SYSCALL, errno = %d\n", errno);
return CURLE_SEND_ERROR;
}
/* a true error */
failf(conn->data, "SSL_write() return error %d\n", err);
@ -328,36 +341,29 @@ int Curl_read(struct connectdata *conn,
ssize_t *n)
{
ssize_t nread;
*n=0; /* reset amount to zero */
#ifdef USE_SSLEAY
if (conn->ssl.use) {
bool loop=TRUE;
int err;
do {
nread = SSL_read(conn->ssl.handle, buf, buffersize);
nread = SSL_read(conn->ssl.handle, buf, buffersize);
if(nread >= 0)
/* successful read */
break;
err = SSL_get_error(conn->ssl.handle, nread);
if(nread < 0) {
/* failed SSL_read */
int err = SSL_get_error(conn->ssl.handle, nread);
switch(err) {
case SSL_ERROR_NONE: /* this is not an error */
case SSL_ERROR_ZERO_RETURN: /* no more data */
loop=0; /* get out of loop */
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
/* if there's data pending, then we re-invoke SSL_read() */
break;
/* there's data pending, re-invoke SSL_read() */
return -1; /* basicly EWOULDBLOCK */
default:
failf(conn->data, "SSL read error: %d", err);
return CURLE_RECV_ERROR;
}
} while(loop);
if(loop && SSL_pending(conn->ssl.handle))
return -1; /* basicly EWOULDBLOCK */
}
}
else {
#endif

View File

@ -30,13 +30,6 @@ void Curl_failf(struct SessionHandle *, const char *fmt, ...);
#define infof Curl_infof
#define failf Curl_failf
struct send_buffer {
char *buffer;
size_t size_max;
size_t size_used;
};
typedef struct send_buffer send_buffer;
#define CLIENTWRITE_BODY 1
#define CLIENTWRITE_HEADER 2
#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)

View File

@ -35,9 +35,8 @@
#define CURL_DISABLE_GOPHER
#endif
#if !defined(WIN32) && defined(_WIN32)
/* This _might_ be a good Borland fix. Please report whether this works or
not! */
#if !defined(WIN32) && defined(__WIN32__)
/* This should be a good Borland fix. Alexander J. Oss told us! */
#define WIN32
#endif

52
Source/CTest/Curl/share.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef __CURL_SHARE_H
#define __CURL_SHARE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
***************************************************************************/
#include "setup.h"
#include <curl/curl.h>
/* this struct is libcurl-private, don't export details */
struct Curl_share {
unsigned int specifier;
unsigned int locked;
unsigned int dirty;
curl_lock_function lockfunc;
curl_unlock_function unlockfunc;
void *clientdata;
};
CURLSHcode Curl_share_aquire_lock (struct SessionHandle *, curl_lock_data);
CURLSHcode Curl_share_release_lock (struct SessionHandle *, curl_lock_data);
#endif /* __CURL_SHARE_H */
/*
* local variables:
* eval: (load-file "../curl-mode.el")
* end:
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/

View File

@ -275,7 +275,8 @@ int cert_stuff(struct connectdata *conn,
if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx,
key_file,
file_type) != 1) {
failf(data, "unable to set private key file\n");
failf(data, "unable to set private key file: '%s' type %s\n",
key_file, key_type?key_type:"PEM");
return 0;
}
break;
@ -324,10 +325,15 @@ int cert_stuff(struct connectdata *conn,
ssl=SSL_new(conn->ssl.ctx);
x509=SSL_get_certificate(ssl);
if (x509 != NULL)
EVP_PKEY_copy_parameters(X509_get_pubkey(x509),
SSL_get_privatekey(ssl));
/* This version was provided by Evan Jordan and is supposed to not
leak memory as the previous version: */
if (x509 != NULL) {
EVP_PKEY *pktmp = X509_get_pubkey(x509);
EVP_PKEY_copy_parameters(pktmp,SSL_get_privatekey(ssl));
EVP_PKEY_free(pktmp);
}
SSL_free(ssl);
/* If we are using DSA, we can copy the parameters from
@ -666,6 +672,44 @@ static int Curl_ASN1_UTCTIME_output(struct connectdata *conn,
#endif
/* ====================================================== */
static int
cert_hostcheck(const char *certname, const char *hostname)
{
char *tmp;
const char *certdomain;
if(!certname ||
strlen(certname)<3 ||
!hostname ||
!strlen(hostname)) /* sanity check */
return 0;
if(strequal(certname, hostname)) /* trivial case */
return 1;
certdomain = certname + 1;
if((certname[0] != '*') || (certdomain[0] != '.'))
return 0; /* not a wildcard certificate, check failed */
if(!strchr(certdomain+1, '.'))
return 0; /* the certificate must have at least another dot in its name */
/* find 'certdomain' within 'hostname' */
tmp = strstr(hostname, certdomain);
if(tmp) {
/* ok the certname's domain matches the hostname, let's check that it's a
tail-match */
if(strequal(tmp, certdomain))
/* looks like a match. Just check we havent swallowed a '.' */
return tmp == strchr(hostname, '.');
else
return 0;
}
return 0;
}
/* ====================================================== */
CURLcode
Curl_SSLConnect(struct connectdata *conn)
@ -904,7 +948,7 @@ Curl_SSLConnect(struct connectdata *conn)
return CURLE_SSL_PEER_CERTIFICATE;
}
if (!strequal(peer_CN, conn->hostname)) {
if (!cert_hostcheck(peer_CN, conn->hostname)) {
if (data->set.ssl.verifyhost > 1) {
failf(data, "SSL: certificate subject name '%s' does not match "
"target host name '%s'",

File diff suppressed because it is too large Load Diff

View File

@ -101,6 +101,7 @@
#include "strequal.h"
#include "escape.h"
#include "strtok.h"
#include "share.h"
/* And now for the protocols */
#include "ftp.h"
@ -1071,8 +1072,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
case CURLOPT_SHARE:
{
curl_share *set;
set = va_arg(param, curl_share *);
struct Curl_share *set;
set = va_arg(param, struct Curl_share *);
if(data->share)
data->share->dirty--;
@ -1088,6 +1089,20 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
data->set.proxytype = va_arg(param, long);
break;
case CURLOPT_PRIVATE:
/*
* Set private data pointer.
*/
data->set.private = va_arg(param, char *);
break;
case CURLOPT_HTTP200ALIASES:
/*
* Set a list of aliases for HTTP 200 in response header
*/
data->set.http200aliases = va_arg(param, struct curl_slist *);
break;
default:
/* unknown tag and its companion, just ignore: */
return CURLE_FAILED_INIT; /* correct this */
@ -1603,6 +1618,9 @@ static CURLcode ConnectPlease(struct connectdata *conn,
return result;
}
/*
* ALERT! The 'dns' pointer being passed in here might be NULL at times.
*/
static void verboseconnect(struct connectdata *conn,
struct Curl_dns_entry *dns)
{
@ -1667,6 +1685,12 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
struct SessionHandle *data = conn->data;
CURLcode result=CURLE_OK;
if(conn->bits.tcpconnect)
/* We already are connected, get back. This may happen when the connect
worked fine in the first call, like when we connect to a local server
or proxy. */
return CURLE_OK;
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
if(data->set.verbose)
@ -1779,6 +1803,9 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/* else, no chunky upload */
FALSE;
conn->fread = data->set.fread;
conn->fread_in = data->set.in;
/***********************************************************
* We need to allocate memory to store the path in. We get the size of the
* full URL to be sure, and we need to make it at least 256 bytes since
@ -2286,6 +2313,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/* Setup a "faked" transfer that'll do nothing */
if(CURLE_OK == result) {
conn->bits.tcpconnect = TRUE; /* we are "connected */
result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */
-1, NULL); /* no upload */
}
@ -2463,6 +2491,9 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/* no name given, get the password only */
sscanf(userpass, ":%127[^@]", data->state.passwd);
/* we have set the password */
data->state.passwdgiven = TRUE;
if(data->state.user[0]) {
char *newname=curl_unescape(data->state.user, 0);
if(strlen(newname) < sizeof(data->state.user)) {
@ -2498,14 +2529,17 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/* the name is given, get user+password */
sscanf(data->set.userpwd, "%127[^:]:%127[^\n]",
data->state.user, data->state.passwd);
if(strchr(data->set.userpwd, ':'))
/* a colon means the password was given, even if blank */
data->state.passwdgiven = TRUE;
}
else
/* no name given, get the password only */
/* no name given, starts with a colon, get the password only */
sscanf(data->set.userpwd+1, "%127[^\n]", data->state.passwd);
}
if (data->set.use_netrc != CURL_NETRC_IGNORED &&
data->state.passwd[0] == '\0' ) { /* need passwd */
!data->state.passwdgiven) { /* need passwd */
if(Curl_parsenetrc(conn->hostname,
data->state.user,
data->state.passwd)) {
@ -2516,8 +2550,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
}
/* if we have a user but no password, ask for one */
if(conn->bits.user_passwd &&
!data->state.passwd[0] ) {
if(conn->bits.user_passwd && !data->state.passwdgiven ) {
if(data->set.fpasswd(data->set.passwd_client,
"password:", data->state.passwd,
sizeof(data->state.passwd)))
@ -2528,9 +2561,12 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/* If our protocol needs a password and we have none, use the defaults */
if ( (conn->protocol & (PROT_FTP|PROT_HTTP)) &&
!conn->bits.user_passwd) {
!conn->bits.user_passwd &&
!data->state.passwdgiven) {
strcpy(data->state.user, CURL_DEFAULT_USER);
strcpy(data->state.passwd, CURL_DEFAULT_PASSWORD);
/* This is the default password, so DON'T set conn->bits.user_passwd */
}
@ -2782,14 +2818,21 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/* Connect only if not already connected! */
result = ConnectPlease(conn, hostaddr, &connected);
if(connected)
if(connected) {
result = Curl_protocol_connect(conn, hostaddr);
if(CURLE_OK == result)
conn->bits.tcpconnect = TRUE;
}
else
conn->bits.tcpconnect = FALSE;
if(CURLE_OK != result)
return result;
}
else {
Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
conn->bits.tcpconnect = TRUE;
if(data->set.verbose)
verboseconnect(conn, hostaddr);
}

View File

@ -157,6 +157,8 @@ struct ssl_config_data {
struct HTTP {
struct FormData *sendit;
int postsize;
char *postdata;
const char *p_pragma; /* Pragma: string */
const char *p_accept; /* Accept: string */
long readbytecount;
@ -164,10 +166,24 @@ struct HTTP {
/* For FORM posting */
struct Form form;
curl_read_callback storefread;
FILE *in;
struct Curl_chunker chunk;
struct back {
curl_read_callback fread; /* backup storage for fread pointer */
void *fread_in; /* backup storage for fread_in pointer */
char *postdata;
int postsize;
} backup;
enum {
HTTPSEND_NADA, /* init */
HTTPSEND_REQUEST, /* sending a request */
HTTPSEND_BODY, /* sending body */
HTTPSEND_LAST /* never use this */
} sending;
void *send_buffer; /* used if the request couldn't be sent in one chunk,
points to an allocated send_buffer struct */
};
/****************************************************************************
@ -190,7 +206,9 @@ struct FTP {
read the line, just ignore the result. */
bool no_transfer; /* nothing was transfered, (possibly because a resumed
transfer already was complete) */
long response_time; /* When no timeout is given, this is the amount of
seconds we await for an FTP response. Initialized
in Curl_ftp_connect() */
};
/****************************************************************************
@ -220,8 +238,14 @@ struct ConnectBits {
bool upload_chunky; /* set TRUE if we are doing chunked transfer-encoding
on upload */
bool getheader; /* TRUE if header parsing is wanted */
bool getheader; /* TRUE if header parsing is wanted */
bool forbidchunk; /* used only to explicitly forbid chunk-upload for
specific upload buffers. See readmoredata() in
http.c for details. */
bool tcpconnect; /* the tcp stream (or simimlar) is connected, this
is set the first time on the first connect function
call */
};
/*
@ -456,6 +480,9 @@ struct connectdata {
and the 'upload_present' contains the number of bytes available at this
position */
char *upload_fromhere;
curl_read_callback fread; /* function that reads the input */
void *fread_in; /* pointer to pass to the fread() above */
};
/* The end of connectdata. 08/27/02 jhrg */
@ -543,6 +570,9 @@ struct UrlState {
char proxyuser[MAX_CURL_USER_LENGTH];
char proxypasswd[MAX_CURL_PASSWORD_LENGTH];
bool passwdgiven; /* set TRUE if an application-provided password has been
set */
struct timeval keeps_speed; /* for the progress meter really */
/* 'connects' will be an allocated array with pointers. If the pointer is
@ -631,7 +661,7 @@ struct UserDefined {
bool free_referer; /* set TRUE if 'referer' points to a string we
allocated */
char *useragent; /* User-Agent string */
char *encoding; /* Accept-Encoding string 08/28/02 jhrg */
char *encoding; /* Accept-Encoding string */
char *postfields; /* if POST, set the fields' values here */
size_t postfieldsize; /* if POST, this might have a size to use instead of
strlen(), and then the data *may* be binary (contain
@ -686,6 +716,10 @@ struct UserDefined {
int dns_cache_timeout; /* DNS cache timeout */
long buffer_size; /* size of receive buffer to use */
char *private; /* Private data */
struct curl_slist *http200aliases; /* linked list of aliases for http200 */
/* Here follows boolean settings that define how to behave during
this session. They are STATIC, set by libcurl users or at least initially
@ -734,7 +768,7 @@ struct UserDefined {
struct SessionHandle {
curl_hash *hostcache;
curl_share *share; /* Share, handles global variable mutexing */
struct Curl_share *share; /* Share, handles global variable mutexing */
struct UserDefined set; /* values set by the libcurl user */
struct DynamicStatic change; /* possibly modified userdefined data */