From: Stephan Bosch Date: Sun, 8 May 2016 21:06:23 +0000 (+0200) Subject: uri-util: Split struct uri_host from uri_authority. X-Git-Tag: 2.3.0.rc1~3754 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8d2d2780c9e71581ff9c3e8bce527b492c295ec1;p=thirdparty%2Fdovecot%2Fcore.git uri-util: Split struct uri_host from uri_authority. Adds support for parsing host separately and manipulating host struct. --- diff --git a/src/lib-http/http-url.c b/src/lib-http/http-url.c index 375c63337e..fab368addd 100644 --- a/src/lib-http/http-url.c +++ b/src/lib-http/http-url.c @@ -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); diff --git a/src/lib-imap/imap-url.c b/src/lib-imap/imap-url.c index ecd7058e50..f61de65759 100644 --- a/src/lib-imap/imap-url.c +++ b/src/lib-imap/imap-url.c @@ -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; diff --git a/src/lib/uri-util.c b/src/lib/uri-util.c index 81b27c7e72..c461c1df8f 100644 --- a/src/lib/uri-util.c +++ b/src/lib/uri-util.c @@ -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) diff --git a/src/lib/uri-util.h b/src/lib/uri-util.h index 348f9d4e19..f30fedbd7a 100644 --- a/src/lib/uri-util.h +++ b/src/lib/uri-util.h @@ -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);