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)
  
  
  

Reply via email to