Follow-up fix for the proxy fix I did for Jon Nelson's bug. It turned out I

was a bit too quick and broke test case 1101 with that change. The order of
some of the setups is sensitive. I now changed it slightly again.
This commit is contained in:
Daniel Stenberg 2009-12-16 23:11:47 +00:00
Родитель 002ed5f298
Коммит 7603a29fc3
2 изменённых файлов: 94 добавлений и 60 удалений

15
CHANGES
Просмотреть файл

@ -6,6 +6,21 @@
Changelog Changelog
Daniel Stenberg (17 Dec 2009)
- Follow-up fix for the proxy fix I did for Jon Nelson's bug. It turned out I
was a bit too quick and broke test case 1101 with that change. The order of
some of the setups is sensitive. I now changed it slightly again to make
sure we do them in this order:
1 - parse URL and figure out what protocol is used in the URL
2 - prepend protocol:// to URL if missing
3 - parse name+password off URL, which needs to know what protocol is used
(since only some allows for name+password in the URL)
4 - figure out if a proxy should be used set by an option
5 - if no proxy option, check proxy environment variables
6 - run the protocol-specific setup function, which needs to have the proxy
already set
Daniel Stenberg (15 Dec 2009) Daniel Stenberg (15 Dec 2009)
- Jon Nelson found a regression that turned out to be a flaw in how libcurl - Jon Nelson found a regression that turned out to be a flaw in how libcurl
detects and uses proxies based on the environment variables. If the proxy detects and uses proxies based on the environment variables. If the proxy

139
lib/url.c
Просмотреть файл

@ -3255,11 +3255,53 @@ static struct connectdata *allocate_conn(void)
return conn; return conn;
} }
static CURLcode findprotocol(struct SessionHandle *data,
struct connectdata *conn)
{
const struct Curl_handler * const *pp;
const struct Curl_handler *p;
/* Scan protocol handler table and match against 'protostr' to set a few
variables based on the URL. Now that the handler may be changed later
when the protocol specific setup function is called. */
for (pp = protocols; (p = *pp) != NULL; pp++) {
if(Curl_raw_equal(p->scheme, conn->protostr)) {
/* Protocol found in table. Check if allowed */
if(!(data->set.allowed_protocols & p->protocol))
/* nope, get out */
break;
/* it is allowed for "normal" request, now do an extra check if this is
the result of a redirect */
if(data->state.this_is_a_follow &&
!(data->set.redir_protocols & p->protocol))
/* nope, get out */
break;
/* Perform setup complement if some. */
conn->handler = p;
conn->protocol |= p->protocol;
/* 'port' and 'remote_port' are set in setup_connection_internals() */
return CURLE_OK;
}
}
/* The protocol was not found in the table, but we don't have to assign it
to anything since it is already assigned to a dummy-struct in the
create_conn() function when the connectdata struct is allocated. */
failf(data, "Protocol %s not supported or disabled in " LIBCURL_NAME,
conn->protostr);
return CURLE_UNSUPPORTED_PROTOCOL;
}
/* /*
* Parse URL and fill in the relevant members of the connection struct. * Parse URL and fill in the relevant members of the connection struct.
*/ */
static CURLcode ParseURLAndFillConnection(struct SessionHandle *data, static CURLcode parseurlandfillconn(struct SessionHandle *data,
struct connectdata *conn) struct connectdata *conn)
{ {
char *at; char *at;
char *tmp; char *tmp;
@ -3455,8 +3497,8 @@ static CURLcode ParseURLAndFillConnection(struct SessionHandle *data,
* conn->host.name is B * conn->host.name is B
* data->state.path is /C * data->state.path is /C
*/ */
(void)rc;
return CURLE_OK; return findprotocol(data, conn);
} }
static void llist_dtor(void *user, void *element) static void llist_dtor(void *user, void *element)
@ -3502,10 +3544,8 @@ static CURLcode setup_range(struct SessionHandle *data)
* Setup connection internals specific to the requested protocol. * Setup connection internals specific to the requested protocol.
* This MUST get called after proxy magic has been figured out. * This MUST get called after proxy magic has been figured out.
***************************************************************/ ***************************************************************/
static CURLcode setup_connection_internals(struct SessionHandle *data, static CURLcode setup_connection_internals(struct connectdata *conn)
struct connectdata *conn)
{ {
const struct Curl_handler * const * pp;
const struct Curl_handler * p; const struct Curl_handler * p;
CURLcode result; CURLcode result;
@ -3513,47 +3553,26 @@ static CURLcode setup_connection_internals(struct SessionHandle *data,
/* Scan protocol handler table. */ /* Scan protocol handler table. */
for (pp = protocols; (p = *pp) != NULL; pp++) /* Perform setup complement if some. */
if(Curl_raw_equal(p->scheme, conn->protostr)) { p = conn->handler;
/* Protocol found in table. Check if allowed */
if(!(data->set.allowed_protocols & p->protocol))
/* nope, get out */
break;
/* it is allowed for "normal" request, now do an extra check if this is if(p->setup_connection) {
the result of a redirect */ result = (*p->setup_connection)(conn);
if(data->state.this_is_a_follow &&
!(data->set.redir_protocols & p->protocol))
/* nope, get out */
break;
/* Perform setup complement if some. */ if(result != CURLE_OK)
conn->handler = p; return result;
if(p->setup_connection) { p = conn->handler; /* May have changed. */
result = (*p->setup_connection)(conn); }
if(result != CURLE_OK) if(conn->port < 0)
return result; /* we check for -1 here since if proxy was detected already, this
was very likely already set to the proxy port */
conn->port = p->defport;
conn->remote_port = (unsigned short)p->defport;
conn->protocol |= p->protocol;
p = conn->handler; /* May have changed. */ return CURLE_OK;
}
if(conn->port < 0)
/* we check for -1 here since if proxy was detected already, this
was very likely already set to the proxy port */
conn->port = p->defport;
conn->remote_port = (unsigned short)p->defport;
conn->protocol |= p->protocol;
return CURLE_OK;
}
/* The protocol was not found in the table, but we don't have to assign it
to anything since it is already assigned to a dummy-struct in the
create_conn() function when the connectdata struct is allocated. */
failf(data, "Protocol %s not supported or disabled in " LIBCURL_NAME,
conn->protostr);
return CURLE_UNSUPPORTED_PROTOCOL;
} }
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
@ -3989,7 +4008,7 @@ static CURLcode parse_remote_port(struct SessionHandle *data,
char endbracket; char endbracket;
/* Note that at this point, the IPv6 address cannot contain any scope /* Note that at this point, the IPv6 address cannot contain any scope
suffix as that has already been removed in the ParseURLAndFillConnection() suffix as that has already been removed in the parseurlandfillconn()
function */ function */
if((1 == sscanf(conn->host.name, "[%*45[0123456789abcdefABCDEF:.]%c", if((1 == sscanf(conn->host.name, "[%*45[0123456789abcdefABCDEF:.]%c",
&endbracket)) && &endbracket)) &&
@ -4423,7 +4442,7 @@ static CURLcode create_conn(struct SessionHandle *data,
conn->host.name = conn->host.rawalloc; conn->host.name = conn->host.rawalloc;
conn->host.name[0] = 0; conn->host.name[0] = 0;
result = ParseURLAndFillConnection(data, conn); result = parseurlandfillconn(data, conn);
if(result != CURLE_OK) { if(result != CURLE_OK) {
return result; return result;
} }
@ -4449,6 +4468,14 @@ static CURLcode create_conn(struct SessionHandle *data,
conn->protocol &= ~PROT_MISSING; /* switch that one off again */ conn->protocol &= ~PROT_MISSING; /* switch that one off again */
} }
/*************************************************************
* Parse a user name and password in the URL and strip it out
* of the host name
*************************************************************/
result = parse_url_userpass(data, conn, user, passwd);
if(result != CURLE_OK)
return result;
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
/************************************************************* /*************************************************************
* Extract the user and password from the authentication string * Extract the user and password from the authentication string
@ -4523,20 +4550,12 @@ static CURLcode create_conn(struct SessionHandle *data,
* Setup internals depending on protocol. Needs to be done after * Setup internals depending on protocol. Needs to be done after
* we figured out what/if proxy to use. * we figured out what/if proxy to use.
*************************************************************/ *************************************************************/
result = setup_connection_internals(data, conn); result = setup_connection_internals(conn);
if(result != CURLE_OK) { if(result != CURLE_OK) {
Curl_safefree(proxy); Curl_safefree(proxy);
return result; return result;
} }
/*************************************************************
* Parse a user name and password in the URL and strip it out
* of the host name
*************************************************************/
result = parse_url_userpass(data, conn, user, passwd);
if(result != CURLE_OK)
return result;
/*********************************************************************** /***********************************************************************
* file: is a special case in that it doesn't need a network connection * file: is a special case in that it doesn't need a network connection
***********************************************************************/ ***********************************************************************/
@ -4598,12 +4617,6 @@ static CURLcode create_conn(struct SessionHandle *data,
if(result != CURLE_OK) if(result != CURLE_OK)
return result; return result;
/*************************************************************
* Check the current list of connections to see if we can
* re-use an already existing one or if we have to create a
* new one.
*************************************************************/
/* Get a cloned copy of the SSL config situation stored in the /* Get a cloned copy of the SSL config situation stored in the
connection struct. But to get this going nicely, we must first make connection struct. But to get this going nicely, we must first make
sure that the strings in the master copy are pointing to the correct sure that the strings in the master copy are pointing to the correct
@ -4624,6 +4637,12 @@ static CURLcode create_conn(struct SessionHandle *data,
if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config))
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
/*************************************************************
* Check the current list of connections to see if we can
* re-use an already existing one or if we have to create a
* new one.
*************************************************************/
/* reuse_fresh is TRUE if we are told to use a new connection by force, but /* reuse_fresh is TRUE if we are told to use a new connection by force, but
we only acknowledge this option if this is not a re-used connection we only acknowledge this option if this is not a re-used connection
already (which happens due to follow-location or during a HTTP already (which happens due to follow-location or during a HTTP