diff options
author | Marc Balmer <mbalmer@cvs.openbsd.org> | 2008-05-13 20:06:46 +0000 |
---|---|---|
committer | Marc Balmer <mbalmer@cvs.openbsd.org> | 2008-05-13 20:06:46 +0000 |
commit | 91c0e0a5d801663df61aa385623cb3489128ca14 (patch) | |
tree | 06dbd86e0c7af2dc49c0eddd0e6b697dd367635e | |
parent | 1ab40702d7c0690e4a6949199d76861f21dadfd0 (diff) |
knf. no binary changes.
-rw-r--r-- | usr.sbin/httpd/src/main/util_uri.c | 684 |
1 files changed, 343 insertions, 341 deletions
diff --git a/usr.sbin/httpd/src/main/util_uri.c b/usr.sbin/httpd/src/main/util_uri.c index 18554a0f685..2b13855270a 100644 --- a/usr.sbin/httpd/src/main/util_uri.c +++ b/usr.sbin/httpd/src/main/util_uri.c @@ -66,105 +66,111 @@ #include "http_conf_globals.h" /* for user_id & group_id */ #include "util_uri.h" -/* Some WWW schemes and their default ports; this is basically /etc/services */ -/* This will become global when the protocol abstraction comes */ -/* As the schemes are searched by a linear search, */ -/* they are sorted by their expected frequency */ +/* + * Some WWW schemes and their default ports; this is basically /etc/services + * This will become global when the protocol abstraction comes + * As the schemes are searched by a linear search, + * they are sorted by their expected frequency + */ static schemes_t schemes[] = { - {"http", DEFAULT_HTTP_PORT}, - {"ftp", DEFAULT_FTP_PORT}, - {"https", DEFAULT_HTTPS_PORT}, - {"gopher", DEFAULT_GOPHER_PORT}, - {"wais", DEFAULT_WAIS_PORT}, - {"nntp", DEFAULT_NNTP_PORT}, - {"snews", DEFAULT_SNEWS_PORT}, - {"prospero", DEFAULT_PROSPERO_PORT}, - {NULL, 0xFFFF} /* unknown port */ + {"http", DEFAULT_HTTP_PORT}, + {"ftp", DEFAULT_FTP_PORT}, + {"https", DEFAULT_HTTPS_PORT}, + {"gopher", DEFAULT_GOPHER_PORT}, + {"wais", DEFAULT_WAIS_PORT}, + {"nntp", DEFAULT_NNTP_PORT}, + {"snews", DEFAULT_SNEWS_PORT}, + {"prospero", DEFAULT_PROSPERO_PORT}, + {NULL, 0xFFFF} /* unknown port */ }; -API_EXPORT(unsigned short) ap_default_port_for_scheme(const char *scheme_str) +API_EXPORT(unsigned short) +ap_default_port_for_scheme(const char *scheme_str) { - schemes_t *scheme; + schemes_t *scheme; - if (scheme_str == NULL) - return 0; + if (scheme_str == NULL) + return 0; - for (scheme = schemes; scheme->name != NULL; ++scheme) - if (strcasecmp(scheme_str, scheme->name) == 0) - return scheme->default_port; + for (scheme = schemes; scheme->name != NULL; ++scheme) + if (strcasecmp(scheme_str, scheme->name) == 0) + return scheme->default_port; - return 0; + return 0; } -API_EXPORT(unsigned short) ap_default_port_for_request(const request_rec *r) +API_EXPORT(unsigned short) +ap_default_port_for_request(const request_rec *r) { - return (r->parsed_uri.scheme) - ? ap_default_port_for_scheme(r->parsed_uri.scheme) - : 0; + return (r->parsed_uri.scheme) + ? ap_default_port_for_scheme(r->parsed_uri.scheme) : 0; } -/* Create a copy of a "struct hostent" record; it was presumably returned +/* + * Create a copy of a "struct hostent" record; it was presumably returned * from a call to gethostbyname() and lives in static storage. * By creating a copy we can tuck it away for later use. */ -API_EXPORT(struct hostent *) ap_pduphostent(pool *p, const struct hostent *hp) +API_EXPORT(struct hostent *) +ap_pduphostent(pool *p, const struct hostent *hp) { - struct hostent *newent; - char **ptrs; - char **aliases; - struct in_addr *addrs; - int i = 0, j = 0; - - if (hp == NULL) - return NULL; - - /* Count number of alias entries */ - if (hp->h_aliases != NULL) - for (; hp->h_aliases[j] != NULL; ++j) - continue; - - /* Count number of in_addr entries */ - if (hp->h_addr_list != NULL) - for (; hp->h_addr_list[i] != NULL; ++i) - continue; - - /* Allocate hostent structure, alias ptrs, addr ptrs, addrs */ - newent = (struct hostent *) ap_palloc(p, sizeof(*hp)); - aliases = (char **) ap_palloc(p, (j + 1) * sizeof(char *)); - ptrs = (char **) ap_palloc(p, (i + 1) * sizeof(char *)); - addrs = (struct in_addr *) ap_palloc(p, (i + 1) * sizeof(struct in_addr)); - - *newent = *hp; - newent->h_name = ap_pstrdup(p, hp->h_name); - newent->h_aliases = aliases; - newent->h_addr_list = (char **) ptrs; - - /* Copy Alias Names: */ - for (j = 0; hp->h_aliases[j] != NULL; ++j) { - aliases[j] = ap_pstrdup(p, hp->h_aliases[j]); - } - aliases[j] = NULL; - - /* Copy address entries */ - for (i = 0; hp->h_addr_list[i] != NULL; ++i) { - ptrs[i] = (char *) &addrs[i]; - addrs[i] = *(struct in_addr *) hp->h_addr_list[i]; - } - ptrs[i] = NULL; + struct hostent *newent; + char **ptrs; + char **aliases; + struct in_addr *addrs; + int i = 0, j = 0; + + if (hp == NULL) + return NULL; + + /* Count number of alias entries */ + if (hp->h_aliases != NULL) + for (; hp->h_aliases[j] != NULL; ++j) + continue; + + /* Count number of in_addr entries */ + if (hp->h_addr_list != NULL) + for (; hp->h_addr_list[i] != NULL; ++i) + continue; + + /* Allocate hostent structure, alias ptrs, addr ptrs, addrs */ + newent = (struct hostent *)ap_palloc(p, sizeof(*hp)); + aliases = (char **)ap_palloc(p, (j + 1) * sizeof(char *)); + ptrs = (char **)ap_palloc(p, (i + 1) * sizeof(char *)); + addrs = (struct in_addr *)ap_palloc(p, (i + 1) * sizeof(struct in_addr)); + + *newent = *hp; + newent->h_name = ap_pstrdup(p, hp->h_name); + newent->h_aliases = aliases; + newent->h_addr_list = (char **)ptrs; + + /* Copy Alias Names: */ + for (j = 0; hp->h_aliases[j] != NULL; ++j) + aliases[j] = ap_pstrdup(p, hp->h_aliases[j]); + aliases[j] = NULL; + + /* Copy address entries */ + for (i = 0; hp->h_addr_list[i] != NULL; ++i) { + ptrs[i] = (char *)&addrs[i]; + addrs[i] = *(struct in_addr *)hp->h_addr_list[i]; + } + ptrs[i] = NULL; - return newent; + return newent; } -/* pgethostbyname(): resolve hostname, if successful return an ALLOCATED +/* + * pgethostbyname(): resolve hostname, if successful return an ALLOCATED * COPY OF the hostent structure, intended to be stored and used later. * (gethostbyname() uses static storage that would be overwritten on each call) */ -API_EXPORT(struct hostent *) ap_pgethostbyname(pool *p, const char *hostname) +API_EXPORT(struct hostent *) +ap_pgethostbyname(pool *p, const char *hostname) { - struct hostent *hp = gethostbyname(hostname); - return (hp == NULL) ? NULL : ap_pduphostent(p, hp); + struct hostent *hp = gethostbyname(hostname); + return (hp == NULL) ? NULL : ap_pduphostent(p, hp); } @@ -172,126 +178,118 @@ API_EXPORT(struct hostent *) ap_pgethostbyname(pool *p, const char *hostname) * Optionally suppress the password for security reasons. * See also RFC 2396. */ -API_EXPORT(char *) ap_unparse_uri_components(pool *p, - const uri_components * uptr, - unsigned flags) +API_EXPORT(char *) +ap_unparse_uri_components(pool *p, const uri_components * uptr, unsigned flags) { - char *parts[16]; /* 16 distinct parts of a URI */ - char *scheme = NULL; /* to hold the scheme without modifying const args */ - int j = 0; /* an index into parts */ - - memset(parts, 0, sizeof(parts)); - - /* If suppressing the site part, omit all of scheme://user:pass@host:port */ - if (!(flags & UNP_OMITSITEPART)) { - - /* if the user passes in a scheme, we'll assume an absoluteURI */ - if (uptr->scheme) { - scheme = uptr->scheme; - - parts[j++] = uptr->scheme; - parts[j++] = ":"; - } - - /* handle the hier_part */ - if (uptr->user || uptr->password || uptr->hostname) { - - /* this stuff requires absoluteURI, so we have to add the scheme */ - if (!uptr->scheme) { - scheme = DEFAULT_URI_SCHEME; - - parts[j++] = DEFAULT_URI_SCHEME; - parts[j++] = ":"; - } - - parts[j++] = "//"; - - /* userinfo requires hostport */ - if (uptr->hostname && (uptr->user || uptr->password)) { - if (uptr->user && !(flags & UNP_OMITUSER)) - parts[j++] = uptr->user; - - if (uptr->password && !(flags & UNP_OMITPASSWORD)) { - parts[j++] = ":"; - - if (flags & UNP_REVEALPASSWORD) - parts[j++] = uptr->password; - else - parts[j++] = "XXXXXXXX"; - } - - parts[j++] = "@"; - } - - /* If we get here, there must be a hostname. */ - parts[j++] = uptr->hostname; - - /* Emit the port. A small beautification - * prevents http://host:80/ and similar visual blight. - */ - if (uptr->port_str && - !(uptr->port && - scheme && - uptr->port == ap_default_port_for_scheme(scheme))) { - - parts[j++] = ":"; - parts[j++] = uptr->port_str; - } - } - } - - if (!(flags & UNP_OMITPATHINFO)) { - - - /* We must ensure we don't put out a hier_part and a rel_path */ - if (j && uptr->path && *uptr->path != '/') - parts[j++] = "/"; - - if (uptr->path != NULL) - parts[j++] = uptr->path; - - if (!(flags & UNP_OMITQUERY)) { - if (uptr->query) { - parts[j++] = "?"; - parts[j++] = uptr->query; - } - - if (uptr->fragment) { - parts[j++] = "#"; - parts[j++] = uptr->fragment; - } - } - } + char *parts[16]; /* 16 distinct parts of a URI */ + char *scheme = NULL; /* to hold the scheme without modifying const + /* args */ + int j = 0; /* an index into parts */ + + memset(parts, 0, sizeof(parts)); + + /* + * If suppressing the site part, omit all of + * scheme://user:pass@host:port + */ + if (!(flags & UNP_OMITSITEPART)) { + + /* + * if the user passes in a scheme, we'll assume an + * absoluteURI + */ + if (uptr->scheme) { + scheme = uptr->scheme; + + parts[j++] = uptr->scheme; + parts[j++] = ":"; + } + + /* handle the hier_part */ + if (uptr->user || uptr->password || uptr->hostname) { + /* this stuff requires absoluteURI, so we have to + * add the scheme + */ + if (!uptr->scheme) { + scheme = DEFAULT_URI_SCHEME; + + parts[j++] = DEFAULT_URI_SCHEME; + parts[j++] = ":"; + } + + parts[j++] = "//"; + + /* userinfo requires hostport */ + if (uptr->hostname && (uptr->user || uptr->password)) { + if (uptr->user && !(flags & UNP_OMITUSER)) + parts[j++] = uptr->user; + + if (uptr->password && + !(flags & UNP_OMITPASSWORD)) { + parts[j++] = ":"; + + if (flags & UNP_REVEALPASSWORD) + parts[j++] = uptr->password; + else + parts[j++] = "XXXXXXXX"; + } + + parts[j++] = "@"; + } + + /* If we get here, there must be a hostname. */ + parts[j++] = uptr->hostname; + + /* + * Emit the port. A small beautification + * prevents http://host:80/ and similar visual blight. + */ + if (uptr->port_str && !(uptr->port && scheme && + uptr->port == ap_default_port_for_scheme(scheme))) { + parts[j++] = ":"; + parts[j++] = uptr->port_str; + } + } + } + + if (!(flags & UNP_OMITPATHINFO)) { + - /* Ugly, but correct and probably faster than ap_vsnprintf. */ - return ap_pstrcat(p, - parts[0], - parts[1], - parts[2], - parts[3], - parts[4], - parts[5], - parts[6], - parts[7], - parts[8], - parts[9], - parts[10], - parts[11], - parts[12], - parts[13], - parts[14], - parts[15], - NULL - ); + /* We must ensure we don't put out a hier_part and a rel_path */ + if (j && uptr->path && *uptr->path != '/') + parts[j++] = "/"; + + if (uptr->path != NULL) + parts[j++] = uptr->path; + + if (!(flags & UNP_OMITQUERY)) { + if (uptr->query) { + parts[j++] = "?"; + parts[j++] = uptr->query; + } + + if (uptr->fragment) { + parts[j++] = "#"; + parts[j++] = uptr->fragment; + } + } + } + + /* Ugly, but correct and probably faster than ap_vsnprintf. */ + return ap_pstrcat(p, parts[0], parts[1], parts[2], parts[3], parts[4], + parts[5], parts[6], parts[7], parts[8], parts[9], parts[10], + parts[11], parts[12], parts[13], parts[14], parts[15], NULL); } -/* Here is the hand-optimized parse_uri_components(). There are some wild +/* + * Here is the hand-optimized parse_uri_components(). There are some wild * tricks we could pull in assembly language that we don't pull here... like we * can do word-at-time scans for delimiter characters using the same technique * that fast memchr()s use. But that would be way non-portable. -djg */ -/* We have a table that we can index by character and it tells us if the +/* + * We have a table that we can index by character and it tells us if the * character is one of the interesting delimiters. Note that we even get * compares for NUL for free -- it's just another delimiter. */ @@ -318,12 +316,14 @@ API_EXPORT(char *) ap_unparse_uri_components(pool *p, #define NOTEND_HOSTINFO (T_SLASH | T_QUESTION | T_HASH | T_NUL) #define NOTEND_PATH (T_QUESTION | T_HASH | T_NUL) -void ap_util_uri_init(void) +void +ap_util_uri_init(void) { - /* Nothing to do - except.... - UTIL_URI_REGEX was removed, but third parties may depend on this symbol - being present. So, we'll leave it in.... - vjo - */ + /* + * Nothing to do - except.... + * UTIL_URI_REGEX was removed, but third parties may depend on this + * symbol being present. So, we'll leave it in.... - vjo + */ } /* parse_uri_components(): @@ -334,129 +334,129 @@ void ap_util_uri_init(void) * - fills in fields of uri_components *uptr * - none on any of the r->* fields */ -API_EXPORT(int) ap_parse_uri_components(pool *p, const char *uri, - uri_components * uptr) +API_EXPORT(int) +ap_parse_uri_components(pool *p, const char *uri, uri_components * uptr) { - const char *s; - const char *s1; - const char *hostinfo; - char *endstr; - int port; - - /* Initialize the structure. parse_uri() and parse_uri_components() - * can be called more than once per request. - */ - memset(uptr, '\0', sizeof(*uptr)); - uptr->is_initialized = 1; - - /* We assume the processor has a branch predictor like most -- - * it assumes forward branches are untaken and backwards are taken. That's - * the reason for the gotos. -djg - */ - if (uri[0] == '/') { - deal_with_path: - /* we expect uri to point to first character of path ... remember - * that the path could be empty -- http://foobar?query for example - */ - s = uri; - while ((uri_delims[*(unsigned char *) s] & NOTEND_PATH) == 0) { - ++s; - } - if (s != uri) { - uptr->path = ap_pstrndup(p, uri, s - uri); - } - if (*s == 0) { - return HTTP_OK; - } - if (*s == '?') { - ++s; - s1 = strchr(s, '#'); - if (s1) { - uptr->fragment = ap_pstrdup(p, s1 + 1); - uptr->query = ap_pstrndup(p, s, s1 - s); - } - else { - uptr->query = ap_pstrdup(p, s); - } - return HTTP_OK; - } - /* otherwise it's a fragment */ - uptr->fragment = ap_pstrdup(p, s + 1); - return HTTP_OK; - } - - /* find the scheme: */ - s = uri; - while ((uri_delims[*(unsigned char *) s] & NOTEND_SCHEME) == 0) { - ++s; - } - /* scheme must be non-empty and followed by :// */ - if (s == uri || s[0] != ':' || s[1] != '/' || s[2] != '/') { - goto deal_with_path; /* backwards predicted taken! */ - } + const char *s; + const char *s1; + const char *hostinfo; + char *endstr; + int port; + + /* Initialize the structure. parse_uri() and parse_uri_components() + * can be called more than once per request. + */ + memset(uptr, '\0', sizeof(*uptr)); + uptr->is_initialized = 1; - uptr->scheme = ap_pstrndup(p, uri, s - uri); - s += 3; - hostinfo = s; - while ((uri_delims[*(unsigned char *) s] & NOTEND_HOSTINFO) == 0) { - ++s; - } - uri = s; /* whatever follows hostinfo is start of uri */ - uptr->hostinfo = ap_pstrndup(p, hostinfo, uri - hostinfo); - - /* If there's a username:password@host:port, the @ we want is the last @... - * too bad there's no memrchr()... For the C purists, note that hostinfo - * is definately not the first character of the original uri so therefore - * &hostinfo[-1] < &hostinfo[0] ... and this loop is valid C. - */ - do { - --s; - } while (s >= hostinfo && *s != '@'); - if (s < hostinfo) { - /* again we want the common case to be fall through */ -deal_with_host: - /* We expect hostinfo to point to the first character of - * the hostname. If there's a port it is the first colon. + /* We assume the processor has a branch predictor like most -- + * it assumes forward branches are untaken and backwards are taken. + * That's the reason for the gotos. -djg */ - if (*hostinfo == '[') { - s = memchr(hostinfo+1, ']', uri - hostinfo - 1); - if (s) - s = strchr(s, ':'); - } else - s = memchr(hostinfo, ':', uri - hostinfo); - if (s == NULL) { - /* we expect the common case to have no port */ - uptr->hostname = ap_pstrndup(p, hostinfo, uri - hostinfo); - goto deal_with_path; + if (uri[0] == '/') { + deal_with_path: + /* we expect uri to point to first character of path ... + * remember that the path could be empty -- + * http://foobar?query for example + */ + s = uri; + while ((uri_delims[*(unsigned char *)s] & NOTEND_PATH) == 0) + ++s; + + if (s != uri) + uptr->path = ap_pstrndup(p, uri, s - uri); + + if (*s == 0) + return HTTP_OK; + + if (*s == '?') { + ++s; + s1 = strchr(s, '#'); + if (s1) { + uptr->fragment = ap_pstrdup(p, s1 + 1); + uptr->query = ap_pstrndup(p, s, s1 - s); + } else + uptr->query = ap_pstrdup(p, s); + + return HTTP_OK; + } + /* otherwise it's a fragment */ + uptr->fragment = ap_pstrdup(p, s + 1); + return HTTP_OK; } - uptr->hostname = ap_pstrndup(p, hostinfo, s - hostinfo); - ++s; - uptr->port_str = ap_pstrndup(p, s, uri - s); - if (uri != s) { - port = ap_strtol(uptr->port_str, &endstr, 10); - uptr->port = port; - if (*endstr == '\0') { + + /* find the scheme: */ + s = uri; + while ((uri_delims[*(unsigned char *) s] & NOTEND_SCHEME) == 0) + ++s; + + /* scheme must be non-empty and followed by :// */ + if (s == uri || s[0] != ':' || s[1] != '/' || s[2] != '/') + goto deal_with_path; /* backwards predicted taken! */ + + + uptr->scheme = ap_pstrndup(p, uri, s - uri); + s += 3; + hostinfo = s; + while ((uri_delims[*(unsigned char *) s] & NOTEND_HOSTINFO) == 0) + ++s; + + uri = s; /* whatever follows hostinfo is start of uri */ + uptr->hostinfo = ap_pstrndup(p, hostinfo, uri - hostinfo); + + /* If there's a username:password@host:port, the @ we want is + * the last @...too bad there's no memrchr()... For the C purists, + * note that hostinfo is definately not the first character of the + * original uri so therefore &hostinfo[-1] < &hostinfo[0] ... + * and this loop is valid C. + */ + do { + --s; + } while (s >= hostinfo && *s != '@'); + if (s < hostinfo) { + /* again we want the common case to be fall through */ + deal_with_host: + /* We expect hostinfo to point to the first character of + * the hostname. If there's a port it is the first colon. + */ + if (*hostinfo == '[') { + s = memchr(hostinfo+1, ']', uri - hostinfo - 1); + if (s) + s = strchr(s, ':'); + } else + s = memchr(hostinfo, ':', uri - hostinfo); + if (s == NULL) { + /* we expect the common case to have no port */ + uptr->hostname = ap_pstrndup(p, hostinfo, + uri - hostinfo); + goto deal_with_path; + } + uptr->hostname = ap_pstrndup(p, hostinfo, s - hostinfo); + ++s; + uptr->port_str = ap_pstrndup(p, s, uri - s); + if (uri != s) { + port = ap_strtol(uptr->port_str, &endstr, 10); + uptr->port = port; + if (*endstr == '\0') + goto deal_with_path; + + /* Invalid characters after ':' found */ + return HTTP_BAD_REQUEST; + } + uptr->port = ap_default_port_for_scheme(uptr->scheme); goto deal_with_path; - } - /* Invalid characters after ':' found */ - return HTTP_BAD_REQUEST; } - uptr->port = ap_default_port_for_scheme(uptr->scheme); - goto deal_with_path; - } - /* first colon delimits username:password */ - s1 = memchr(hostinfo, ':', s - hostinfo); - if (s1) { - uptr->user = ap_pstrndup(p, hostinfo, s1 - hostinfo); - ++s1; - uptr->password = ap_pstrndup(p, s1, s - s1); - } - else { - uptr->user = ap_pstrndup(p, hostinfo, s - hostinfo); - } - hostinfo = s + 1; - goto deal_with_host; + /* first colon delimits username:password */ + s1 = memchr(hostinfo, ':', s - hostinfo); + if (s1) { + uptr->user = ap_pstrndup(p, hostinfo, s1 - hostinfo); + ++s1; + uptr->password = ap_pstrndup(p, s1, s - s1); + } else + uptr->user = ap_pstrndup(p, hostinfo, s - hostinfo); + hostinfo = s + 1; + goto deal_with_host; } /* Special case for CONNECT parsing: it comes with the hostinfo part only */ @@ -464,40 +464,42 @@ deal_with_host: * currently at http://www.mcom.com/newsref/std/tunneling_ssl.html * for the format of the "CONNECT host:port HTTP/1.0" request */ -API_EXPORT(int) ap_parse_hostinfo_components(pool *p, const char *hostinfo, - uri_components * uptr) +API_EXPORT(int) +ap_parse_hostinfo_components(pool *p, const char *hostinfo, + uri_components *uptr) { - const char *s; - char *endstr; - - /* Initialize the structure. parse_uri() and parse_uri_components() - * can be called more than once per request. - */ - memset(uptr, '\0', sizeof(*uptr)); - uptr->is_initialized = 1; - uptr->hostinfo = ap_pstrdup(p, hostinfo); - - /* We expect hostinfo to point to the first character of - * the hostname. There must be a port, separated by a colon - */ - if (*hostinfo == '[') { - s = strchr(hostinfo+1, ']'); - if (s) - s = strchr(s, ':'); - } else - s = strchr(hostinfo, ':'); - if (s == NULL) { - return HTTP_BAD_REQUEST; - } - uptr->hostname = ap_pstrndup(p, hostinfo, s - hostinfo); - ++s; - uptr->port_str = ap_pstrdup(p, s); - if (*s != '\0') { - uptr->port = (unsigned short)ap_strtol(uptr->port_str, &endstr, 10); - if (*endstr == '\0') { - return HTTP_OK; - } - /* Invalid characters after ':' found */ - } - return HTTP_BAD_REQUEST; + const char *s; + char *endstr; + + /* Initialize the structure. parse_uri() and parse_uri_components() + * can be called more than once per request. + */ + memset(uptr, '\0', sizeof(*uptr)); + uptr->is_initialized = 1; + uptr->hostinfo = ap_pstrdup(p, hostinfo); + + /* We expect hostinfo to point to the first character of + * the hostname. There must be a port, separated by a colon + */ + if (*hostinfo == '[') { + s = strchr(hostinfo+1, ']'); + if (s) + s = strchr(s, ':'); + } else + s = strchr(hostinfo, ':'); + if (s == NULL) + return HTTP_BAD_REQUEST; + + uptr->hostname = ap_pstrndup(p, hostinfo, s - hostinfo); + ++s; + uptr->port_str = ap_pstrdup(p, s); + if (*s != '\0') { + uptr->port = (unsigned short)ap_strtol(uptr->port_str, + &endstr, 10); + if (*endstr == '\0') + return HTTP_OK; + + /* Invalid characters after ':' found */ + } + return HTTP_BAD_REQUEST; } |