]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
uri-util: Split struct uri_host from uri_authority.
authorStephan Bosch <stephan@rename-it.nl>
Sun, 8 May 2016 21:06:23 +0000 (23:06 +0200)
committerGitLab <gitlab@git.dovecot.net>
Mon, 16 May 2016 07:36:48 +0000 (10:36 +0300)
Adds support for parsing host separately and manipulating host struct.

src/lib-http/http-url.c
src/lib-imap/imap-url.c
src/lib/uri-util.c
src/lib/uri-util.h

index 375c63337ee9b669ec229715d43e1550d1ddfa65..fab368addd8f7c50e2724e98a744a82e25546b09 100644 (file)
@@ -37,7 +37,7 @@ static bool http_url_parse_authority(struct http_url_parser *url_parser)
 
        if ((ret = uri_parse_authority(parser, &auth, TRUE)) < 0)
                return FALSE;
-       if (auth.host_literal == NULL || *auth.host_literal == '\0') {
+       if (auth.host.name == NULL || *auth.host.name == '\0') {
                /* RFC 7230, Section 2.7.1: http URI Scheme
 
                   A sender MUST NOT generate an "http" URI with an empty host
@@ -79,8 +79,8 @@ static bool http_url_parse_authority(struct http_url_parser *url_parser)
                }
        }
        if (url != NULL) {
-               url->host_name = p_strdup(parser->pool, auth.host_literal);
-               url->host_ip = auth.host_ip;
+               url->host_name = p_strdup(parser->pool, auth.host.name);
+               url->host_ip = auth.host.ip;
                url->port = auth.port;
                url->user = p_strdup(parser->pool, user);
                url->password = p_strdup(parser->pool, password);
@@ -362,37 +362,37 @@ int http_url_request_target_parse(const char *request_target,
 {
        struct http_url_parser url_parser;
        struct uri_parser *parser;
-       struct uri_authority host;
+       struct uri_authority auth;
        struct http_url base;
 
        memset(&url_parser, '\0', sizeof(url_parser));
        parser = &url_parser.parser;
        uri_parser_init(parser, pool, host_header);
 
-       if (uri_parse_authority(parser, &host, TRUE) <= 0) {
+       if (uri_parse_authority(parser, &auth, TRUE) <= 0) {
                *error_r = t_strdup_printf("Invalid Host header: %s", parser->error);
                return -1;
        }
 
-       if (parser->cur != parser->end || host.enc_userinfo != NULL) {
+       if (parser->cur != parser->end || auth.enc_userinfo != NULL) {
                *error_r = "Invalid Host header: Contains invalid character";
                return -1;
        }
 
        if (request_target[0] == '*' && request_target[1] == '\0') {
                struct http_url *url = p_new(pool, struct http_url, 1);
-               url->host_name = p_strdup(pool, host.host_literal);
-               url->host_ip = host.host_ip;
-               url->port = host.port;
+               url->host_name = p_strdup(pool, auth.host.name);
+               url->host_ip = auth.host.ip;
+               url->port = auth.port;
                target->url = url;
                target->format = HTTP_REQUEST_TARGET_FORMAT_ASTERISK;
                return 0;
        }
 
        memset(&base, 0, sizeof(base));
-       base.host_name = host.host_literal;
-       base.host_ip = host.host_ip;
-       base.port = host.port;
+       base.host_name = auth.host.name;
+       base.host_ip = auth.host.ip;
+       base.port = auth.port;
 
        memset(parser, '\0', sizeof(*parser));
        uri_parser_init(parser, pool, request_target);
index ecd7058e50f350051fd30201a10136111e73ff48..f61de657591b7155b5942e615c9c72a2668df1a0 100644 (file)
@@ -194,7 +194,7 @@ static int imap_url_parse_iserver(struct imap_url_parser *url_parser)
        if ((ret = uri_parse_slashslash_authority
                (parser, &auth, TRUE)) <= 0)
                return ret;
-       if (auth.host_literal == NULL || *auth.host_literal == '\0') {
+       if (auth.host.name == NULL || *auth.host.name == '\0') {
                /* This situation is not documented anywhere, but it is not
                   currently useful either and potentially problematic if not
                   handled explicitly everywhere. So, it is denied hier for now.
@@ -260,8 +260,8 @@ static int imap_url_parse_iserver(struct imap_url_parser *url_parser)
        }
 
        if (url != NULL) {
-               url->host_name = auth.host_literal;
-               url->host_ip = auth.host_ip;
+               url->host_name = auth.host.name;
+               url->host_ip = auth.host.ip;
                url->port = auth.port;
        }
        return 1;
index 81b27c7e7247a3524a6bd4921da74da71af03b73..c461c1df8ffc68da446ca844a1a48502df9cb70c 100644 (file)
@@ -433,7 +433,7 @@ uri_parse_reg_name(struct uri_parser *parser,
        return 0;
 }
 
-static int uri_parse_host_name_dns(struct uri_parser *parser,
+static int uri_do_parse_host_name_dns(struct uri_parser *parser,
        string_t *host_name) ATTR_NULL(2, 3)
 {
        const unsigned char *first, *part;
@@ -549,6 +549,22 @@ static int uri_parse_host_name_dns(struct uri_parser *parser,
        return 1;
 }
 
+int uri_parse_host_name_dns(struct uri_parser *parser,
+       const char **host_name_r)
+{
+       string_t *host_name = NULL;
+       int ret;
+
+       if (host_name_r != NULL)
+               host_name = uri_parser_get_tmpbuf(parser, 256);
+
+       if ((ret=uri_do_parse_host_name_dns(parser, host_name)) <= 0)
+               return ret;
+
+       *host_name_r = str_c(host_name);
+       return 1;
+}
+
 static int
 uri_parse_ip_literal(struct uri_parser *parser, string_t *literal,
                     struct in6_addr *ip6_r) ATTR_NULL(2,3)
@@ -600,9 +616,8 @@ uri_parse_ip_literal(struct uri_parser *parser, string_t *literal,
        return 1;
 }
 
-static int 
-uri_parse_host(struct uri_parser *parser,
-       struct uri_authority *auth, bool dns_name) ATTR_NULL(2)
+int uri_parse_host(struct uri_parser *parser,
+       struct uri_host *host, bool dns_name) ATTR_NULL(2)
 {
        const unsigned char *preserve;
        struct in_addr ip4;
@@ -615,6 +630,9 @@ uri_parse_host(struct uri_parser *parser,
         * host          = IP-literal / IPv4address / reg-name
         */
 
+       if (host != NULL)
+               memset(host, 0, sizeof(*host));
+
        literal = uri_parser_get_tmpbuf(parser, 256);
 
        /* IP-literal / */
@@ -622,10 +640,10 @@ uri_parse_host(struct uri_parser *parser,
                if ((ret=uri_parse_ip_literal(parser, literal, &ip6)) <= 0)
                        return -1;
 
-               if (auth != NULL) {
-                       auth->host_literal = p_strdup(parser->pool, str_c(literal));
-                       auth->host_ip.family = AF_INET6;
-                       auth->host_ip.u.ip6 = ip6;
+               if (host != NULL) {
+                       host->name = p_strdup(parser->pool, str_c(literal));;
+                       host->ip.family = AF_INET6;
+                       host->ip.u.ip6 = ip6;
                }
                return 1;
        }
@@ -636,10 +654,10 @@ uri_parse_host(struct uri_parser *parser,
         */
        preserve = parser->cur;
        if ((ret = uri_parse_ipv4address(parser, literal, &ip4)) > 0) {
-               if (auth != NULL) {
-                       auth->host_literal = p_strdup(parser->pool, str_c(literal));
-                       auth->host_ip.family = AF_INET;
-                       auth->host_ip.u.ip4 = ip4;
+               if (host != NULL) {
+                       host->name = p_strdup(parser->pool, str_c(literal));
+                       host->ip.family = AF_INET;
+                       host->ip.u.ip4 = ip4;
                }
                return ret;
        }
@@ -648,12 +666,12 @@ uri_parse_host(struct uri_parser *parser,
 
        /* reg-name */
        if (dns_name) {
-               if (uri_parse_host_name_dns(parser, literal) < 0)
+               if (uri_do_parse_host_name_dns(parser, literal) < 0)
                        return -1;
        } else  if (uri_parse_reg_name(parser, literal) < 0)
                return -1;
-       if (auth != NULL)
-               auth->host_literal = p_strdup(parser->pool, str_c(literal));
+       if (host != NULL)
+               host->name = p_strdup(parser->pool, str_c(literal));
        return 0;
 }
 
@@ -717,7 +735,8 @@ int uri_parse_authority(struct uri_parser *parser,
        }
 
        /* host */
-       if (uri_parse_host(parser, auth, dns_name) < 0)
+       if (uri_parse_host(parser,
+               (auth == NULL ? NULL : &auth->host), dns_name) < 0)
                return -1;
        if (parser->cur == parser->end)
                return 1;
@@ -993,6 +1012,25 @@ string_t *uri_parser_get_tmpbuf(struct uri_parser *parser, size_t size)
        return parser->tmpbuf;
 }
 
+/*
+ * Generic URI manipulation
+ */
+
+void uri_host_copy(pool_t pool, struct uri_host *dest,
+       const struct uri_host *src)
+{
+       const char *host_name = src->name;
+
+       /* create host name literal if caller is lazy */
+       if (host_name == NULL && src->ip.family != 0) {
+               host_name = net_ip2addr(&src->ip);
+               i_assert(*host_name != '\0');
+       }
+
+       *dest = *src;
+       dest->name = p_strdup(pool, host_name);
+}
+
 /*
  * Generic URI construction
  */
@@ -1055,6 +1093,18 @@ void uri_append_host_ip(string_t *out, const struct ip_addr *host_ip)
        str_append_c(out, ']');
 }
 
+void uri_append_host(string_t *out, const struct uri_host *host)
+{
+       if (host->name != NULL) {
+               /* assume IPv6 literal if starts with '['; avoid encoding */
+               if (*host->name == '[')
+                       str_append(out, host->name);
+               else
+                       uri_append_host_name(out, host->name);
+       } else
+               uri_append_host_ip(out, &host->ip);
+}
+
 void uri_append_port(string_t *out, in_port_t port)
 {
        if (port != 0)
index 348f9d4e198f5ff28e793420de5c2d87667a93f3..f30fedbd7a006c27f0ccebe02fa8f7b720a2067c 100644 (file)
@@ -7,12 +7,15 @@
  * Generic URI parsing.
  */
 
+struct uri_host {
+       const char *name;
+       struct ip_addr ip;
+};
+
 struct uri_authority {
        const char *enc_userinfo;
 
-       const char *host_literal;
-       struct ip_addr host_ip;
-
+       struct uri_host host;
        in_port_t port;
 };
 
@@ -38,6 +41,12 @@ int uri_cut_scheme(const char **uri_p, const char **scheme_r)
        ATTR_NULL(2);
 int uri_parse_scheme(struct uri_parser *parser, const char **scheme_r)
        ATTR_NULL(2);
+
+int uri_parse_host_name_dns(struct uri_parser *parser,
+       const char **host_name_r) ATTR_NULL(2);
+int uri_parse_host(struct uri_parser *parser,
+       struct uri_host *host, bool dns_name) ATTR_NULL(2);
+
 int uri_parse_authority(struct uri_parser *parser,
        struct uri_authority *auth, bool dns_name) ATTR_NULL(2);
 int uri_parse_slashslash_authority(struct uri_parser *parser,
@@ -61,6 +70,12 @@ void uri_parser_init(struct uri_parser *parser,
 string_t *uri_parser_get_tmpbuf(struct uri_parser *parser,
        size_t size);
 
+/*
+ * Generic URI manipulation
+ */
+
+void uri_host_copy(pool_t pool, struct uri_host *dest,
+       const struct uri_host *src);
 
 /*
  * Generic URI construction
@@ -70,8 +85,10 @@ void uri_append_scheme(string_t *out, const char *scheme);
 
 void uri_append_user_data(string_t *out, const char *esc, const char *data);
 void uri_append_userinfo(string_t *out, const char *userinfo);
+
 void uri_append_host_name(string_t *out, const char *name);
 void uri_append_host_ip(string_t *out, const struct ip_addr *host_ip);
+void uri_append_host(string_t *out, const struct uri_host *host);
 void uri_append_port(string_t *out, in_port_t port);
 
 void uri_append_path_segment_data(string_t *out, const char *esc, const char *data);