urlpieces: remove members that live in peers/creds

Remove members of `struct urlpieces` that now live in peers/creds.

Change all remaining uses of those urlpieces.

When comparing schemes, use the protocol constants.

Closes #22171
This commit is contained in:
Stefan Eissing 2026-06-25 11:36:23 +02:00 committed by Daniel Stenberg
parent cfc7922377
commit 18475e662c
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
11 changed files with 65 additions and 54 deletions

View file

@ -2115,7 +2115,7 @@ static CURLcode http_target(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
}
if(curl_strequal("http", data->state.up.scheme)) {
if(data->state.origin->scheme == &Curl_scheme_http) {
/* when getting HTTP, we do not want the userinfo the URL */
uc = curl_url_set(h, CURLUPART_USER, NULL, 0);
if(uc) {
@ -2157,7 +2157,7 @@ static CURLcode http_target(struct Curl_easy *data,
if(result)
return result;
if(curl_strequal("ftp", data->state.up.scheme) &&
if((data->state.origin->scheme == &Curl_scheme_ftp) &&
data->set.proxy_transfer_mode) {
/* when doing ftp, append ;type=<a|i> if not present */
size_t len = strlen(path);

View file

@ -449,10 +449,10 @@ CURLcode Curl_http_proxy_create_tunnel_request(
return result;
if(udp_tunnel)
infof(data, "Establishing %s proxy UDP tunnel to %s:%s",
infof(data, "Establishing %s proxy UDP tunnel to %s:%u",
(ver == PROXY_HTTP_V2) ? "HTTP/2" :
(ver == PROXY_HTTP_V3) ? "HTTP/3" : "HTTP",
data->state.up.hostname, data->state.up.port);
dest->user_hostname, dest->port);
else
infof(data, "Establishing %s proxy tunnel to %s",
(ver == PROXY_HTTP_V2) ? "HTTP/2" :

View file

@ -739,7 +739,8 @@ static curl_ldap_num_t ldap_url_parse2_low(struct Curl_easy *data,
if(!data ||
!data->state.up.path ||
data->state.up.path[0] != '/' ||
!curl_strnequal("LDAP", data->state.up.scheme, 4))
((data->state.origin->scheme != &Curl_scheme_ldap) &&
(data->state.origin->scheme != &Curl_scheme_ldaps)))
return LDAP_INVALID_SYNTAX;
ludp->lud_scope = LDAP_SCOPE_BASE;

View file

@ -164,7 +164,7 @@ static CURLcode oldap_map_error(int rc, CURLcode result)
static CURLcode oldap_url_parse(struct Curl_easy *data, LDAPURLDesc **ludp)
{
CURLcode result = CURLE_OK;
int rc = LDAP_URL_ERR_BADURL;
int rc;
static const char * const url_errs[] = {
"success",
"out of memory",
@ -180,9 +180,16 @@ static CURLcode oldap_url_parse(struct Curl_easy *data, LDAPURLDesc **ludp)
};
*ludp = NULL;
if(!data->state.up.user && !data->state.up.password &&
!data->state.up.options)
/* `ldap_url_parse() seems to be terrible with urls
* that have user/pass/options in it. So when we have options or
* creds from the url, fail without calling the function.
* Yes, this is super-weird code and I do not like it. */
if((data->state.creds && (data->state.creds->source == CREDS_URL)) ||
data->state.up.options)
rc = LDAP_URL_ERR_BADURL;
else
rc = ldap_url_parse(Curl_bufref_ptr(&data->state.url), ludp);
if(rc != LDAP_URL_SUCCESS) {
const char *msg = "url parsing problem";
@ -605,7 +612,7 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
if(result)
goto out;
li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme);
li->proto = ldap_pvt_url_scheme2proto(data->state.origin->scheme->name);
/* Initialize the SASL storage */
Curl_sasl_init(&li->sasl, data, &saslldap);
@ -614,10 +621,11 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
if(result)
goto out;
hosturl = curl_maprintf("%s://%s:%d",
hosturl = curl_maprintf("%s://%s:%u",
conn->scheme->name,
(data->state.up.hostname[0] == '[') ?
data->state.up.hostname : conn->origin->hostname,
conn->origin->ipv6 ?
conn->origin->user_hostname :
conn->origin->hostname,
conn->origin->port);
if(!hosturl) {
result = CURLE_OUT_OF_MEMORY;

View file

@ -74,6 +74,7 @@
#include "peer.h"
#include "urldata.h"
#include "url.h"
#include "urlapi-int.h"
#include "vtls/vtls.h"
struct peer_parse {
@ -350,31 +351,28 @@ bool Curl_peer_same_destination(struct Curl_peer *p1, struct Curl_peer *p2)
CURLcode Curl_peer_from_url(CURLU *uh, struct Curl_easy *data,
uint16_t port_override,
uint32_t scopeid_override,
struct urlpieces *up,
struct Curl_peer **ppeer)
{
struct peer_parse pp;
char *zoneid = NULL;
char *zoneid = NULL, *scheme = NULL, *hostname = NULL;
CURLUcode uc;
CURLcode result;
Curl_peer_unlink(ppeer);
memset(&pp, 0, sizeof(pp));
curlx_safefree(up->scheme);
uc = curl_url_get(uh, CURLUPART_SCHEME, &up->scheme, 0);
uc = curl_url_get(uh, CURLUPART_SCHEME, &scheme, 0);
if(uc)
return Curl_uc_to_curlcode(uc);
pp.scheme = Curl_get_scheme(up->scheme);
pp.scheme = Curl_get_scheme(scheme);
if(!pp.scheme) {
failf(data, "Protocol \"%s\" not supported%s", up->scheme,
failf(data, "Protocol \"%s\" not supported%s", scheme,
data->state.this_is_a_follow ? " (in redirect)" : "");
result = CURLE_UNSUPPORTED_PROTOCOL;
goto out;
}
curlx_safefree(up->hostname);
uc = curl_url_get(uh, CURLUPART_HOST, &up->hostname, 0);
uc = curl_url_get(uh, CURLUPART_HOST, &hostname, 0);
if(uc) {
if((uc == CURLUE_NO_HOST) && (pp.scheme->flags & PROTOPT_NONETWORK))
; /* acceptable */
@ -383,13 +381,13 @@ CURLcode Curl_peer_from_url(CURLU *uh, struct Curl_easy *data,
goto out;
}
}
else if(strlen(up->hostname) > MAX_URL_LEN) {
else if(strlen(hostname) > MAX_URL_LEN) {
failf(data, "Too long hostname (maximum is %d)", MAX_URL_LEN);
result = CURLE_URL_MALFORMAT;
goto out;
}
pp.host_user.str = up->hostname ? up->hostname : "";
pp.host_user.str = hostname ? hostname : "";
pp.host_user.len = strlen(pp.host_user.str);
if(pp.host_user.len) {
result = peer_parse_host(data, &pp, FALSE);
@ -399,7 +397,6 @@ CURLcode Curl_peer_from_url(CURLU *uh, struct Curl_easy *data,
else
pp.host = pp.host_user;
curlx_safefree(up->port);
if(port_override) {
/* if set, we use this instead of the port possibly given in the URL */
char portbuf[16];
@ -413,7 +410,7 @@ CURLcode Curl_peer_from_url(CURLU *uh, struct Curl_easy *data,
pp.port = port_override;
}
else {
uc = curl_url_get(uh, CURLUPART_PORT, &up->port, CURLU_DEFAULT_PORT);
uc = Curl_url_get_port(uh, &pp.port);
if(uc) {
if(uc == CURLUE_OUT_OF_MEMORY) {
result = CURLE_OUT_OF_MEMORY;
@ -425,13 +422,6 @@ CURLcode Curl_peer_from_url(CURLU *uh, struct Curl_easy *data,
}
/* no port ok when not a network scheme */
}
else {
const char *p = up->port;
curl_off_t offt;
if(curlx_str_number(&p, &offt, 0xffff))
return CURLE_URL_MALFORMAT;
pp.port = (uint16_t)offt;
}
}
if(scopeid_override)
@ -456,6 +446,8 @@ CURLcode Curl_peer_from_url(CURLU *uh, struct Curl_easy *data,
out:
peer_parse_clear(&pp);
curlx_free(scheme);
curlx_free(hostname);
curlx_free(zoneid);
return result;
}

View file

@ -25,7 +25,6 @@
***************************************************************************/
struct Curl_scheme;
struct urlpieces;
/* if peer hostname starts with this, the peer is a unix domain socket
* path, e.g. the remainder after 'localhost'. */
@ -84,7 +83,6 @@ bool Curl_peer_same_destination(struct Curl_peer *p1, struct Curl_peer *p2);
CURLcode Curl_peer_from_url(CURLU *uh, struct Curl_easy *data,
uint16_t port_override,
uint32_t scopeid_override,
struct urlpieces *up,
struct Curl_peer **ppeer);
CURLcode Curl_peer_from_connect_to(struct Curl_easy *data,

View file

@ -178,11 +178,6 @@ void Curl_freeset(struct Curl_easy *data)
static void up_free(struct Curl_easy *data)
{
struct urlpieces *up = &data->state.up;
curlx_safefree(up->scheme);
curlx_safefree(up->hostname);
curlx_safefree(up->port);
curlx_safefree(up->user);
curlx_safefree(up->password);
curlx_safefree(up->options);
curlx_safefree(up->path);
curlx_safefree(up->query);
@ -1381,7 +1376,6 @@ static CURLcode hsts_upgrade(struct Curl_easy *data,
CURLUcode uc;
CURLcode result;
curlx_safefree(data->state.up.scheme);
uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0);
if(uc)
return Curl_uc_to_curlcode(uc);
@ -1393,7 +1387,7 @@ static CURLcode hsts_upgrade(struct Curl_easy *data,
Curl_bufref_set(&data->state.url, url, 0, curl_free);
result = Curl_peer_from_url(uh, data, port_override, scope_id,
&data->state.up, &data->state.origin);
&data->state.origin);
if(result)
return result;
infof(data, "Switched from HTTP to HTTPS due to HSTS => %s", url);
@ -1549,26 +1543,28 @@ static CURLcode url_set_data_creds(struct Curl_easy *data, CURLU *uh)
/* Extract credentials from the URL only if there are none OR
* if no CURLOPT_USER was set. */
if(!newcreds || !Curl_creds_has_user(newcreds)) {
char *user = NULL;
char *passwd = NULL;
char *udecoded = NULL;
char *pdecoded = NULL;
CURLUcode uc;
uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0);
uc = curl_url_get(uh, CURLUPART_USER, &user, 0);
if(uc && (uc != CURLUE_NO_USER))
result = Curl_uc_to_curlcode(uc);
if(!result) {
uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
uc = curl_url_get(uh, CURLUPART_PASSWORD, &passwd, 0);
if(uc && (uc != CURLUE_NO_PASSWORD))
result = Curl_uc_to_curlcode(uc);
}
if(!result && data->state.up.user) {
result = Curl_urldecode(data->state.up.user, 0, &udecoded, NULL,
if(!result && user) {
result = Curl_urldecode(user, 0, &udecoded, NULL,
(data->state.origin->scheme->flags &
PROTOPT_USERPWDCTRL) ?
REJECT_ZERO : REJECT_CTRL);
}
if(!result && data->state.up.password) {
result = Curl_urldecode(data->state.up.password, 0, &pdecoded, NULL,
if(!result && passwd) {
result = Curl_urldecode(passwd, 0, &pdecoded, NULL,
(data->state.origin->scheme->flags &
PROTOPT_USERPWDCTRL) ?
REJECT_ZERO : REJECT_CTRL);
@ -1579,6 +1575,8 @@ static CURLcode url_set_data_creds(struct Curl_easy *data, CURLU *uh)
curlx_free(udecoded);
curlx_free(pdecoded);
curlx_free(passwd);
curlx_free(user);
if(result) {
failf(data, "error extracting credentials from URL");
goto out;
@ -2276,7 +2274,7 @@ static CURLcode url_set_data_origin_and_creds(struct Curl_easy *data)
/* `uh` is now as the connection should use it, probably. */
result = Curl_peer_from_url(uh, data, port_override, scope_id,
&data->state.up, &data->state.origin);
&data->state.origin);
if(result)
goto out;
/* The origin might get changed when HSTS applies */

View file

@ -65,4 +65,6 @@ CURLUcode Curl_junkscan(const char *url, size_t *urllen, bool allowspace);
bool Curl_url_same_origin(CURLU *base, CURLU *href);
CURLUcode Curl_url_get_port(CURLU *u, uint16_t *pport);
#endif /* HEADER_CURL_URLAPI_INT_H */

View file

@ -2108,3 +2108,20 @@ bool Curl_url_same_origin(CURLU *base, CURLU *href)
return FALSE;
return TRUE;
}
CURLUcode Curl_url_get_port(CURLU *u, uint16_t *pport)
{
if(u->port_present) {
*pport = u->portnum;
return CURLUE_OK;
}
else if(u->scheme) {
const struct Curl_scheme *s = Curl_get_scheme(u->scheme);
if(s && s->defport) {
*pport = s->defport;
return CURLUE_OK;
}
}
*pport = 0;
return CURLUE_NO_PORT;
}

View file

@ -560,11 +560,6 @@ struct time_node {
/* individual pieces of the URL */
struct urlpieces {
char *scheme;
char *hostname;
char *port;
char *user;
char *password;
char *options;
char *path;
char *query;

View file

@ -2586,8 +2586,8 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
}
rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_HOST,
(data->state.up.hostname[0] == '[') ?
data->state.up.hostname : conn->origin->hostname);
conn->origin->ipv6 ?
conn->origin->user_hostname : conn->origin->hostname);
if(rc != SSH_OK) {
failf(data, "Could not set remote host");