httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mar...@hyperreal.org
Subject cvs commit: apache-1.3/src/modules/standard mod_log_config.c
Date Fri, 27 Feb 1998 15:15:30 GMT
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[:password]@]host[:port] */
     user;       /* user name, as in http://user:passwd@host:port/ */
     password;   /* password, as in http://user:passwd@host: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[:password]@]host[:port] */
  +	user;       /* user name, as in http://user:passwd@host:port/ */
  +	password;   /* password, as in http://user:passwd@host: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://user@site: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[:password]@]host[:port] */
      char *user;			/* user name, as in http://user:passwd@host:port/ */
      char *password;		/* password, as in http://user:passwd@host: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[:password]@]host[: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 "user@host" */
  	    /* NOTE: using reverse search here because user:password might
  	     * contain a '@' as well (ftp login: user=ftp : password=user@host)
  	     */
  	    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)
  
  
  

Mime
View raw message