]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
urlpieces: remove members that live in peers/creds
authorStefan Eissing <stefan@eissing.org>
Thu, 25 Jun 2026 09:36:23 +0000 (11:36 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 26 Jun 2026 12:39:40 +0000 (14:39 +0200)
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

lib/http.c
lib/http_proxy.c
lib/ldap.c
lib/openldap.c
lib/peer.c
lib/peer.h
lib/url.c
lib/urlapi-int.h
lib/urlapi.c
lib/urldata.h
lib/vssh/libssh.c

index a0aee51c78809e36436af29ddba8b65c45c8faac..072b1ed3b4f715279d9649faf8ae93c012e31de1 100644 (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);
index d019796b53241bd3806cb17b0dd9465ddd024913..b2cb018c10da1a1cafead918148a425ed4999a7d 100644 (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" :
index 29bc5efab2d59a20304a0a5a07759090e1b48994..b4b107a572666d13cd7ecb5040f8af417c939f68 100644 (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;
index 8ec6bb27cd844265c3ee3fd45088e259bf7eb549..ee765d8d05b2d3851014a11bce2c9799a1d4209c 100644 (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;
index 44bcb52f231434f1923e04b9061273984066ffe4..4a7a12d8cf06271aef73446c98bf1e9deb1c0b9b 100644 (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;
 }
index 1ceb230739b243c63483a418e0a4355f18976cfa..f6ed00cd485e582a29a1b1e2aaf767f6e5b8d50a 100644 (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,
index ea635fd1e43bd7523e2371a016c6be3cc73399af..de5111920a3b85227abb1f0a58140df2f86b2a22 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -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 */
index 4d23dd87b44cdc8d51834437381c0bfa9d7076e6..cf1fe6e7cc6ca96b94a7bb78c46530098bb0b0a5 100644 (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 */
index a664c7304b55da0f99705ae856d8d92fa2e57dc9..66f00c6b42def2fe587cab83a29e18931916dd9c 100644 (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;
+}
index 4666fa3658ecb910fd4581e74f5397219df2b61a..8a716d5590254ce7b382d321a436ee5776182190 100644 (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;
index d0bc13cadb70f884e8d016998ad9b6648116175d..1ff7714af03af577d7e7000e0d1d3bfa8e8cd415 100644 (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");