martin 98/02/27 07:15:30
Modified: src CHANGES src/include httpd.h src/main Makefile.tmpl http_main.c http_protocol.c http_request.c http_vhost.c src/modules/proxy mod_proxy.c mod_proxy.h proxy_http.c proxy_util.c src/modules/standard mod_log_config.c Added: src/include util_uri.h src/main util_uri.c Log: For testing purposes, I added a new source called main/util_uri.c; It contains a routine parse_uri_components_regex() and friends which tries to break an URI into its parts. These parts are stored in a new uri_components structure within each request_rec and are therefore available to all routines which act on a request. Additionally, an unparse routine is supplied which re-assembles the URI components back to an URI, optionally hiding the username:password@ part from ftp proxy requests, and other useful routines. Within the structure, you find on a ready-for-use basis: scheme; /* scheme ("http"/"ftp"/...) */ hostinfo; /* combined [user[:[EMAIL PROTECTED]:port] */ user; /* user name, as in http://user:[EMAIL PROTECTED]:port/ */ password; /* password, as in http://user:[EMAIL PROTECTED]:port/ */ hostname; /* hostname from URI (or from Host: header) */ port_str; /* port string (integer representation is in "port") */ path; /* the request path (or "/" if only scheme://host was given) */ query; /* Everything after a '?' in the path, if present */ fragment; /* Trailing "#fragment" string, if present */ plus flags to indicate whether the strings have valid values. This is meant to serve as the platform for *BIG* savings in code complexity for the proxy module (and maybe the vhost logic). NOTE: This code is enabled only if the WITH_UTIL_URI define is set; currently this is not enabled by default. [Martin Kraemer] Reviewed by: Dean Gaudet (on a previous occasion) Revision Changes Path 1.671 +24 -0 apache-1.3/src/CHANGES Index: CHANGES =================================================================== RCS file: /home/cvs/apache-1.3/src/CHANGES,v retrieving revision 1.670 retrieving revision 1.671 diff -u -u -r1.670 -r1.671 --- CHANGES 1998/02/27 14:55:02 1.670 +++ CHANGES 1998/02/27 15:15:13 1.671 @@ -1,5 +1,29 @@ Changes with Apache 1.3b6 + *) For testing purposes, I added a new source called main/util_uri.c; + It contains a routine parse_uri_components_regex() and friends which + tries to break an URI into its parts. These parts are stored in a new + uri_components structure within each request_rec and are therefore + available to all routines which act on a request. + Additionally, an unparse routine is supplied which re-assembles the + URI components back to an URI, optionally hiding the username:password@ + part from ftp proxy requests, and other useful routines. + Within the structure, you find on a ready-for-use basis: + scheme; /* scheme ("http"/"ftp"/...) */ + hostinfo; /* combined [user[:[EMAIL PROTECTED]:port] */ + user; /* user name, as in http://user:[EMAIL PROTECTED]:port/ */ + password; /* password, as in http://user:[EMAIL PROTECTED]:port/ */ + hostname; /* hostname from URI (or from Host: header) */ + port_str; /* port string (integer representation is in "port") */ + path; /* the request path (or "/" if only scheme://host was given) */ + query; /* Everything after a '?' in the path, if present */ + fragment; /* Trailing "#fragment" string, if present */ + plus flags to indicate whether the strings have valid values. + This is meant to serve as the platform for *BIG* savings in + code complexity for the proxy module (and maybe the vhost logic). + NOTE: This code is enabled only if the WITH_UTIL_URI define is set; + currently this is not enabled by default. [Martin Kraemer] + *) Make all possible meta-construct expansions ($N, %N, %{NAME} and ${map:key}) available for all location where a string is created in mod_rewrite rewriting rulesets: 1st arg of RewriteCond, 2nd arg of 1.188 +7 -0 apache-1.3/src/include/httpd.h Index: httpd.h =================================================================== RCS file: /home/cvs/apache-1.3/src/include/httpd.h,v retrieving revision 1.187 retrieving revision 1.188 diff -u -u -r1.187 -r1.188 --- httpd.h 1998/02/18 08:39:21 1.187 +++ httpd.h 1998/02/27 15:15:15 1.188 @@ -537,6 +537,10 @@ typedef struct request_rec request_rec; typedef struct listen_rec listen_rec; +#ifdef WITH_UTIL_URI +#include "util_uri.h" +#endif + struct request_rec { pool *pool; @@ -656,6 +660,9 @@ char *path_info; char *args; /* QUERY_ARGS, if any */ struct stat finfo; /* ST_MODE set to zero if no such file */ +#ifdef WITH_UTIL_URI + uri_components parsed_uri; /* components of uri, dismantled */ +#endif /* Various other config info which may change with .htaccess files * These are config vectors, with one void* pointer for each module 1.1 apache-1.3/src/include/util_uri.h Index: util_uri.h =================================================================== /* ==================================================================== * Copyright (c) 1995-1997 The Apache Group. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * 4. The names "Apache Server" and "Apache Group" must not be used to * endorse or promote products derived from this software without * prior written permission. * * 5. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Group and was originally based * on public domain software written at the National Center for * Supercomputing Applications, University of Illinois, Urbana-Champaign. * For more information on the Apache Group and the Apache HTTP server * project, please see <http://www.apache.org/>. * */ /* * util_uri.h: External Interface of util_uri.c */ #ifndef UTIL_URI_H #define UTIL_URI_H typedef struct { const char *name; unsigned short default_port; } schemes_t; #define DEFAULT_FTP_DATA_PORT 20 #define DEFAULT_FTP_PORT 21 #define DEFAULT_GOPHER_PORT 70 #define DEFAULT_NNTP_PORT 119 #define DEFAULT_WAIS_PORT 210 #define DEFAULT_HTTPS_PORT 443 #define DEFAULT_SNEWS_PORT 563 #define DEFAULT_PROSPERO_PORT 1525 /* WARNING: conflict w/Oracle */ /* Flags passed to unparse_uri_components(): */ #define UNP_OMITSITEPART (1U<<0) /* suppress "scheme://[EMAIL PROTECTED]:port" */ #define UNP_OMITUSER (1U<<1) /* Just omit user */ #define UNP_OMITPASSWORD (1U<<2) /* Just omit password */ #define UNP_OMITUSERINFO (UNP_OMITUSER|UNP_OMITPASSWORD) /* omit "user:password@" part */ #define UNP_REVEALPASSWORD (1U<<3) /* Show plain text password (default: show XXXXXXXX) */ typedef struct { char *scheme; /* scheme ("http"/"ftp"/...) */ char *hostinfo; /* combined [user[:[EMAIL PROTECTED]:port] */ char *user; /* user name, as in http://user:[EMAIL PROTECTED]:port/ */ char *password; /* password, as in http://user:[EMAIL PROTECTED]:port/ */ char *hostname; /* hostname from URI (or from Host: header) */ char *port_str; /* port string (integer representation is in "port") */ char *path; /* the request path (or "/" if only scheme://host was given) */ char *query; /* Everything after a '?' in the path, if present */ char *fragment; /* Trailing "#fragment" string, if present */ struct hostent *hostent; unsigned hostlen; /* strlen("scheme://[user[:[EMAIL PROTECTED]:port]") */ unsigned short port; /* The port number, numeric */ unsigned is_initialized:1; unsigned has_scheme:1; unsigned has_hostinfo:1; unsigned has_user:1; unsigned has_password:1; unsigned has_hostname:1; unsigned has_port:1; unsigned has_path:1; unsigned has_query:1; unsigned has_fragment:1; unsigned dns_looked_up:1; unsigned dns_resolved:1; } uri_components; /* util_uri.c */ extern unsigned short default_port_for_scheme(const char *scheme_str); extern unsigned short default_port_for_request(const request_rec *r); extern struct hostent *pduphostent(pool *p, struct hostent *hp); extern struct hostent *pgethostbyname(pool *p, const char *hostname); extern char *unparse_uri_components(pool *p, const uri_components *uptr, int *pHostlen, unsigned flags); extern int parse_uri_components(pool *p, const char *uri, uri_components *uptr, int *pHostlen); extern int parse_uri_components_regex(pool *p, const char *uri, uri_components *uptr); #endif /*UTIL_URI_H*/ 1.13 +1 -1 apache-1.3/src/main/Makefile.tmpl Index: Makefile.tmpl =================================================================== RCS file: /home/cvs/apache-1.3/src/main/Makefile.tmpl,v retrieving revision 1.12 retrieving revision 1.13 diff -u -u -r1.12 -r1.13 --- Makefile.tmpl 1998/02/23 00:04:43 1.12 +++ Makefile.tmpl 1998/02/27 15:15:18 1.13 @@ -11,7 +11,7 @@ OBJS= alloc.o http_main.o http_core.o http_config.o http_request.o \ http_log.o http_protocol.o rfc1413.o util.o util_script.o buff.o \ - md5c.o util_md5.o http_bprintf.o util_date.o \ + md5c.o util_md5.o http_bprintf.o util_date.o util_uri.o \ fnmatch.o http_vhost.o .c.o: 1.296 +3 -0 apache-1.3/src/main/http_main.c Index: http_main.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/http_main.c,v retrieving revision 1.295 retrieving revision 1.296 diff -u -u -r1.295 -r1.296 --- http_main.c 1998/02/24 12:27:19 1.295 +++ http_main.c 1998/02/27 15:15:19 1.296 @@ -2886,6 +2886,9 @@ #ifdef NEED_HASHBANG_EMUL printf(" -D NEED_HASHBANG_EMUL\n"); #endif +#ifdef WITH_UTIL_URI + printf(" -D WITH_UTIL_URI\n"); +#endif printf("\n"); } 1.192 +134 -0 apache-1.3/src/main/http_protocol.c Index: http_protocol.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/http_protocol.c,v retrieving revision 1.191 retrieving revision 1.192 diff -u -u -r1.191 -r1.192 --- http_protocol.c 1998/02/22 21:37:47 1.191 +++ http_protocol.c 1998/02/27 15:15:20 1.192 @@ -570,8 +570,71 @@ return total; } + +/* parse_uri: check uri, determine whether proxy request, TRACE, or local request + * Side Effects: + * - sets r->proxyreq if "scheme://host:port" found + * - sets r->args to rest after '?' (or NULL if no '?') unless TRACE or proxy req. + * - sets r->uri to request uri (without r->args part unless TRACE or proxy req.) + *#ifdef WITH_UTIL_URI + * - sets r->hostname (if not set already) from request (scheme://host:port) + * - sets r->hostlen to length of "scheme://...host:port" prefix + *#endif + */ void parse_uri(request_rec *r, const char *uri) { +#ifdef WITH_UTIL_URI + int hostlen = 0; + int status = HTTP_OK; + + /* If an identical uri was parsed before, return without action */ + if (r->parsed_uri.is_initialized && r->uri && strcmp(uri, r->uri) == 0) + return; + + /* Simple syntax Errors in URLs are trapped by parse_uri_components(). */ + status = parse_uri_components_regex(r->pool, uri, &r->parsed_uri); + + if (is_HTTP_SUCCESS(status)) { + + r->hostlen = r->parsed_uri.hostlen; + + /* if hostlen is 0, it's not a proxy request */ + r->proxyreq = (r->hostlen > 0); + + if (!r->proxyreq) { + r->hostname = NULL; + + if (r->method && !strcmp(r->method, "TRACE")) { + /* don't split into path & args for TRACE requests */ + r->args = NULL; + r->uri = pstrdup(r->pool, uri); + } + else { + r->uri = r->parsed_uri.has_path ? r->parsed_uri.path : "/"; + r->args = r->parsed_uri.query; + } + } + else { + if (r->hostlen == strlen(uri)) + /* the request is just http://hostname - no trailing slash. + * Provide one: + */ + r->uri = pstrcat(r->pool, uri, "/", NULL); + else + r->uri = pstrdup(r->pool, uri); + r->hostname = r->parsed_uri.hostname; + /* no args splitting for proxy requests */ + r->args = NULL; + } + } + else { + r->args = NULL; + r->hostlen = 0; + r->hostname = NULL; + r->status = status; /* set error status */ + r->uri = pstrdup(r->pool, uri); + } +#else /*WITH_UTIL_URI*/ const char *s; #if defined(__EMX__) || defined(WIN32) @@ -621,8 +684,16 @@ else r->args = NULL; } +#endif /*WITH_UTIL_URI*/ } +/* check_fulluri: check full uri against main server names/addresses + * Side Effects: + *#ifndef WITH_UTIL_URI + * - sets r->hostname (if not set already) from request (scheme://host:port) + * - sets r->hostlen to length of "scheme://host:port" part + *#endif + */ const char *check_fulluri(request_rec *r, const char *uri) { char *host, *proto, *slash, *colon; @@ -630,6 +701,63 @@ unsigned port; const char *res_uri; +#ifdef WITH_UTIL_URI + if (!r->parsed_uri.has_hostname + || !r->parsed_uri.has_scheme + || strcasecmp(r->parsed_uri.scheme, "http") != 0) + return uri; + + /* Note: There's no use comparing against ntohs(r->connection->local_addr.sin_port) + * here, because in a proxy request, the two have nothing in common. + */ + /* Make sure ports match */ + port = (r->parsed_uri.has_port) ? r->parsed_uri.port : default_port_for_request(r); + if (port != r->server->port) + return uri; + + host = r->parsed_uri.hostname; + + /* Easy simplification: If main server host name and port match, + * then this request is rewritten from a net_path to an abs_path + * and reduced from a proxyreq to a local request. + */ + if (strcasecmp(host, r->server->server_hostname) == 0 + || strcmp(host, inet_ntoa(r->connection->local_addr.sin_addr)) == 0) + { + r->proxyreq = 0; + r->uri += r->hostlen; + r->hostlen = 0; + } + else { + /* Now things get a bit trickier - check the IP address(es) of + * the host they gave, see if it matches ours. + */ + struct hostent *hp; + int n; + if (r->parsed_uri.dns_looked_up) + /* looked up earlier; re-use: */ + hp = r->parsed_uri.hostent; + else { + hp = pgethostbyname(r->pool, host); + r->parsed_uri.dns_looked_up = 1; + r->parsed_uri.dns_resolved = (hp != NULL); + r->parsed_uri.hostent = hp; + } + + if (r->parsed_uri.dns_resolved) { + for (n = 0; hp->h_addr_list[n] != NULL; n++) { + if (r->connection->local_addr.sin_addr.s_addr == + (((struct in_addr *) (hp->h_addr_list[n]))->s_addr)) { + r->proxyreq = 0; + r->uri += r->hostlen; + r->hostlen = 0; + break; + } + } + } + } + return r->uri; +#else /*WITH_UTIL_URI*/ /* This routine parses full URLs, if they match the server */ proto = http_method(r); plen = strlen(proto); @@ -698,6 +826,7 @@ } return uri; +#endif /*WITH_UTIL_URI*/ } int read_request_line(request_rec *r) @@ -746,8 +875,13 @@ r->the_request = pstrdup(r->pool, l); r->method = getword_white(r->pool, &ll); uri = getword_white(r->pool, &ll); +#ifdef WITH_UTIL_URI + parse_uri(r, uri); + r->uri = pstrdup(r->pool, check_fulluri(r, r->uri)); /* r->uri isn't const, so copy */ +#else uri = check_fulluri(r, uri); parse_uri(r, uri); +#endif r->assbackwards = (ll[0] == '\0'); r->protocol = pstrdup(r->pool, ll[0] ? ll : "HTTP/0.9"); 1.108 +8 -1 apache-1.3/src/main/http_request.c Index: http_request.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/http_request.c,v retrieving revision 1.107 retrieving revision 1.108 diff -u -u -r1.107 -r1.108 --- http_request.c 1998/02/18 10:01:14 1.107 +++ http_request.c 1998/02/27 15:15:21 1.108 @@ -749,6 +749,9 @@ rnew->uri = make_full_path(rnew->pool, udir, new_file); rnew->filename = make_full_path(rnew->pool, fdir, new_file); +#ifdef WITH_UTIL_URI + parse_uri(rnew, rnew->uri); /* fill in parsed_uri values */ +#endif if (stat(rnew->filename, &rnew->finfo) < 0) { rnew->finfo.st_mode = 0; } @@ -794,6 +797,10 @@ } } else { +#ifdef WITH_UTIL_URI + /* XXX: @@@: What should be done with the parsed_uri values? */ + parse_uri(rnew, new_file); /* fill in parsed_uri values */ +#endif /* * XXX: this should be set properly like it is in the same-dir case * but it's actually sometimes to impossible to do it... because the @@ -1196,7 +1203,7 @@ new->pool = r->pool; /* - * A whole lot of this really ought to be shared with protocol.c... + * A whole lot of this really ought to be shared with http_protocol.c... * another missing cleanup. It's particularly inappropriate to be * setting header_only, etc., here. */ 1.7 +4 -0 apache-1.3/src/main/http_vhost.c Index: http_vhost.c =================================================================== RCS file: /home/cvs/apache-1.3/src/main/http_vhost.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -u -r1.6 -r1.7 --- http_vhost.c 1998/02/01 21:19:30 1.6 +++ http_vhost.c 1998/02/27 15:15:21 1.7 @@ -329,6 +329,9 @@ * whack of /24s. This is probably the most common configuration for * ISPs with large virtual servers. * + * NOTE: This function is symmetric (i.e. collapses all 4 octets + * into one), so machine byte order (big/little endianness) does not matter. + * * Hash function provided by David Hankins. */ static ap_inline unsigned hash_inaddr(unsigned key) @@ -689,6 +692,7 @@ r->server = r->connection->server = s; if (r->hostlen && !strncasecmp(r->uri, "http://", 7)) { r->uri += r->hostlen; + r->proxyreq = 0; parse_uri(r, r->uri); } } 1.1 apache-1.3/src/main/util_uri.c Index: util_uri.c =================================================================== /* ==================================================================== * Copyright (c) 1995-1997 The Apache Group. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * 4. The names "Apache Server" and "Apache Group" must not be used to * endorse or promote products derived from this software without * prior written permission. * * 5. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Group and was originally based * on public domain software written at the National Center for * Supercomputing Applications, University of Illinois, Urbana-Champaign. * For more information on the Apache Group and the Apache HTTP server * project, please see <http://www.apache.org/>. * */ /* * util_uri.c: URI related utility things * */ #include "httpd.h" #include "http_log.h" #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 */ static schemes_t schemes[] = { {"ftp", DEFAULT_FTP_PORT}, {"gopher", DEFAULT_GOPHER_PORT}, {"http", DEFAULT_HTTP_PORT}, {"nntp", DEFAULT_NNTP_PORT}, {"wais", DEFAULT_WAIS_PORT}, {"https", DEFAULT_HTTPS_PORT}, {"snews", DEFAULT_SNEWS_PORT}, {"prospero", DEFAULT_PROSPERO_PORT}, { NULL, 0xFFFF } /* unknown port */ }; unsigned short default_port_for_scheme(const char *scheme_str) { schemes_t *scheme; for (scheme = schemes; scheme->name != NULL; ++scheme) if (strcasecmp(scheme_str, scheme->name) == 0) return scheme->default_port; return 0; } #ifdef WITH_UTIL_URI unsigned short default_port_for_request(const request_rec *r) { return (r->parsed_uri.has_scheme) ? default_port_for_scheme(r->parsed_uri.scheme) : 0; } #endif /*WITH_UTIL_URI*/ static unsigned short default_port_for_uri_components(const uri_components *uri_p) { return (uri_p->has_scheme) ? default_port_for_scheme(uri_p->scheme) : 0; } /* 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. */ struct hostent *pduphostent(pool *p, struct hostent *hp) { struct hostent *newent; char **ptrs; char **aliases; struct in_addr *addrs; int i = 0, j = 0; if (hp == NULL) return hp; /* 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 *) palloc(p, sizeof(*hp)); aliases = (char **) palloc(p, (j+1) * sizeof(char*)); ptrs = (char **) palloc(p, (i+1) * sizeof(char*)); addrs = (struct in_addr *) palloc(p, (i+1) * sizeof(struct in_addr)); *newent = *hp; newent->h_name = 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] = 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; } /* 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) */ struct hostent *pgethostbyname(pool *p, const char *hostname) { struct hostent *hp = gethostbyname(hostname); return (hp == NULL) ? NULL : pduphostent(p, hp); } /* Unparse a uri_components structure to an URI string. * Optionally suppress the password for security reasons. */ char *unparse_uri_components(pool *p, const uri_components *uptr, int *pHostlen, unsigned flags) { char *ret = ""; /* Construct a "user:password@" string, honoring the passed UNP_ flags: */ if (uptr->has_user||uptr->has_password) ret = pstrcat (p, (uptr->has_user && !(flags & UNP_OMITUSER)) ? uptr->user : "", (uptr->has_password && !(flags & UNP_OMITPASSWORD)) ? ":" : "", (uptr->has_password && !(flags & UNP_OMITPASSWORD)) ? ((flags & UNP_REVEALPASSWORD) ? uptr->password : "XXXXXXXX") : "", "@", NULL); /* Construct scheme://site string */ if (uptr->has_hostname && !(flags & UNP_OMITSITEPART)) { ret = pstrcat (p, uptr->scheme, "://", ret, uptr->has_hostname ? uptr->hostname : "", uptr->has_port ? ":" : "", uptr->has_port ? uptr->port_str : "", NULL); } /* Return length constructed so far (the famous "hostlen") */ if (pHostlen != NULL) *pHostlen = strlen(ret); /* Append path, query and fragment strings: */ ret = pstrcat (p, ret, uptr->path, uptr->has_query ? "?" : "", uptr->has_query ? uptr->query : "", uptr->has_fragment ? "#" : NULL, uptr->has_fragment ? uptr->fragment : NULL, NULL); return ret; } /* parse_uri_components(): * Parse a given URI, fill in all supplied fields of a uri_components * structure. This eliminates the necessity of extracting host, port, * path, query info repeatedly in the modules. * Side effects: * - fills in fields of uri_components *uptr * - none on any of the r->* fields */ int parse_uri_components(pool *p, const char *uri, uri_components *uptr, int *pHostlen) { const char *s; int ret = HTTP_OK; int hostlen = 0; /* 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; /* A proxy request contains a ':' early on (after the scheme), * but not as first character. RFC1738 allows [a-zA-Z0-9-+.]: */ for (s = uri; s != '\0'; s++) if (!isalnum(*s) && *s != '+' && *s != '-' && *s != '.') break; if (s == uri || s[0] != ':' || s[1] == '\0') { /* not a full URL (not: scheme://host/path), so no proxy request: */ /* Store path, without the optional "?query" argument: */ uptr->has_path = 1; uptr->path = getword (p, &uri, '?'); uptr->has_query = (uri[0] != '\0'); uptr->query = (uptr->has_query) ? pstrdup(p, uri) : NULL; #if defined(__EMX__) || defined(WIN32) /* Handle path translations for OS/2 and plug security hole. * This will prevent "http://www.wherever.com/..\..\/" from * returning a directory for the root drive. */ for (s = uptr->path; (s = strchr(s, '\\')) != NULL; ) *s = '/'; #ifndef WIN32 /* for OS/2 only: */ /* Fix OS/2 HPFS filename case problem. */ uptr->path = strlwr(uptr->path); #endif #endif /* __EMX__ || WIN32 */ } else { /* Yes, it is a proxy request. We've detected the scheme, now * we split the URI's components and mark what we've found: * - scheme * followed by "://", then: * - [ username [ ":" password ] "@" ] * - hostname * [ ":" port ] * [ "/" path ... [ "?" query ] ] */ /* As per RFC1738: * The generic form of a URL is: * genericurl = scheme ":" schemepart * * the scheme is in lower case; interpreters should use case-ignore * scheme = 1*[ lowalpha | digit | "+" | "-" | "." ] * * Extract the scheme: */ s = uri; uptr->scheme = getword(p, &s, ':'); uptr->has_scheme = 1; /* URL schemeparts for ip based protocols: * * ip-schemepart = "//" login [ "/" urlpath ] * * login = [ user [ ":" password ] "@" ] hostport * hostport = host [ ":" port ] * host = hostname | hostnumber * hostname = *[ domainlabel "." ] toplabel * domainlabel = alphadigit | alphadigit *[ alphadigit | "-" ] alphadigit * toplabel = alpha | alpha *[ alphadigit | "-" ] alphadigit * alphadigit = alpha | digit * hostnumber = digits "." digits "." digits "." digits * port = digits * user = *[ uchar | ";" | "?" | "&" | "=" ] * password = *[ uchar | ";" | "?" | "&" | "=" ] * urlpath = *xchar */ /* if IP-schemepart follows, extract host, port etc. */ if (s[0] == '/' && s[1] == '/') { char *tmp; s += 2; if ((tmp = strchr(s, '/')) != NULL) { hostlen = (tmp - uri); /* In the request_rec structure, the uri is not * separated into path & query for proxy requests. * But here, we want maximum knowledge about the request, * so we still split them. */ uptr->has_path = 1; uptr->path = getword_nc(p, &tmp, '?'); uptr->has_query = (tmp[0] != '\0'); uptr->query = (uptr->has_query) ? pstrdup(p, tmp) : NULL; } else { /* the request is just http://hostname - no trailing slash. * Provide one: */ uptr->path = "/"; uptr->has_path = 1; uptr->has_query = 0; hostlen = strlen(uri); } uptr->hostname = getword (p, &s, '/'); uptr->has_hostname = uptr->hostname[0] != '\0'; /* disintegrate "[EMAIL PROTECTED]" */ /* NOTE: using reverse search here because user:password might * contain a '@' as well (ftp login: user=ftp : [EMAIL PROTECTED]) */ if ((tmp = strrchr(uptr->hostname, '@')) != NULL) { uptr->user = uptr->hostname; uptr->has_user = 1; *tmp++ = '\0'; uptr->hostname = tmp; /* disintegrate "user:password" */ if ((tmp = strchr(uptr->user, ':')) != NULL) { *tmp++ = '\0'; uptr->password = tmp; uptr->has_password = 1; } } /* disintegrate "host:port" */ if ((tmp = strchr(uptr->hostname, ':')) != NULL) { *tmp++ = '\0'; uptr->port_str = tmp; uptr->port = (unsigned short) strtol(tmp, &tmp, 10); uptr->has_port = 1; /* Catch possible problem: http://www.apache.org:80@@@/dist/ */ if (*tmp != '\0') ret = HTTP_BAD_REQUEST; } /* Strip any trailing dots in hostname */ tmp = &uptr->hostname[strlen(uptr->hostname)-1]; for (; *tmp == '.' && tmp > uptr->hostname; --tmp) *tmp = '\0'; /* This name hasn't been looked up yet */ uptr->dns_looked_up = 0; } /* If the ip-schemepart doesn't start with "//", deny: */ else ret = HTTP_BAD_REQUEST; } /* If caller is interested in the length of the scheme://...host:port prefix: */ if (pHostlen != NULL) *pHostlen = hostlen; return ret; } /* parse_uri_components_regex(): * Parse a given URI, fill in all supplied fields of a uri_components * structure. This eliminates the necessity of extracting host, port, * path, query info repeatedly in the modules. * Side effects: * - fills in fields of uri_components *uptr * - none on any of the r->* fields */ int parse_uri_components_regex(pool *p, const char *uri, uri_components *uptr) { int ret = HTTP_OK; static struct { regex_t uri; regex_t hostpart; regmatch_t match[10]; /* This must have at least as much elements * as there are braces in the re_strings */ unsigned is_initialized:1; } re = { 0, 0, 0 }; ap_assert (uptr != NULL); /* 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; if (!re.is_initialized) { const char *re_str; re.is_initialized = 1; /* This is a modified version of the regex that appeared in * http://www.ics.uci.edu/~fielding/url/url.txt * It doesnt allow the uri to contain a scheme but no hostinfo * or vice versa. * $ 12 3 4 5 6 7 8 */ re_str = "^(([^:/?#]+)://([^/?#]+))?([^?#]*)(\\?([^#]*))?(#(.*))?"; /* ^^scheme^^://^^site^^^ ^^path^^ ?^query^ #frag */ if ((ret = regcomp(&re.uri, re_str, REG_EXTENDED)) != 0) { char line[1024]; /* Make a readable error message */ ret = regerror(ret, &re.uri, line, sizeof line); aplog_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, "Internal error: regcomp(\"%s\") returned non-zero (%s) - " "possibly due to broken regex lib! " "Did you define WANTHSREGEX=yes?", re_str, line); return HTTP_INTERNAL_SERVER_ERROR; } /* This is a sub-RE which will break down the hostinfo part, * i.e., user, password, hostname and port. * $ 12 3 4 5 6 */ re_str = "^(([^:]*):(.*)?@)?([^@:]*)(:(.*))?$"; /* ^^user^ :pw ^host^ port */ if ((ret = regcomp(&re.hostpart, re_str, REG_EXTENDED|REG_ICASE)) != 0) { char line[1024]; /* Make a readable error message */ ret = regerror(ret, &re.hostpart, line, sizeof line); aplog_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, "Internal error: regcomp(\"%s\") returned non-zero (%s) - " "possibly due to broken regex lib! " "Did you define WANTHSREGEX=yes?", re_str, line); return HTTP_INTERNAL_SERVER_ERROR; } } ret = regexec(&re.uri, uri, re.uri.re_nsub, re.match, 0); if (ret != 0) { aplog_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, "regexec() could not parse uri (\"%s\")", uri); return HTTP_BAD_REQUEST; } /* if hostlen is 0, it's not a proxy request */ uptr->hostlen = (re.match[1].rm_eo - re.match[1].rm_so); uptr->has_scheme = (re.match[2].rm_so != re.match[2].rm_eo); uptr->has_hostinfo = (re.match[3].rm_so != re.match[3].rm_eo); uptr->has_path = (re.match[4].rm_so != re.match[4].rm_eo); uptr->has_query = (re.match[5].rm_so != re.match[5].rm_eo); uptr->has_fragment = (re.match[7].rm_so != re.match[7].rm_eo); if (uptr->has_scheme) uptr->scheme = pstrndup (p, uri+re.match[2].rm_so, re.match[2].rm_eo - re.match[2].rm_so); if (uptr->has_hostinfo) uptr->hostinfo = pstrndup (p, uri+re.match[3].rm_so, re.match[3].rm_eo - re.match[3].rm_so); if (uptr->has_path) uptr->path = pstrndup (p, uri+re.match[4].rm_so, re.match[4].rm_eo - re.match[4].rm_so); if (uptr->has_query) uptr->query = pstrndup (p, uri+re.match[6].rm_so, re.match[6].rm_eo - re.match[6].rm_so); if (uptr->has_fragment) uptr->fragment = pstrndup (p, uri+re.match[7].rm_so, re.match[7].rm_eo - re.match[7].rm_so); if (uptr->has_hostinfo) { /* Parse the hostinfo part to extract user, password, host, and port */ ret = regexec(&re.hostpart, uptr->hostinfo, re.hostpart.re_nsub, re.match, 0); if (ret != 0) { aplog_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, "regexec() could not parse (\"%s\") as host part", uptr->hostinfo); return HTTP_BAD_REQUEST; } /* $ 12 3 4 5 6 */ /* = "^(([^:]*):(.*)?@)?([^@:]*)(:([0-9]*))?$" */ /* ^^user^ :pw ^host^ port */ if (uptr->has_user = (re.match[2].rm_so != re.match[2].rm_eo)) uptr->user = pstrndup (p, uptr->hostinfo+re.match[2].rm_so, re.match[2].rm_eo - re.match[2].rm_so); if (uptr->has_password = (re.match[3].rm_so != re.match[3].rm_eo)) uptr->password = pstrndup (p, uptr->hostinfo+re.match[3].rm_so, re.match[3].rm_eo - re.match[3].rm_so); if (uptr->has_hostname = (re.match[4].rm_so != re.match[4].rm_eo)) uptr->hostname = pstrndup (p, uptr->hostinfo+re.match[4].rm_so, re.match[4].rm_eo - re.match[4].rm_so); if (uptr->has_port = (re.match[5].rm_so != re.match[5].rm_eo)) { uptr->port_str = pstrndup (p, uptr->hostinfo+re.match[5].rm_so+1, re.match[5].rm_eo - re.match[5].rm_so-1); /* Note that the port string can be empty. * If it is, we use the default port associated with the scheme */ if (uptr->port_str[0] != '\0') { char *endstr; uptr->port = strtoul(uptr->port_str, &endstr, 10); if (*endstr != '\0') /* Invalid characters after ':' found */ return HTTP_BAD_REQUEST; } else uptr->port = default_port_for_scheme(uptr->scheme); } } #if defined(__EMX__) || defined(WIN32) /* Handle path translations for OS/2 and plug security hole. * This will prevent "http://www.wherever.com/..\..\/" from * returning a directory for the root drive. */ { char *s; for (s = uptr->path; (s = strchr(s, '\\')) != NULL; ) *s = '/'; } #ifndef WIN32 /* for OS/2 only: */ /* Fix OS/2 HPFS filename case problem. */ str_tolower(uptr->path); #endif #endif /* __EMX__ || WIN32 */ if (ret == 0) ret = HTTP_OK; return ret; } 1.41 +70 -8 apache-1.3/src/modules/proxy/mod_proxy.c Index: mod_proxy.c =================================================================== RCS file: /home/cvs/apache-1.3/src/modules/proxy/mod_proxy.c,v retrieving revision 1.40 retrieving revision 1.41 diff -u -u -r1.40 -r1.41 --- mod_proxy.c 1998/02/27 14:47:15 1.40 +++ mod_proxy.c 1998/02/27 15:15:24 1.41 @@ -164,14 +164,31 @@ char *url, *p; int i; - if (strncmp(r->filename, "proxy:", 6) != 0) + if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0) return DECLINED; url = &r->filename[6]; + +#ifdef WITH_UTIL_URI + + if (!r->parsed_uri.has_scheme) { + return DECLINED; + } + +/* canonicalise each specific scheme */ + if (strcasecmp(r->parsed_uri.scheme, "http") == 0) + return proxy_http_canon(r, url + 5, "http", default_port_for_scheme(r->parsed_uri.scheme)); + else if (strcasecmp(r->parsed_uri.scheme, "ftp") == 0) + return proxy_ftp_canon(r, url + 4); + else + return OK; /* otherwise; we've done the best we can */ + +#else /*WITH_UTIL_URI*/ + /* lowercase the scheme */ p = strchr(url, ':'); if (p == NULL || p == url) - return BAD_REQUEST; + return HTTP_BAD_REQUEST; for (i = 0; i != p - url; i++) url[i] = tolower(url[i]); @@ -182,6 +199,8 @@ return proxy_ftp_canon(r, url + 4); else return OK; /* otherwise; we've done the best we can */ + +#endif /*WITH_UTIL_URI*/ } static void proxy_init(server_rec *r, pool *p) @@ -199,6 +218,42 @@ /* The "ProxyDomain" directive determines what domain will be appended */ static int proxy_needsdomain(request_rec *r, const char *url, const char *domain) { +#ifdef WITH_UTIL_URI + char *nuri, *ref; + char strport[10]; + + /* We only want to worry about GETs */ + if (!r->proxyreq || r->method_number != M_GET + || !r->parsed_uri.has_hostname) + return DECLINED; + + /* If host does contain a dot already, or it is "localhost", decline */ + if (strchr(r->parsed_uri.hostname, '.') != NULL + || strcasecmp(r->parsed_uri.hostname, "localhost") == 0) + return DECLINED; /* host name has a dot already */ + + ref = table_get(r->headers_in, "Referer"); + + /* Reassemble the request, but insert the domain after the host name */ + /* Note that the domain name always starts with a dot */ + r->parsed_uri.hostname = pstrcat(r->pool, r->parsed_uri.hostname, + domain, NULL); + nuri = unparse_uri_components(r->pool, + &r->parsed_uri, + &r->parsed_uri.hostlen, + UNP_REVEALPASSWORD); + + table_set(r->headers_out, "Location", nuri); + aplog_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r->server, + "Domain missing: %s sent to %s%s%s", r->uri, + unparse_uri_components(r->pool, &r->parsed_uri, + &r->parsed_uri.hostlen, UNP_OMITUSERINFO), + ref ? " from " : "", ref ? ref : ""); + + return HTTP_MOVED_PERMANENTLY; + +#else /*WITH_UTIL_URI*/ + char *scheme = pstrdup(r->pool, url); char *url_copy, *user = NULL, *password = NULL, *path, *err, *host; int port = -1; @@ -258,6 +313,8 @@ return HTTP_MOVED_PERMANENTLY; } + +#endif /*WITH_UTIL_URI*/ } /* -------------------------------------------------------------- */ @@ -275,7 +332,7 @@ struct cache_req *cr; int direct_connect = 0; - if (strncmp(r->filename, "proxy:", 6) != 0) + if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0) return DECLINED; if ((rc = setup_client_block(r, REQUEST_CHUNKED_ERROR))) @@ -284,16 +341,18 @@ url = r->filename + 6; p = strchr(url, ':'); if (p == NULL) - return BAD_REQUEST; + return HTTP_BAD_REQUEST; rc = proxy_cache_check(r, url, &conf->cache, &cr); if (rc != DECLINED) return rc; /* If the host doesn't have a domain name, add one and redirect. */ - if (conf->domain != NULL - && proxy_needsdomain(r, url, conf->domain) == REDIRECT) - return REDIRECT; + if (conf->domain != NULL) { + rc = proxy_needsdomain(r, url, conf->domain); + if (is_HTTP_REDIRECT(rc)) + return HTTP_MOVED_PERMANENTLY; + } *p = '\0'; scheme = pstrdup(r->pool, url); @@ -348,7 +407,7 @@ rc = DECLINED; /* an error or success */ - if (rc != DECLINED && rc != BAD_GATEWAY) + if (rc != DECLINED && rc != HTTP_BAD_GATEWAY) return rc; /* we failed to talk to the upstream proxy */ } @@ -523,6 +582,9 @@ if (!found) { New = push_array(conf->dirconn); New->name = arg; +#ifdef WITH_UTIL_URI + New->hostentry = NULL;; +#endif /*WITH_UTIL_URI*/ if (proxy_is_ipaddr(New, parms->pool)) { #if DEBUGGING 1.30 +4 -0 apache-1.3/src/modules/proxy/mod_proxy.h Index: mod_proxy.h =================================================================== RCS file: /home/cvs/apache-1.3/src/modules/proxy/mod_proxy.h,v retrieving revision 1.29 retrieving revision 1.30 diff -u -u -r1.29 -r1.30 --- mod_proxy.h 1998/02/27 10:18:39 1.29 +++ mod_proxy.h 1998/02/27 15:15:25 1.30 @@ -162,7 +162,11 @@ struct dirconn_entry { char *name; struct in_addr addr, mask; +#ifdef WITH_UTIL_URI + struct hostent *hostentry; +#else /*WITH_UTIL_URI*/ struct hostent hostlist; +#endif /*WITH_UTIL_URI*/ int (*matcher) (struct dirconn_entry * This, request_rec *r); }; 1.40 +4 -4 apache-1.3/src/modules/proxy/proxy_http.c Index: proxy_http.c =================================================================== RCS file: /home/cvs/apache-1.3/src/modules/proxy/proxy_http.c,v retrieving revision 1.39 retrieving revision 1.40 diff -u -u -r1.39 -r1.40 --- proxy_http.c 1998/02/23 08:04:11 1.39 +++ proxy_http.c 1998/02/27 15:15:26 1.40 @@ -77,7 +77,7 @@ port = def_port; err = proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port); if (err) - return BAD_REQUEST; + return HTTP_BAD_REQUEST; /* now parse path/search args, according to rfc1738 */ /* N.B. if this isn't a true proxy request, then the URL _path_ @@ -94,13 +94,13 @@ /* process path */ path = proxy_canonenc(r->pool, url, strlen(url), enc_path, r->proxyreq); if (path == NULL) - return BAD_REQUEST; + return HTTP_BAD_REQUEST; /* process search */ if (p != NULL) { search = p; if (search == NULL) - return BAD_REQUEST; + return HTTP_BAD_REQUEST; } else search = NULL; @@ -252,7 +252,7 @@ if (sock == -1) { aplog_error(APLOG_MARK, APLOG_ERR, r->server, "proxy: error creating socket"); - return SERVER_ERROR; + return HTTP_INTERNAL_SERVER_ERROR; } if (conf->recv_buffer_size) { 1.45 +17 -15 apache-1.3/src/modules/proxy/proxy_util.c Index: proxy_util.c =================================================================== RCS file: /home/cvs/apache-1.3/src/modules/proxy/proxy_util.c,v retrieving revision 1.44 retrieving revision 1.45 diff -u -u -r1.44 -r1.45 --- proxy_util.c 1998/02/27 10:18:40 1.44 +++ proxy_util.c 1998/02/27 15:15:26 1.45 @@ -58,6 +58,9 @@ #include "md5.h" #include "multithread.h" #include "http_log.h" +#ifdef WITH_UTIL_URI +#include "util_uri.h" +#endif /*WITH_UTIL_URI*/ static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r); static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r); @@ -836,7 +839,7 @@ hp = &hpbuf; } } - memcpy(reqhp, hp, sizeof(struct hostent)); + *reqhp = *hp; return NULL; } @@ -886,16 +889,9 @@ /* Parse IP addr manually, optionally allowing */ /* abbreviated net addresses like 192.168. */ -/* quads = sscanf(what, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], - &ip_addr[2], &ip_addr[3]); - commented out: use of strtok() allows arbitrary base, like in: - 139.25.113.10 == 0x8b.0x19.0x71.0x0a - (yes, inet_addr() can parse that, too!) - */ - /* Iterate over up to 4 (dotted) quads. */ for (quads = 0; quads < 4 && *addr != '\0'; ++quads) { - char *tmp; + const char *tmp; if (*addr == '/' && quads > 0) /* netmask starts here. */ break; @@ -923,7 +919,7 @@ This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i)); if (addr[0] == '/' && isdigit(addr[1])) { /* net mask follows: */ - char *tmp; + const char *tmp; ++addr; @@ -1048,8 +1044,6 @@ } } - /* Use net math to determine if a host lies in a subnet */ - /*return This->addr.s_addr == (r->connection->remote_addr.sin_addr.s_addr & This->mask.s_addr); */ return 0; } @@ -1064,7 +1058,8 @@ return 0; /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */ - for (i = 0; isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i); + for (i = 0; isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i) + continue; #if 0 if (addr[i] == ':') { @@ -1108,6 +1103,7 @@ /* Return TRUE if addr represents a host name */ int proxy_is_hostname(struct dirconn_entry *This, pool *p) { + struct hostent host; char *addr = This->name; int i; @@ -1125,9 +1121,15 @@ } #endif - if (addr[i] != '\0' || proxy_host2addr(addr, &This->hostlist) != NULL) + if (addr[i] != '\0' || proxy_host2addr(addr, &host) != NULL) return 0; +#ifdef WITH_UTIL_URI + This->hostentry = pduphostent (p, &host); +#else /*WITH_UTIL_URI*/ + This->hostlist = host; /*XXX: FIXME: This points to overwritten static storage!!! */ +#endif /*WITH_UTIL_URI*/ + /* Strip trailing dots */ for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i) addr[i] = '\0'; @@ -1148,7 +1150,7 @@ unsigned long *ip_list; /* Try to deal with multiple IP addr's for a host */ - for (ip_list = *This->hostlist.h_addr_list; *ip_list != 0UL; ++ip_list) + for (ip_list = *This->hostentry->h_addr_list; *ip_list != 0UL; ++ip_list) if (*ip_list == ? ? ? ? ? ? ? ? ? ? ? ? ?) return 1; #endif 1.44 +12 -0 apache-1.3/src/modules/standard/mod_log_config.c Index: mod_log_config.c =================================================================== RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_log_config.c,v retrieving revision 1.43 retrieving revision 1.44 diff -u -u -r1.43 -r1.44 --- mod_log_config.c 1998/01/26 19:50:21 1.43 +++ mod_log_config.c 1998/02/27 15:15:28 1.44 @@ -296,7 +296,19 @@ static char *log_request_line(request_rec *r, char *a) { +#ifdef WITH_UTIL_URI + /* NOTE: If the original request contained a password, we + * re-write the request line here to contain XXXXXX instead: + * (note the truncation before the protocol string for HTTP/0.9 requests) + * (note also that r->the_request contains the unmodified request) + */ + return (r->parsed_uri.has_password) ? pstrcat(r->pool, r->method, " ", + unparse_uri_components(r->pool, &r->parsed_uri, NULL, 0), + r->assbackwards ? NULL : " ", r->protocol, NULL) + : r->the_request; +#else /*WITH_UTIL_URI*/ return r->the_request; +#endif /*WITH_UTIL_URI*/ } static char *log_request_file(request_rec *r, char *a)