]> granicus.if.org Git - apache/commitdiff
This is the 1.3.x current proxy into 2.0 - first stage
authorChuck Murcko <chuck@apache.org>
Sat, 11 Nov 2000 11:07:03 +0000 (11:07 +0000)
committerChuck Murcko <chuck@apache.org>
Sat, 11 Nov 2000 11:07:03 +0000 (11:07 +0000)
PR:
Obtained from: Sam Magnuson
Submitted by:  Chuck Murcko
Reviewed by:

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86923 13f79535-47bb-0310-9956-ffa450edef68

modules/proxy/proxy_connect.c
modules/proxy/proxy_http.c
modules/proxy/proxy_util.c

index 00ae97ceb68f5b55a213e021599bd6f95f6fcff3..4de7ab5e836bd553ba9dd6638201988fa7f54f52 100644 (file)
 
 /* CONNECT method for Apache proxy */
 
-#include "apr_strings.h"
 #include "mod_proxy.h"
 #include "http_log.h"
 #include "http_main.h"
 
 #ifdef HAVE_BSTRING_H
-#include <bstring.h>        /* for IRIX, FD_SET calls bzero() */
+#include <bstring.h>           /* for IRIX, FD_SET calls bzero() */
 #endif
 
 /*  
@@ -104,15 +103,15 @@ allowed_port(proxy_server_conf *conf, int port)
     int *list = (int *) conf->allowed_connect_ports->elts;
 
     for(i = 0; i < conf->allowed_connect_ports->nelts; i++) {
-    if(port == list[i])
-        return 1;
+       if(port == list[i])
+           return 1;
     }
     return 0;
 }
 
 
 int ap_proxy_connect_handler(request_rec *r, ap_cache_el  *c, char *url,
-              const char *proxyhost, int proxyport)
+                         const char *proxyhost, int proxyport)
 {
     struct in_addr destaddr;
     const char *host;
@@ -123,7 +122,7 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el  *c, char *url,
     int nbytes, i;
 
     BUFF *sock_buff;
-    apr_socket_t *client_sock=NULL;
+    apr_socket_t *client_sock = NULL;
     apr_pollfd_t *pollfd;
     apr_int32_t pollcnt;
     apr_int16_t pollevent;
@@ -137,77 +136,80 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el  *c, char *url,
     host = url;
     p = strchr(url, ':');
     if (p == NULL)
-    port = DEFAULT_HTTPS_PORT;
+       port = DEFAULT_HTTPS_PORT;
     else {
-    port = atoi(p + 1);
-    *p = '\0';
+       port = atoi(p + 1);
+       *p = '\0';
     }
 
 /* check if ProxyBlock directive on this host */
-    destaddr.s_addr = apr_inet_addr(host);
+    destaddr.s_addr = ap_inet_addr(host);
     for (i = 0; i < conf->noproxies->nelts; i++) {
-    if ((npent[i].name != NULL && ap_strstr_c(host, npent[i].name) != NULL)
-        || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*')
-        return ap_proxyerror(r, HTTP_FORBIDDEN,
-                 "Connect to remote machine blocked");
+       if ((npent[i].name != NULL && ap_strstr_c(host, npent[i].name) != NULL)
+           || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*')
+           return ap_proxyerror(r, HTTP_FORBIDDEN,
+                "Connect to remote machine blocked");
     }
 
     /* Check if it is an allowed port */
     if (conf->allowed_connect_ports->nelts == 0) {
-    /* Default setting if not overridden by AllowCONNECT */
-    switch (port) {
-        case DEFAULT_HTTPS_PORT:
-        case DEFAULT_SNEWS_PORT:
-        break;
-        default:
-        return HTTP_FORBIDDEN;
-    }
+       /* Default setting if not overridden by AllowCONNECT */
+       switch (port) {
+           case DEFAULT_HTTPS_PORT:
+           case DEFAULT_SNEWS_PORT:
+               break;
+           default:
+               return HTTP_FORBIDDEN;
+       }
     } else if(!allowed_port(conf, port))
-    return HTTP_FORBIDDEN;
+       return HTTP_FORBIDDEN;
 
     if (proxyhost) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
-                     "CONNECT to remote proxy %s on port %d", proxyhost, proxyport);
+            "CONNECT to remote proxy %s on port %d", proxyhost, proxyport);
     }
     else {
         ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
-                     "CONNECT to %s on port %d", host, port);
+            "CONNECT to %s on port %d", host, port);
     }
 
     if ((apr_create_tcp_socket(&sock, r->pool)) != APR_SUCCESS) {
         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                      "proxy: error creating socket");
+            "proxy: error creating socket");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    if (ap_proxy_doconnect(sock, (char *)(proxyhost ? proxyhost : host), proxyport ? proxyport : port, r) == -1) {
+    if (ap_proxy_doconnect(sock, (char *)(proxyhost ? proxyhost : host),
+      proxyport ? proxyport : port, r) == -1) {
         apr_close_socket(sock);
         return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
-                             apr_pstrcat(r->pool, "Could not connect to remote machine:<br>",
-                                        strerror(errno), NULL));
+            apr_pstrcat(r->pool, "Could not connect to remote machine:<br>",
+            strerror(errno), NULL));
     }
 
     /* If we are connecting through a remote proxy, we need to pass
      * the CONNECT request on to it.
      */
     if (proxyport) {
-        /* FIXME: We should not be calling write() directly, but we currently
-         * have no alternative.  Error checking ignored.  Also, we force
-         * a HTTP/1.0 request to keep things simple.
-         */
+       /* FIXME: We should not be calling write() directly, but we currently
+        * have no alternative.  Error checking ignored.  Also, we force
+        * a HTTP/1.0 request to keep things simple.
+        */
         ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
-                     "Sending the CONNECT request to the remote proxy");
-        nbytes = apr_snprintf(buffer, sizeof(buffer), "CONNECT %s HTTP/1.0" CRLF, r->uri);
+             "Sending the CONNECT request to the remote proxy");
+        nbytes = apr_snprintf(buffer, sizeof(buffer),
+             "CONNECT %s HTTP/1.0" CRLF, r->uri);
         apr_send(sock, buffer, &nbytes);
-        nbytes = apr_snprintf(buffer, sizeof(buffer),"Proxy-agent: %s" CRLF CRLF, ap_get_server_version());
+        nbytes = apr_snprintf(buffer, sizeof(buffer),
+             "Proxy-agent: %s" CRLF CRLF, ap_get_server_version());
         apr_send(sock, buffer, &nbytes);
     }
     else {
         ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
-                     "Returning 200 OK Status");
-    ap_rvputs(r, "HTTP/1.0 200 Connection established" CRLF, NULL);
-    ap_rvputs(r, "Proxy-agent: ", ap_get_server_version(), CRLF CRLF, NULL);
-    ap_bflush(r->connection->client);
+            "Returning 200 OK Status");
+        ap_rvputs(r, "HTTP/1.0 200 Connection established" CRLF, NULL);
+        ap_rvputs(r, "Proxy-agent: ", ap_get_server_version(), CRLF CRLF, NULL);
+        ap_bflush(r->connection->client);
     }
 
     sock_buff = ap_bcreate(r->pool, B_RDWR);
@@ -215,7 +217,8 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el  *c, char *url,
 
     if(apr_setup_poll(&pollfd, 2, r->pool) != APR_SUCCESS)
     {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "proxy: error apr_setup_poll()");
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+            "proxy: error apr_setup_poll()");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
@@ -226,20 +229,21 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el  *c, char *url,
    just see if a recv gives us anything and do the same to sock (server) side, I'll leave this as TBD so
    one can decide the best path to take
 */
-    if(apr_put_os_sock(&client_sock, (apr_os_sock_t *)get_socket(r->connection->client),
+    if(apr_put_os_sock(&client_sock,
+        (apr_os_sock_t *)get_socket(r->connection->client),
                       r->pool) != APR_SUCCESS)
     {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "proxy: error creating client apr_socket_t");
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+            "proxy: error creating client apr_socket_t");
         return HTTP_INTERNAL_SERVER_ERROR;
     }
     apr_add_poll_socket(pollfd, client_sock, APR_POLLIN);
 #endif
-    
-    
+
     /* Add the server side to the poll */
     apr_add_poll_socket(pollfd, sock, APR_POLLIN);
-    
-    while (1) {            /* Infinite loop until error (one side closes the connection) */
+
+    while (1) { /* Infinite loop until error (one side closes the connection) */
         ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "Going to sleep (poll)");
         if(apr_poll(pollfd, &pollcnt, -1) != APR_SUCCESS)
         {
@@ -262,8 +266,7 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el  *c, char *url,
                         o += i;
                         nbytes -= i;
                     }
-                    ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
-                                 "Wrote %d bytes to client", nbytes);
+                    ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,                                 "Wrote %d bytes to client", nbytes);
                 }
                 else
                     break;
@@ -273,7 +276,8 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el  *c, char *url,
             if (pollevent & APR_POLLIN) {
                 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
                              "client was set");
-                if(ap_bread(r->connection->client, buffer, HUGE_STRING_LEN, &nbytes) == APR_SUCCESS) {
+                if(ap_bread(r->connection->client, buffer, HUGE_STRING_LEN,
+                  &nbytes) == APR_SUCCESS) {
                     int o = 0;
                     while(nbytes)
                     {
@@ -281,8 +285,8 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el  *c, char *url,
                         o += i;
                         nbytes -= i;
                     }
-                    ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
-                                 "Wrote %d bytes to server", nbytes);
+                    ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
+                        NULL, "Wrote %d bytes to server", nbytes);
                 }
                 else
                     break;
@@ -291,7 +295,7 @@ int ap_proxy_connect_handler(request_rec *r, ap_cache_el  *c, char *url,
         else
             break;
     }
-    
+
     apr_close_socket(sock);
 
     return OK;
index ff5e28634a2716cc69a52e53caf785dd646d700b..b26a2ed13193d794e4cfb836e8b91231e40ec1a9 100644 (file)
@@ -58,7 +58,6 @@
 
 /* HTTP routines for Apache proxy */
 
-#include "apr_strings.h"
 #include "mod_proxy.h"
 #include "http_log.h"
 #include "http_main.h"
@@ -83,7 +82,7 @@ int ap_proxy_http_canon(request_rec *r, char *url, const char *scheme, int def_p
     port = def_port;
     err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
     if (err)
-    return HTTP_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_
@@ -91,25 +90,25 @@ int ap_proxy_http_canon(request_rec *r, char *url, const char *scheme, int def_p
  * == r->unparsed_uri, and no others have that property.
  */
     if (r->uri == r->unparsed_uri) {
-    search = strchr(url, '?');
-    if (search != NULL)
-        *(search++) = '\0';
+       search = strchr(url, '?');
+       if (search != NULL)
+           *(search++) = '\0';
     }
     else
-    search = r->args;
+       search = r->args;
 
 /* process path */
     path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, r->proxyreq);
     if (path == NULL)
-    return HTTP_BAD_REQUEST;
+       return HTTP_BAD_REQUEST;
 
     if (port != def_port)
-    apr_snprintf(sport, sizeof(sport), ":%d", port);
+       apr_snprintf(sport, sizeof(sport), ":%d", port);
     else
-    sport[0] = '\0';
+       sport[0] = '\0';
 
     r->filename = apr_pstrcat(r->pool, "proxy:", scheme, "://", host, sport, "/",
-           path, (search) ? "?" : "", (search) ? search : "", NULL);
+                  path, (search) ? "?" : "", (search) ? search : "", NULL);
     return OK;
 }
  
@@ -135,7 +134,7 @@ static const char *proxy_location_reverse_map(request_rec *r, const char *url)
     return url;
 }
 
-/* Clear all connection-based headers from the incoming headers apr_table_t */
+/* Clear all connection-based headers from the incoming headers table */
 static void clear_connection(apr_pool_t *p, apr_table_t *headers)
 {
     const char *name;
@@ -143,17 +142,17 @@ static void clear_connection(apr_pool_t *p, apr_table_t *headers)
 
     apr_table_unset(headers, "Proxy-Connection");
     if (!next)
-        return;
+               return;
 
     while (*next) {
-        name = next;
-        while (*next && !apr_isspace(*next) && (*next != ','))
-            ++next;
-        while (*next && (apr_isspace(*next) || (*next == ','))) {
-            *next = '\0';
-            ++next;
-        }
-        apr_table_unset(headers, name);
+       name = next;
+       while (*next && !apr_isspace(*next) && (*next != ','))
+           ++next;
+       while (*next && (apr_isspace(*next) || (*next == ','))) {
+           *next = '\0';
+           ++next;
+       }
+       apr_table_unset(headers, name);
     }
     apr_table_unset(headers, "Connection");
 }
@@ -167,34 +166,34 @@ static void clear_connection(apr_pool_t *p, apr_table_t *headers)
  * we return DECLINED so that we can try another proxy. (Or the direct
  * route.)
  */
-int ap_proxy_http_handler(request_rec *r, ap_cache_el  *c, char *url,
-               const char *proxyhost, int proxyport)
+int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
+                      const char *proxyhost, int proxyport)
 {
     const char *strp;
     char *strp2;
     char *desthost;
     apr_socket_t *sock;
-    int i, len, backasswards, content_length=-1;
+    int i, len, backasswards, content_length = -1;
     apr_array_header_t *reqhdrs_arr;
-    apr_table_t *resp_hdrs=NULL;
+    apr_table_t *resp_hdrs = NULL;
     apr_table_entry_t *reqhdrs;
     struct sockaddr_in server;
     struct in_addr destaddr;
     BUFF *f;
-    apr_file_t *cachefp=NULL;
     char buffer[HUGE_STRING_LEN];
     char portstr[32];
     apr_pool_t *p = r->pool;
     const long int zero = 0L;
     int destport = 0;
-    apr_ssize_t cntr;
     char *destportstr = NULL;
     const char *urlptr = NULL;
     char *datestr, *clen;
+    apr_ssize_t cntr;
+    apr_file_t *cachefp = NULL;
 
     void *sconf = r->server->module_config;
     proxy_server_conf *conf =
-        (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
+    (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
     struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
     struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts;
     int nocache = 0;
@@ -206,38 +205,40 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el  *c, char *url,
 
     urlptr = strstr(url, "://");
     if (urlptr == NULL)
-        return HTTP_BAD_REQUEST;
+       return HTTP_BAD_REQUEST;
     urlptr += 3;
     destport = DEFAULT_HTTP_PORT;
     strp = ap_strchr_c(urlptr, '/');
     if (strp == NULL) {
-        desthost = apr_pstrdup(p, urlptr);
-        urlptr = "/";
+       desthost = apr_pstrdup(p, urlptr);
+       urlptr = "/";
     }
     else {
-        char *q = apr_palloc(p, strp - urlptr + 1);
-        memcpy(q, urlptr, strp - urlptr);
-        q[strp - urlptr] = '\0';
-        urlptr = strp;
-        desthost = q;
+       char *q = apr_palloc(p, strp - urlptr + 1);
+       memcpy(q, urlptr, strp - urlptr);
+       q[strp - urlptr] = '\0';
+       urlptr = strp;
+       desthost = q;
     }
 
     strp2 = ap_strchr(desthost, ':');
     if (strp2 != NULL) {
-        *(strp2++) = '\0';
-        if (apr_isdigit(*strp2)) {
-            destport = atoi(strp2);
-            destportstr = strp2;
-        }
+       *(strp2++) = '\0';
+       if (apr_isdigit(*strp2)) {
+           destport = atoi(strp2);
+           destportstr = strp2;
+       }
     }
 
 /* check if ProxyBlock directive on this host */
     destaddr.s_addr = apr_inet_addr(desthost);
     for (i = 0; i < conf->noproxies->nelts; i++) {
-        if ((npent[i].name != NULL && ap_strstr_c(desthost, npent[i].name) != NULL)
-            || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*')
-            return ap_proxyerror(r, HTTP_FORBIDDEN,
-                                 "Connect to remote machine blocked");
+       if ((npent[i].name != NULL
+            && ap_strstr_c(desthost, npent[i].name) != NULL)
+           || destaddr.s_addr == npent[i].addr.s_addr
+            || npent[i].name[0] == '*')
+           return ap_proxyerror(r, HTTP_FORBIDDEN,
+                                "Connect to remote machine blocked");
     }
 
     if ((apr_create_tcp_socket(&sock, r->pool)) != APR_SUCCESS) {
@@ -246,11 +247,14 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el  *c, char *url,
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    if (conf->recv_buffer_size > 0 && apr_setsocketopt(sock, APR_SO_RCVBUF,conf->recv_buffer_size)) {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                      "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
+#if !defined(TPF) && !defined(BEOS)
+    if (conf->recv_buffer_size > 0 && apr_setsocketopt(sock, APR_SO_RCVBUF,
+       conf->recv_buffer_size)) {
+           ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
     }
-    
+#endif
+
     if (proxyhost != NULL) {
         i = ap_proxy_doconnect(sock, (char *)proxyhost, proxyport, r);
     }
@@ -259,147 +263,148 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el  *c, char *url,
     }
 
     if (i == -1) {
-        if (proxyhost != NULL)
-            return DECLINED;    /* try again another way */
-        else
-            return ap_proxyerror(r, HTTP_BAD_GATEWAY,
-                apr_pstrcat(r->pool, "Could not connect to remote machine: ",
-                    strerror(errno), NULL));
+       if (proxyhost != NULL)
+           return DECLINED;    /* try again another way */
+       else
+           return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(r->pool,
+                               "Could not connect to remote machine: ",
+                               strerror(errno), NULL));
     }
 
-    clear_connection(r->pool, r->headers_in);    /* Strip connection-based headers */
+    clear_connection(r->pool, r->headers_in);  /* Strip connection-based headers */
 
     f = ap_bcreate(p, B_RDWR);
     ap_bpush_socket(f, sock);
 
     ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.0" CRLF,
-              NULL);
+          NULL);
     if (destportstr != NULL && destport != DEFAULT_HTTP_PORT)
-        ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
+       ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
     else
-        ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
+       ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
 
     if (conf->viaopt == via_block) {
-        /* Block all outgoing Via: headers */
-        apr_table_unset(r->headers_in, "Via");
+       /* Block all outgoing Via: headers */
+       apr_table_unset(r->headers_in, "Via");
     } else if (conf->viaopt != via_off) {
-        /* Create a "Via:" request header entry and merge it */
-        i = ap_get_server_port(r);
-        if (ap_is_default_port(i,r)) {
-            strcpy(portstr,"");
-        } else {
-            apr_snprintf(portstr, sizeof portstr, ":%d", i);
-        }
-        /* Generate outgoing Via: header with/without server comment: */
-        apr_table_mergen(r->headers_in, "Via",
-                        (conf->viaopt == via_full)
-                        ? apr_psprintf(p, "%d.%d %s%s (%s)",
-                                      HTTP_VERSION_MAJOR(r->proto_num),
-                                      HTTP_VERSION_MINOR(r->proto_num),
-                                      ap_get_server_name(r), portstr,
-                                      AP_SERVER_BASEVERSION)
-                        : apr_psprintf(p, "%d.%d %s%s",
-                                      HTTP_VERSION_MAJOR(r->proto_num),
-                                      HTTP_VERSION_MINOR(r->proto_num),
-                                      ap_get_server_name(r), portstr)
-            );
+       /* Create a "Via:" request header entry and merge it */
+       i = ap_get_server_port(r);
+       if (ap_is_default_port(i,r)) {
+           strcpy(portstr,"");
+       } else {
+           apr_snprintf(portstr, sizeof portstr, ":%d", i);
+       }
+       /* Generate outgoing Via: header with/without server comment: */
+       ap_table_mergen(r->headers_in, "Via",
+                   (conf->viaopt == via_full)
+                       ? apr_psprintf(p, "%d.%d %s%s (%s)",
+                               HTTP_VERSION_MAJOR(r->proto_num),
+                               HTTP_VERSION_MINOR(r->proto_num),
+                               ap_get_server_name(r), portstr,
+                               AP_SERVER_BASEVERSION)
+                       : apr_psprintf(p, "%d.%d %s%s",
+                               HTTP_VERSION_MAJOR(r->proto_num),
+                               HTTP_VERSION_MINOR(r->proto_num),
+                               ap_get_server_name(r), portstr)
+                       );
     }
 
     reqhdrs_arr = apr_table_elts(r->headers_in);
     reqhdrs = (apr_table_entry_t *) reqhdrs_arr->elts;
     for (i = 0; i < reqhdrs_arr->nelts; i++) {
-        if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL
-            /* Clear out headers not to send */
-            || !strcasecmp(reqhdrs[i].key, "Host")    /* Already sent */
-            /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be 
-             * suppressed if THIS server requested the authentication,
-             * not when a frontend proxy requested it!
-             */
-            || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization"))
-            continue;
-        ap_bvputs(f, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL);
+       if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL
+       /* Clear out headers not to send */
+           || !strcasecmp(reqhdrs[i].key, "Host")      /* Already sent */
+           /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be 
+            * suppressed if THIS server requested the authentication,
+            * not when a frontend proxy requested it!
+            */
+           || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization"))
+           continue;
+       ap_bvputs(f, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL);
     }
 
     ap_bputs(CRLF, f);
 /* send the request data, if any. */
 
     if (ap_should_client_block(r)) {
-        while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0)
-            ap_bwrite(f, buffer, i, &cntr);
+       while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0)
+           ap_bwrite(f, buffer, i, &cntr);
     }
     ap_bflush(f);
 
     len = ap_bgets(buffer, sizeof buffer - 1, f);
     if (len == -1) {
-        ap_bclose(f);
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                      "ap_bgets() - proxy receive - Error reading from remote server %s (length %d)",
-                      proxyhost ? proxyhost : desthost, len);
-        return ap_proxyerror(r, HTTP_BAD_GATEWAY,
-                             "Error reading from remote server");
+       ap_bclose(f);
+       ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+            "ap_bgets() - proxy receive - Error reading from remote server %s (length %d)",
+            proxyhost ? proxyhost : desthost, len);
+       return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+                            "Error reading from remote server");
     } else if (len == 0) {
-        ap_bclose(f);
-        return ap_proxyerror(r, HTTP_BAD_GATEWAY,
-                             "Document contains no data");
+       ap_bclose(f);
+       return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+                            "Document contains no data");
     }
 
 /* Is it an HTTP/1 response?  This is buggy if we ever see an HTTP/1.10 */
     if (ap_checkmask(buffer, "HTTP/#.# ###*")) {
-        int major, minor;
-        if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) {
-            major = 1;
-            minor = 0;
-        }
+       int major, minor;
+       if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) {
+           major = 1;
+           minor = 0;
+       }
 
 /* If not an HTTP/1 message or if the status line was > 8192 bytes */
-        if (buffer[5] != '1' || buffer[len - 1] != '\n') {
-            ap_bclose(f);
-            return HTTP_BAD_GATEWAY;
-        }
-        backasswards = 0;
-        buffer[--len] = '\0';
-
-        buffer[12] = '\0';
-        r->status = atoi(&buffer[9]);
-        buffer[12] = ' ';
-        r->status_line = apr_pstrdup(p, &buffer[9]);
+       if (buffer[5] != '1' || buffer[len - 1] != '\n') {
+           ap_bclose(f);
+           return HTTP_BAD_GATEWAY;
+       }
+       backasswards = 0;
+       buffer[--len] = '\0';
+
+       buffer[12] = '\0';
+       r->status = atoi(&buffer[9]);
+       buffer[12] = ' ';
+       r->status_line = apr_pstrdup(p, &buffer[9]);
 
 /* read the headers. */
 /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */
 /* Also, take care with headers with multiple occurences. */
-        resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, f);
-        if (resp_hdrs == NULL) {
-            ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
-                         "proxy: Bad HTTP/%d.%d header returned by %s (%s)",
-                         major, minor, r->uri, r->method);
-            nocache = 1;    /* do not cache this broken file */
-        }
+
+       resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, f);
+       if (resp_hdrs == NULL) {
+           ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
+                "proxy: Bad HTTP/%d.%d header returned by %s (%s)",
+                major, minor, r->uri, r->method);
+           nocache = 1;    /* do not cache this broken file */
+       }
         else
         {
             clear_connection(p, resp_hdrs);    /* Strip Connection hdrs */
             ap_cache_el_header_merge(c, resp_hdrs);
         }
-            
-        if (conf->viaopt != via_off && conf->viaopt != via_block) {
-            /* Create a "Via:" response header entry and merge it */
-            i = ap_get_server_port(r);
-            if (ap_is_default_port(i,r)) {
-                strcpy(portstr,"");
-            } else {
-                apr_snprintf(portstr, sizeof portstr, ":%d", i);
-            }
+
+       if (conf->viaopt != via_off && conf->viaopt != via_block) {
+           /* Create a "Via:" response header entry and merge it */
+           i = ap_get_server_port(r);
+           if (ap_is_default_port(i,r)) {
+               strcpy(portstr,"");
+           } else {
+               apr_snprintf(portstr, sizeof portstr, ":%d", i);
+           }
             ap_cache_el_header_add(c, "Via", (conf->viaopt == via_full)
-                         ? apr_psprintf(p, "%d.%d %s%s (%s)", major, minor,
-                                       ap_get_server_name(r), portstr, AP_SERVER_BASEVERSION)
-                         : apr_psprintf(p, "%d.%d %s%s", major, minor, ap_get_server_name(r), portstr)
-                );
-        }
+                ? apr_psprintf(p, "%d.%d %s%s (%s)", major, minor,
+                ap_get_server_name(r), portstr, AP_SERVER_BASEVERSION)
+                : apr_psprintf(p, "%d.%d %s%s", major, minor,
+                ap_get_server_name(r), portstr));
+       }
     }
     else {
 /* an http/0.9 response */
-        backasswards = 1;
-        r->status = 200;
-        r->status_line = "200 OK";
+       backasswards = 1;
+       r->status = 200;
+       r->status_line = "200 OK";
     }
 
 /*
@@ -423,44 +428,44 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el  *c, char *url,
         content_length = atoi(clen ? clen : "-1");
 
     for (i = 0; i < conf->nocaches->nelts; i++) {
-        if ((ncent[i].name != NULL && ap_strstr_c(desthost, ncent[i].name) != NULL)
-            || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*')
-            nocache = 1;
+       if ((ncent[i].name != NULL && ap_strstr_c(desthost, ncent[i].name) != NULL)
+         || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*')
+           nocache = 1;
     }
 
     if(nocache || !ap_proxy_cache_should_cache(r, resp_hdrs, !backasswards))
         ap_proxy_cache_error(&c);
     else
         ap_cache_el_data(c, &cachefp);
-    
+
 /* write status line */
     if (!r->assbackwards)
-        ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL);
-    if (cachefp &&    apr_puts(apr_pstrcat(r->pool, "HTTP/1.0 ", r->status_line, CRLF, NULL), cachefp) != APR_SUCCESS) {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                      "proxy: error writing status line to cache");
-        ap_proxy_cache_error(&c);
-        cachefp = NULL;
+       ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL);
+    if (cachefp && apr_puts(apr_pstrcat(r->pool, "HTTP/1.0 ",
+        r->status_line, CRLF, NULL), cachefp) != APR_SUCCESS) {
+           ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+               "proxy: error writing status line to cache");
+           ap_proxy_cache_error(&c);
+            cachefp = NULL;
     }
 
 /* send headers */
     ap_cache_el_header_walk(c, ap_proxy_send_hdr_line, r, NULL);
 
     if (!r->assbackwards)
-        ap_rputs(CRLF, r);
+       ap_rputs(CRLF, r);
 
     ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
     r->sent_bodyct = 1;
-/* Is it an HTTP/0.9 respose? If so, send the extra data */
+/* Is it an HTTP/0.9 response? If so, send the extra data */
     if (backasswards) {
-        ap_bwrite(r->connection->client, buffer, len, &cntr);
+       ap_bwrite(r->connection->client, buffer, len, &cntr);
         cntr = len;
         if (cachefp && apr_write(cachefp, buffer, &cntr) != APR_SUCCESS) {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                          "proxy: error writing extra data to cache %ld",
-                          (long)cachefp);
-            ap_proxy_cache_error(&c);
-        }
+           ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+               "proxy: error writing extra data to cache");
+           ap_proxy_cache_error(&c);
+       }
     }
 
 #ifdef CHARSET_EBCDIC
@@ -471,14 +476,14 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el  *c, char *url,
     ap_bsetflag(r->connection->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);
 #endif
 
-    /* send body */
-    /* if header only, then cache will be NULL */
-    /* HTTP/1.0 tells us to read to EOF, rather than content-length bytes */
+       /* send body */
+       /* if header only, then cache will be NULL */
+       /* HTTP/1.0 tells us to read to EOF, rather than content-length bytes */
     if (!r->header_only) {
-        proxy_completion pc;
-        pc.content_length = content_length;
-        pc.cache_completion = conf->cache_completion;
-        ap_proxy_send_fb(&pc, f, r, c);
+               proxy_completion pc;
+               pc.content_length = content_length;
+               pc.cache_completion = conf->cache_completion;
+               ap_proxy_send_fb(&pc, f, r, c);
     }
 
     ap_bclose(f);
index 5b6a18331ff07b54570e7854b856a042567a6a92..4b6b2139b52b9558a08b3ac719ac9897f610fb08 100644 (file)
  */
 
 /* Utility routines for Apache proxy */
-#include "apr_strings.h"
 #include "mod_proxy.h"
 #include "http_main.h"
-#include "apr_md5.h"
 #include "http_log.h"
 #include "util_uri.h"
-#include "util_date.h"    /* get ap_checkmask() decl. */
-
-#include <pthread.h>
+#include "util_date.h" /* get ap_checkmask() decl. */
+#include "apr_md5.h"
 
 static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
 static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
 static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r);
 static int proxy_match_word(struct dirconn_entry *This, request_rec *r);
-
+static struct per_thread_data *get_per_thread_data(void);
 /* already called in the knowledge that the characters are hex digits */
 int ap_proxy_hex2c(const char *x)
 {
@@ -80,20 +77,20 @@ int ap_proxy_hex2c(const char *x)
 #ifndef CHARSET_EBCDIC
     ch = x[0];
     if (apr_isdigit(ch))
-    i = ch - '0';
+       i = ch - '0';
     else if (apr_isupper(ch))
-    i = ch - ('A' - 10);
+       i = ch - ('A' - 10);
     else
-    i = ch - ('a' - 10);
+       i = ch - ('a' - 10);
     i <<= 4;
 
     ch = x[1];
     if (apr_isdigit(ch))
-    i += ch - '0';
+       i += ch - '0';
     else if (apr_isupper(ch))
-    i += ch - ('A' - 10);
+       i += ch - ('A' - 10);
     else
-    i += ch - ('a' - 10);
+       i += ch - ('a' - 10);
     return i;
 #else /*CHARSET_EBCDIC*/
     return (1 == sscanf(x, "%2x", &i)) ? os_toebcdic[i&0xFF] : 0;
@@ -108,15 +105,15 @@ void ap_proxy_c2hex(int ch, char *x)
     x[0] = '%';
     i = (ch & 0xF0) >> 4;
     if (i >= 10)
-    x[1] = ('A' - 10) + i;
+       x[1] = ('A' - 10) + i;
     else
-    x[1] = '0' + i;
+       x[1] = '0' + i;
 
     i = ch & 0x0F;
     if (i >= 10)
-    x[2] = ('A' - 10) + i;
+       x[2] = ('A' - 10) + i;
     else
-    x[2] = '0' + i;
+       x[2] = '0' + i;
 #else /*CHARSET_EBCDIC*/
     static const char ntoa[] = { "0123456789ABCDEF" };
     ch &= 0xFF;
@@ -137,13 +134,13 @@ void ap_proxy_c2hex(int ch, char *x)
  * and encodes those which must be encoded, and does not touch
  * those which must not be touched.
  */
-char *
-     ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t, int isenc)
+char *ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
+       int isenc)
 {
     int i, j, ch;
     char *y;
-    char *allowed;    /* characters which should not be encoded */
-    char *reserved;    /* characters which much not be en/de-coded */
+    char *allowed;     /* characters which should not be encoded */
+    char *reserved;    /* characters which much not be en/de-coded */
 
 /* N.B. in addition to :@&=, this allows ';' in an http path
  * and '?' in an ftp path -- this may be revised
@@ -153,51 +150,51 @@ char *
  * it only permits ; / ? : @ = & as reserved chars.)
  */
     if (t == enc_path)
-    allowed = "$-_.+!*'(),;:@&=";
+       allowed = "$-_.+!*'(),;:@&=";
     else if (t == enc_search)
-    allowed = "$-_.!*'(),;:@&=";
+       allowed = "$-_.!*'(),;:@&=";
     else if (t == enc_user)
-    allowed = "$-_.+!*'(),;@&=";
+       allowed = "$-_.+!*'(),;@&=";
     else if (t == enc_fpath)
-    allowed = "$-_.+!*'(),?:@&=";
-    else            /* if (t == enc_parm) */
-    allowed = "$-_.+!*'(),?/:@&=";
+       allowed = "$-_.+!*'(),?:@&=";
+    else                       /* if (t == enc_parm) */
+       allowed = "$-_.+!*'(),?/:@&=";
 
     if (t == enc_path)
-    reserved = "/";
+       reserved = "/";
     else if (t == enc_search)
-    reserved = "+";
+       reserved = "+";
     else
-    reserved = "";
+       reserved = "";
 
     y = apr_palloc(p, 3 * len + 1);
 
     for (i = 0, j = 0; i < len; i++, j++) {
 /* always handle '/' first */
-    ch = x[i];
-    if (strchr(reserved, ch)) {
-        y[j] = ch;
-        continue;
-    }
+       ch = x[i];
+       if (strchr(reserved, ch)) {
+           y[j] = ch;
+           continue;
+       }
 /* decode it if not already done */
-    if (isenc && ch == '%') {
-        if (!apr_isxdigit(x[i + 1]) || !apr_isxdigit(x[i + 2]))
-        return NULL;
-        ch = ap_proxy_hex2c(&x[i + 1]);
-        i += 2;
-        if (ch != 0 && strchr(reserved, ch)) {    /* keep it encoded */
-        ap_proxy_c2hex(ch, &y[j]);
-        j += 2;
-        continue;
-        }
-    }
+       if (isenc && ch == '%') {
+           if (!ap_isxdigit(x[i + 1]) || !ap_isxdigit(x[i + 2]))
+               return NULL;
+           ch = ap_proxy_hex2c(&x[i + 1]);
+           i += 2;
+           if (ch != 0 && strchr(reserved, ch)) {      /* keep it encoded */
+               ap_proxy_c2hex(ch, &y[j]);
+               j += 2;
+               continue;
+           }
+       }
 /* recode it, if necessary */
-    if (!apr_isalnum(ch) && !strchr(allowed, ch)) {
-        ap_proxy_c2hex(ch, &y[j]);
-        j += 2;
-    }
-    else
-        y[j] = ch;
+       if (!apr_isalnum(ch) && !strchr(allowed, ch)) {
+           ap_proxy_c2hex(ch, &y[j]);
+           j += 2;
+       }
+       else
+           y[j] = ch;
     }
     y[j] = '\0';
     return y;
@@ -215,81 +212,81 @@ char *
  */
 char *
      ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
-            char **passwordp, char **hostp, int *port)
+                       char **passwordp, char **hostp, int *port)
 {
     int i;
     char *strp, *host, *url = *urlp;
     char *user = NULL, *password = NULL;
 
     if (url[0] != '/' || url[1] != '/')
-    return "Malformed URL";
+       return "Malformed URL";
     host = url + 2;
     url = strchr(host, '/');
     if (url == NULL)
-    url = "";
+       url = "";
     else
-    *(url++) = '\0';    /* skip seperating '/' */
+       *(url++) = '\0';        /* skip seperating '/' */
 
     /* find _last_ '@' since it might occur in user/password part */
     strp = strrchr(host, '@');
 
     if (strp != NULL) {
-    *strp = '\0';
-    user = host;
-    host = strp + 1;
+       *strp = '\0';
+       user = host;
+       host = strp + 1;
 
 /* find password */
-    strp = strchr(user, ':');
-    if (strp != NULL) {
-        *strp = '\0';
-        password = ap_proxy_canonenc(p, strp + 1, strlen(strp + 1), enc_user, 1);
-        if (password == NULL)
-        return "Bad %-escape in URL (password)";
-    }
-
-    user = ap_proxy_canonenc(p, user, strlen(user), enc_user, 1);
-    if (user == NULL)
-        return "Bad %-escape in URL (username)";
+       strp = strchr(user, ':');
+       if (strp != NULL) {
+           *strp = '\0';
+           password = ap_proxy_canonenc(p, strp + 1, strlen(strp + 1), enc_user, 1);
+           if (password == NULL)
+               return "Bad %-escape in URL (password)";
+       }
+
+       user = ap_proxy_canonenc(p, user, strlen(user), enc_user, 1);
+       if (user == NULL)
+           return "Bad %-escape in URL (username)";
     }
     if (userp != NULL) {
-    *userp = user;
+       *userp = user;
     }
     if (passwordp != NULL) {
-    *passwordp = password;
+       *passwordp = password;
     }
 
     strp = strrchr(host, ':');
     if (strp != NULL) {
-    *(strp++) = '\0';
-
-    for (i = 0; strp[i] != '\0'; i++)
-        if (!apr_isdigit(strp[i]))
-        break;
-
-    /* if (i == 0) the no port was given; keep default */
-    if (strp[i] != '\0') {
-        return "Bad port number in URL";
-    } else if (i > 0) {
-        *port = atoi(strp);
-        if (*port > 65535)
-        return "Port number in URL > 65535";
-    }
+       *(strp++) = '\0';
+
+       for (i = 0; strp[i] != '\0'; i++)
+           if (!apr_isdigit(strp[i]))
+               break;
+
+       /* if (i == 0) the no port was given; keep default */
+       if (strp[i] != '\0') {
+           return "Bad port number in URL";
+       } else if (i > 0) {
+           *port = atoi(strp);
+           if (*port > 65535)
+               return "Port number in URL > 65535";
+       }
     }
-    ap_str_tolower(host);        /* DNS names are case insensitive */
+    ap_str_tolower(host);              /* DNS names are case-insensitive */
     if (*host == '\0')
-    return "Missing host in URL";
+       return "Missing host in URL";
 /* check hostname syntax */
     for (i = 0; host[i] != '\0'; i++)
-    if (!apr_isdigit(host[i]) && host[i] != '.')
-        break;
+       if (!apr_isdigit(host[i]) && host[i] != '.')
+           break;
     /* must be an IP address */
-#ifdef WIN32
+#if defined(WIN32) || defined(NETWARE) || defined(TPF) || defined(BEOS)
     if (host[i] == '\0' && (inet_addr(host) == -1))
 #else
-    if (host[i] == '\0' && (apr_inet_addr(host) == -1 || inet_network(host) == -1))
+    if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1))
 #endif
     {
-    return "Bad IP address in URL";
+       return "Bad IP address in URL";
     }
 
 /*    if (strchr(host,'.') == NULL && domain != NULL)
@@ -321,49 +318,49 @@ const char *
     q = strchr(x, ',');
     /* check for RFC 850 date */
     if (q != NULL && q - x > 3 && q[1] == ' ') {
-    *q = '\0';
-    for (wk = 0; wk < 7; wk++)
-        if (strcmp(x, lwday[wk]) == 0)
-        break;
-    *q = ',';
-    if (wk == 7)
-        return x;        /* not a valid date */
-    if (q[4] != '-' || q[8] != '-' || q[11] != ' ' || q[14] != ':' ||
-        q[17] != ':' || strcmp(&q[20], " GMT") != 0)
-        return x;
-    if (sscanf(q + 2, "%u-%3s-%u %u:%u:%u %3s", &mday, month, &year,
-           &hour, &min, &sec, zone) != 7)
-        return x;
-    if (year < 70)
-        year += 2000;
-    else
-        year += 1900;
+       *q = '\0';
+       for (wk = 0; wk < 7; wk++)
+           if (strcmp(x, lwday[wk]) == 0)
+               break;
+       *q = ',';
+       if (wk == 7)
+           return x;           /* not a valid date */
+       if (q[4] != '-' || q[8] != '-' || q[11] != ' ' || q[14] != ':' ||
+           q[17] != ':' || strcmp(&q[20], " GMT") != 0)
+           return x;
+       if (sscanf(q + 2, "%u-%3s-%u %u:%u:%u %3s", &mday, month, &year,
+                  &hour, &min, &sec, zone) != 7)
+           return x;
+       if (year < 70)
+           year += 2000;
+       else
+           year += 1900;
     }
     else {
 /* check for acstime() date */
-    if (x[3] != ' ' || x[7] != ' ' || x[10] != ' ' || x[13] != ':' ||
-        x[16] != ':' || x[19] != ' ' || x[24] != '\0')
-        return x;
-    if (sscanf(x, "%3s %3s %u %u:%u:%u %u", week, month, &mday, &hour,
-           &min, &sec, &year) != 7)
-        return x;
-    for (wk = 0; wk < 7; wk++)
-        if (strcmp(week, apr_day_snames[wk]) == 0)
-        break;
-    if (wk == 7)
-        return x;
+       if (x[3] != ' ' || x[7] != ' ' || x[10] != ' ' || x[13] != ':' ||
+           x[16] != ':' || x[19] != ' ' || x[24] != '\0')
+           return x;
+       if (sscanf(x, "%3s %3s %u %u:%u:%u %u", week, month, &mday, &hour,
+                  &min, &sec, &year) != 7)
+           return x;
+       for (wk = 0; wk < 7; wk++)
+           if (strcmp(week, ap_day_snames[wk]) == 0)
+               break;
+       if (wk == 7)
+           return x;
     }
 
 /* check date */
     for (mon = 0; mon < 12; mon++)
-    if (strcmp(month, apr_month_snames[mon]) == 0)
-        break;
+       if (strcmp(month, ap_month_snames[mon]) == 0)
+           break;
     if (mon == 12)
-    return x;
+       return x;
 
     q = apr_palloc(p, 30);
-    apr_snprintf(q, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", apr_day_snames[wk], mday,
-        apr_month_snames[mon], year, hour, min, sec);
+    apr_snprintf(q, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", ap_day_snames[wk],
+       mday, ap_month_snames[mon], year, hour, min, sec);
     return q;
 }
 
@@ -439,61 +436,61 @@ apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF
     char *value, *end;
     char field[MAX_STRING_LEN];
 
-    resp_hdrs = apr_make_table(r->pool, 20);
+    resp_hdrs = ap_make_table(r->pool, 20);
 
     /*
      * Read header lines until we get the empty separator line, a read error,
      * the connection closes (EOF), or we timeout.
      */
     while ((len = proxy_getline(buffer, size, f, 1)) > 0) {
-    
-    if (!(value = strchr(buffer, ':'))) {     /* Find the colon separator */
-
-        /* Buggy MS IIS servers sometimes return invalid headers
-         * (an extra "HTTP/1.0 200, OK" line sprinkled in between
-         * the usual MIME headers). Try to deal with it in a sensible
-         * way, but log the fact.
-         * XXX: The mask check is buggy if we ever see an HTTP/1.10 */
-
-        if (!ap_checkmask(buffer, "HTTP/#.# ###*")) {
-        /* Nope, it wasn't even an extra HTTP header. Give up. */
-        return NULL;
-        }
-
-        ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
-             "proxy: Ignoring duplicate HTTP header "
-             "returned by %s (%s)", r->uri, r->method);
-        continue;
-    }
+       
+       if (!(value = strchr(buffer, ':'))) {     /* Find the colon separator */
+
+           /* Buggy MS IIS servers sometimes return invalid headers
+            * (an extra "HTTP/1.0 200, OK" line sprinkled in between
+            * the usual MIME headers). Try to deal with it in a sensible
+            * way, but log the fact.
+            * XXX: The mask check is buggy if we ever see an HTTP/1.10 */
+
+           if (!ap_checkmask(buffer, "HTTP/#.# ###*")) {
+               /* Nope, it wasn't even an extra HTTP header. Give up. */
+               return NULL;
+           }
+
+           ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
+                        "proxy: Ignoring duplicate HTTP header "
+                        "returned by %s (%s)", r->uri, r->method);
+           continue;
+       }
 
         *value = '\0';
         ++value;
-    /* XXX: RFC2068 defines only SP and HT as whitespace, this test is
-     * wrong... and so are many others probably.
-     */
+       /* XXX: RFC2068 defines only SP and HT as whitespace, this test is
+        * wrong... and so are many others probably.
+        */
         while (apr_isspace(*value))
             ++value;            /* Skip to start of value   */
 
-    /* should strip trailing whitespace as well */
-    for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
-        *end = '\0';
-
-        apr_table_add(resp_hdrs, buffer, value);
-
-    /* the header was too long; at the least we should skip extra data */
-    if (len >= size - 1) { 
-        while ((len = proxy_getline(field, MAX_STRING_LEN, f, 1))
-            >= MAX_STRING_LEN - 1) {
-        /* soak up the extra data */
-        }
-        if (len == 0) /* time to exit the larger loop as well */
-        break;
-    }
+       /* should strip trailing whitespace as well */
+       for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
+           *end = '\0';
+
+        ap_table_add(resp_hdrs, buffer, value);
+
+       /* the header was too long; at the least we should skip extra data */
+       if (len >= size - 1) { 
+           while ((len = proxy_getline(field, MAX_STRING_LEN, f, 1))
+                   >= MAX_STRING_LEN - 1) {
+               /* soak up the extra data */
+           }
+           if (len == 0) /* time to exit the larger loop as well */
+               break;
+       }
     }
     return resp_hdrs;
 }
 
-long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r, ap_cache_el  *c)
+long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r, ap_cache_el *c)
 {
     int  ok;
     char buf[IOBUFSIZE];
@@ -501,10 +498,10 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
     apr_ssize_t cntr;
     register int n, o;
     conn_rec *con = r->connection;
-    int alternate_timeouts = 1;    /* 1 if we alternate between soft & hard timeouts */
+    int alternate_timeouts = 1;        /* 1 if we alternate between soft & hard timeouts */
     apr_file_t *cachefp = NULL;
     int written = 0, wrote_to_cache;
-    
+       
     total_bytes_rcvd = 0;
     if (c) ap_cache_el_data(c, &cachefp);
 
@@ -512,7 +509,7 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
     /* The cache copy is ASCII, not EBCDIC, even for text/html) */
     ap_bsetflag(f, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);
     if (c != NULL && c->fp != NULL)
-        ap_bsetflag(c->fp, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);
+               ap_bsetflag(c->fp, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);
     ap_bsetflag(con->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);
 #endif
 
@@ -521,17 +518,20 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
      * has its own timeout handler which can set both buffers to EOUT.
      */
 
-#ifdef WIN32
+#if defined(WIN32) || defined(TPF) || defined(NETWARE)
     /* works fine under win32, so leave it */
+    alternate_timeouts = 0;
 #else
     /* CHECKME! Since hard_timeout won't work in unix on sends with partial
      * cache completion, we have to alternate between hard_timeout
      * for reads, and soft_timeout for send.  This is because we need
      * to get a return from ap_bwrite to be able to continue caching.
      * BUT, if we *can't* continue anyway, just use hard_timeout.
+     * (Also, if no cache file is written, use hard timeouts)
      */
 
-    if (!completion || completion->content_length > 0 || completion->cache_completion == 1.0) {
+    if (!completion || completion->content_length > 0
+      || completion->cache_completion == 1.0) {
         alternate_timeouts = 0;
     }
 #endif
@@ -540,28 +540,26 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
      * or (after the client aborted) while we can successfully
      * read and finish the configured cache_completion.
      */
-    for (ok = 1; ok; cntr=0) {
-        /* Read block from server */
-        if(ap_bread(f, buf, IOBUFSIZE, &cntr) != APR_SUCCESS && !cntr)
+    for (ok = 1; ok; cntr = 0) {
+       /* Read block from server */
+       if (ap_bread(f, buf, IOBUFSIZE, &cntr) != APR_SUCCESS && !cntr)
         {
             if (c != NULL) {
                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                              "proxy: error reading from %s", c->name);
+                    "proxy: error reading from %s", c->name);
                 ap_proxy_cache_error(&c);
             }
             break;
-        }
+       }
         else if(cntr == 0) break;
-       
-    
-        /* Write to cache first. */
-        /*@@@ XXX FIXME: Assuming that writing the cache file won't time out?!!? */
+
+       /* Write to cache first. */
+       /*@@@ XXX FIXME: Assuming that writing the cache file won't time out?!!? */
         wrote_to_cache = cntr;
         if (cachefp && apr_write(cachefp, &buf[0], &wrote_to_cache) != APR_SUCCESS) {
             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                          "proxy: error writing to cache");
+               "proxy: error writing to cache");
             ap_proxy_cache_error(&c);
-            cachefp = NULL;
         } else {
             written += n;
         }
@@ -570,7 +568,7 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
         total_bytes_rcvd += cntr;
         in_buffer = cntr;
 
-        /* Write the block to the client, detect aborted transfers */
+       /* Write the block to the client, detect aborted transfers */
         while (!con->aborted && in_buffer > 0) {
             if (ap_bwrite(con->client, &buf[o], in_buffer, &cntr) != APR_SUCCESS) {
                 if (completion) {
@@ -594,7 +592,7 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
     } /* loop and ap_bread while "ok" */
 
     if (!con->aborted)
-        ap_bflush(con->client);
+       ap_bflush(con->client);
 
     return total_bytes_rcvd;
 }
@@ -608,25 +606,25 @@ long int ap_proxy_send_fb(proxy_completion *completion, BUFF *f, request_rec *r,
  */
 void ap_proxy_send_headers(request_rec *r, const char *respline, apr_table_t *t)
 {
-    int i;
-    BUFF *fp = r->connection->client;
-    apr_table_entry_t *elts = (apr_table_entry_t *) apr_table_elts(t)->elts;
+       int i;
+       BUFF *fp = r->connection->client;
+       apr_table_entry_t *elts = (apr_table_entry_t *) apr_table_elts(t)->elts;
 
-    ap_bvputs(fp, respline, CRLF, NULL);
+       ap_bvputs(fp, respline, CRLF, NULL);
 
-    for (i = 0; i < apr_table_elts(t)->nelts; ++i) {
-        if (elts[i].key != NULL) {
-            ap_bvputs(fp, elts[i].key, ": ", elts[i].val, CRLF, NULL);
-            apr_table_addn(r->headers_out, elts[i].key, elts[i].val);
-        }
-    }
+       for (i = 0; i < ap_table_elts(t)->nelts; ++i) {
+            if (elts[i].key != NULL) {
+                ap_bvputs(fp, elts[i].key, ": ", elts[i].val, CRLF, NULL);
+                apr_table_addn(r->headers_out, elts[i].key, elts[i].val);
+            }
+       }
 
-    ap_bputs(CRLF, fp);
+       ap_bputs(CRLF, fp);
 }
 
 
 /*
- * list is a comma-separated list of case insensitive tokens, with
+ * list is a comma-separated list of case-insensitive tokens, with
  * optional whitespace around the tokens.
  * The return returns 1 if the token val is found in the list, or 0
  * otherwise.
@@ -639,26 +637,25 @@ int ap_proxy_liststr(const char *list, const char *val)
     len = strlen(val);
 
     while (list != NULL) {
-    p = ap_strchr_c(list, ',');
-    if (p != NULL) {
-        i = p - list;
-        do
-        p++;
-        while (apr_isspace(*p));
-    }
-    else
-        i = strlen(list);
-
-    while (i > 0 && apr_isspace(list[i - 1]))
-        i--;
-    if (i == len && strncasecmp(list, val, len) == 0)
-        return 1;
-    list = p;
+       p = ap_strchr_c(list, ',');
+       if (p != NULL) {
+           i = p - list;
+           do
+               p++;
+           while (apr_isspace(*p));
+       }
+       else
+           i = strlen(list);
+
+       while (i > 0 && apr_isspace(list[i - 1]))
+           i--;
+       if (i == len && strncasecmp(list, val, len) == 0)
+           return 1;
+       list = p;
     }
     return 0;
 }
 
-
 /*
  * Converts 8 hex digits to a time integer
  */
@@ -668,19 +665,19 @@ int ap_proxy_hex2sec(const char *x)
     unsigned int j;
 
     for (i = 0, j = 0; i < 8; i++) {
-    ch = x[i];
-    j <<= 4;
-    if (apr_isdigit(ch))
-        j |= ch - '0';
-    else if (apr_isupper(ch))
-        j |= ch - ('A' - 10);
-    else
-        j |= ch - ('a' - 10);
+       ch = x[i];
+       j <<= 4;
+       if (apr_isdigit(ch))
+           j |= ch - '0';
+       else if (apr_isupper(ch))
+           j |= ch - ('A' - 10);
+       else
+           j |= ch - ('a' - 10);
     }
     if (j == 0xffffffff)
-    return -1;        /* so that it works with 8-byte ints */
+       return -1;              /* so that it works with 8-byte ints */
     else
-    return j;
+       return j;
 }
 
 /*
@@ -692,18 +689,18 @@ void ap_proxy_sec2hex(int t, char *y)
     unsigned int j = t;
 
     for (i = 7; i >= 0; i--) {
-    ch = j & 0xF;
-    j >>= 4;
-    if (ch >= 10)
-        y[i] = ch + ('A' - 10);
-    else
-        y[i] = ch + '0';
+       ch = j & 0xF;
+       j >>= 4;
+       if (ch >= 10)
+           y[i] = ch + ('A' - 10);
+       else
+           y[i] = ch + '0';
     }
     y[8] = '\0';
 }
 
 
-void ap_proxy_cache_error(ap_cache_el  **c)
+void ap_proxy_cache_error(ap_cache_el **c)
 {
     if (c && *c) {
         const char *name = (*c)->name;
@@ -716,15 +713,15 @@ void ap_proxy_cache_error(ap_cache_el  **c)
 int ap_proxyerror(request_rec *r, int statuscode, const char *message)
 {
     apr_table_setn(r->notes, "error-notes",
-          apr_pstrcat(r->pool, 
-                 "The proxy server could not handle the request "
-                 "<EM><A HREF=\"", ap_escape_uri(r->pool, r->uri),
-                 "\">", ap_escape_html(r->pool, r->method),
-                 "&nbsp;", 
-                 ap_escape_html(r->pool, r->uri), "</A></EM>.<P>\n"
-                 "Reason: <STRONG>",
-                 ap_escape_html(r->pool, message), 
-                 "</STRONG>", NULL));
+       apr_pstrcat(r->pool, 
+               "The proxy server could not handle the request "
+               "<EM><A HREF=\"", ap_escape_uri(r->pool, r->uri),
+               "\">", ap_escape_html(r->pool, r->method),
+               "&nbsp;", 
+               ap_escape_html(r->pool, r->uri), "</A></EM>.<P>\n"
+               "Reason: <STRONG>",
+               ap_escape_html(r->pool, message), 
+               "</STRONG>", NULL));
 
     /* Allow "error-notes" string to be printed by ap_send_error_response() */
     apr_table_setn(r->notes, "verbose-error-to", apr_pstrdup(r->pool, "*"));
@@ -740,34 +737,30 @@ const char *ap_proxy_host2addr(const char *host, struct hostent *reqhp)
 {
     int i;
     struct hostent *hp;
-/* XXX - Either get rid of TLS, or use pthread/APR functions */
-#define APACHE_TLS
-    static APACHE_TLS struct hostent hpbuf;
-    static APACHE_TLS u_long ipaddr;
-    static APACHE_TLS char *charpbuf[2];
+    struct per_thread_data *ptd = get_per_thread_data();
 
     for (i = 0; host[i] != '\0'; i++)
-        if (!apr_isdigit(host[i]) && host[i] != '.')
-            break;
+       if (!apr_isdigit(host[i]) && host[i] != '.')
+           break;
 
     if (host[i] != '\0') {
-        hp = gethostbyname(host);
-        if (hp == NULL)
-            return "Host not found";
+       hp = gethostbyname(host);
+       if (hp == NULL)
+           return "Host not found";
     }
     else {
-        ipaddr = apr_inet_addr(host);
-        hp = gethostbyaddr((char *) &ipaddr, sizeof(u_long), AF_INET);
-        if (hp == NULL) {
-            memset(&hpbuf, 0, sizeof(hpbuf));
-            hpbuf.h_name = 0;
-            hpbuf.h_addrtype = AF_INET;
-            hpbuf.h_length = sizeof(u_long);
-            hpbuf.h_addr_list = charpbuf;
-            hpbuf.h_addr_list[0] = (char *) &ipaddr;
-            hpbuf.h_addr_list[1] = 0;
-            hp = &hpbuf;
-        }
+       ptd->ipaddr = ap_inet_addr(host);
+       hp = gethostbyaddr((char *) &ptd->ipaddr, sizeof(ptd->ipaddr), AF_INET);
+       if (hp == NULL) {
+           memset(&ptd->hpbuf, 0, sizeof(ptd->hpbuf));
+           ptd->hpbuf.h_name = 0;
+           ptd->hpbuf.h_addrtype = AF_INET;
+           ptd->hpbuf.h_length = sizeof(ptd->ipaddr);
+           ptd->hpbuf.h_addr_list = ptd->charpbuf;
+           ptd->hpbuf.h_addr_list[0] = (char *) &ptd->ipaddr;
+           ptd->hpbuf.h_addr_list[1] = 0;
+           hp = &ptd->hpbuf;
+       }
     }
     *reqhp = *hp;
     return NULL;
@@ -780,24 +773,24 @@ static const char *
     int port = -1;
 
     if (r->hostname != NULL)
-    return r->hostname;
+       return r->hostname;
 
     /* Set url to the first char after "scheme://" */
     if ((url = strchr(r->uri, ':')) == NULL
-    || url[1] != '/' || url[2] != '/')
-    return NULL;
+       || url[1] != '/' || url[2] != '/')
+       return NULL;
 
-    url = apr_pstrdup(r->pool, &url[1]);    /* make it point to "//", which is what proxy_canon_netloc expects */
+    url = apr_pstrdup(r->pool, &url[1]);       /* make it point to "//", which is what proxy_canon_netloc expects */
 
     err = ap_proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port);
 
     if (err != NULL)
-    ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
-             "%s", err);
+       ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
+                    "%s", err);
 
     r->hostname = host;
 
-    return host;        /* ought to return the port, too */
+    return host;               /* ought to return the port, too */
 }
 
 /* Return TRUE if addr represents an IP address (or an IP network address) */
@@ -809,7 +802,7 @@ int ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p)
     long bits;
 
     /* if the address is given with an explicit netmask, use that */
-    /* Due to a deficiency in apr_inet_addr(), it is impossible to parse */
+    /* Due to a deficiency in ap_inet_addr(), it is impossible to parse */
     /* "partial" addresses (with less than 4 quads) correctly, i.e.  */
     /* 192.168.123 is parsed as 192.168.0.123, which is not what I want. */
     /* I therefore have to parse the IP address manually: */
@@ -822,86 +815,87 @@ int ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p)
 
     /* Iterate over up to 4 (dotted) quads. */
     for (quads = 0; quads < 4 && *addr != '\0'; ++quads) {
-    char *tmp;
+       char *tmp;
 
-    if (*addr == '/' && quads > 0)    /* netmask starts here. */
-        break;
+       if (*addr == '/' && quads > 0)  /* netmask starts here. */
+           break;
 
-    if (!apr_isdigit(*addr))
-        return 0;        /* no digit at start of quad */
+       if (!apr_isdigit(*addr))
+           return 0;           /* no digit at start of quad */
 
-    ip_addr[quads] = strtol(addr, &tmp, 0);
+       ip_addr[quads] = strtol(addr, &tmp, 0);
 
-    if (tmp == addr)    /* expected a digit, found something else */
-        return 0;
+       if (tmp == addr)        /* expected a digit, found something else */
+           return 0;
 
-    if (ip_addr[quads] < 0 || ip_addr[quads] > 255) {
-        /* invalid octet */
-        return 0;
-    }
+       if (ip_addr[quads] < 0 || ip_addr[quads] > 255) {
+           /* invalid octet */
+           return 0;
+       }
 
-    addr = tmp;
+       addr = tmp;
 
-    if (*addr == '.' && quads != 3)
-        ++addr;        /* after the 4th quad, a dot would be illegal */
+       if (*addr == '.' && quads != 3)
+           ++addr;             /* after the 4th quad, a dot would be illegal */
     }
 
     for (This->addr.s_addr = 0, i = 0; i < quads; ++i)
-    This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
+       This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
 
-    if (addr[0] == '/' && apr_isdigit(addr[1])) {    /* net mask follows: */
-    char *tmp;
+    if (addr[0] == '/' && apr_isdigit(addr[1])) {      /* net mask follows: */
+       char *tmp;
 
-    ++addr;
+       ++addr;
 
-    bits = strtol(addr, &tmp, 0);
+       bits = strtol(addr, &tmp, 0);
 
-    if (tmp == addr)    /* expected a digit, found something else */
-        return 0;
+       if (tmp == addr)        /* expected a digit, found something else */
+           return 0;
 
-    addr = tmp;
+       addr = tmp;
 
-    if (bits < 0 || bits > 32)    /* netmask must be between 0 and 32 */
-        return 0;
+       if (bits < 0 || bits > 32)      /* netmask must be between 0 and 32 */
+           return 0;
 
     }
     else {
-    /* Determine (i.e., "guess") netmask by counting the */
-    /* number of trailing .0's; reduce #quads appropriately */
-    /* (so that 192.168.0.0 is equivalent to 192.168.)        */
-    while (quads > 0 && ip_addr[quads - 1] == 0)
-        --quads;
-
-    /* "IP Address should be given in dotted-quad form, optionally followed by a netmask (e.g., 192.168.111.0/24)"; */
-    if (quads < 1)
-        return 0;
-
-    /* every zero-byte counts as 8 zero-bits */
-    bits = 8 * quads;
-
-    if (bits != 32)        /* no warning for fully qualified IP address */
-        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
-                         "Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld",
-            inet_ntoa(This->addr), bits);
+       /* Determine (i.e., "guess") netmask by counting the */
+       /* number of trailing .0's; reduce #quads appropriately */
+       /* (so that 192.168.0.0 is equivalent to 192.168.)        */
+       while (quads > 0 && ip_addr[quads - 1] == 0)
+           --quads;
+
+       /* "IP Address should be given in dotted-quad form, optionally followed by a netmask (e.g., 192.168.111.0/24)"; */
+       if (quads < 1)
+           return 0;
+
+       /* every zero-byte counts as 8 zero-bits */
+       bits = 8 * quads;
+
+       if (bits != 32)         /* no warning for fully qualified IP address */
+            ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
+             "Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld\n",
+                inet_ntoa(This->addr), bits);
     }
 
-    This->mask.s_addr = htonl(APR_INADDR_NONE << (32 - bits));
+    This->mask.s_addr = htonl(INADDR_NONE << (32 - bits));
 
     if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) {
-    ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, "Warning: NetMask and IP-Addr disagree in %s/%ld",
-        inet_ntoa(This->addr), bits);
-    This->addr.s_addr &= This->mask.s_addr;
-    ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
-                     "         Set to %s/%ld",
-        inet_ntoa(This->addr), bits);
+        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
+           "Warning: NetMask and IP-Addr disagree in %s/%ld\n",
+               inet_ntoa(This->addr), bits);
+       This->addr.s_addr &= This->mask.s_addr;
+        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
+           "         Set to %s/%ld\n",
+               inet_ntoa(This->addr), bits);
     }
 
     if (*addr == '\0') {
-    This->matcher = proxy_match_ipaddr;
-    return 1;
+       This->matcher = proxy_match_ipaddr;
+       return 1;
     }
     else
-    return (*addr == '\0');    /* okay iff we've parsed the whole string */
+       return (*addr == '\0'); /* okay iff we've parsed the whole string */
 }
 
 /* Return TRUE if addr represents an IP address (or an IP network address) */
@@ -922,54 +916,54 @@ static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r)
     memset(ip_addr, '\0', sizeof ip_addr);
 
     if (4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3])) {
-    for (addr.s_addr = 0, i = 0; i < 4; ++i)
-        addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
+       for (addr.s_addr = 0, i = 0; i < 4; ++i)
+           addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
 
-    if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr)) {
+       if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr)) {
 #if DEBUGGING
-        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
+        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                          "1)IP-Match: %s[%s] <-> ", host, inet_ntoa(addr));
-        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
+        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                          "%s/", inet_ntoa(This->addr));
-        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
+        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                          "%s", inet_ntoa(This->mask));
 #endif
-        return 1;
-    }
+           return 1;
+       }
 #if DEBUGGING
-    else {
-        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
+       else {
+        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                          "1)IP-NoMatch: %s[%s] <-> ", host, inet_ntoa(addr));
-        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
+        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                          "%s/", inet_ntoa(This->addr));
-        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
+        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                          "%s", inet_ntoa(This->mask));
-    }
+       }
 #endif
     }
     else {
-    struct hostent the_host;
+       struct hostent the_host;
 
-    memset(&the_host, '\0', sizeof the_host);
-    found = ap_proxy_host2addr(host, &the_host);
+       memset(&the_host, '\0', sizeof the_host);
+       found = ap_proxy_host2addr(host, &the_host);
 
-    if (found != NULL) {
+       if (found != NULL) {
 #if DEBUGGING
-        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
+        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                          "2)IP-NoMatch: hostname=%s msg=%s", host, found);
 #endif
-        return 0;
-    }
-
-    if (the_host.h_name != NULL)
-        found = the_host.h_name;
-    else
-        found = host;
-
-    /* Try to deal with multiple IP addr's for a host */
-    for (ip_listptr = the_host.h_addr_list; *ip_listptr; ++ip_listptr) {
-        ip_list = (struct in_addr *) *ip_listptr;
-        if (This->addr.s_addr == (ip_list->s_addr & This->mask.s_addr)) {
+           return 0;
+       }
+
+       if (the_host.h_name != NULL)
+           found = the_host.h_name;
+       else
+           found = host;
+
+       /* Try to deal with multiple IP addr's for a host */
+       for (ip_listptr = the_host.h_addr_list; *ip_listptr; ++ip_listptr) {
+           ip_list = (struct in_addr *) *ip_listptr;
+           if (This->addr.s_addr == (ip_list->s_addr & This->mask.s_addr)) {
 #if DEBUGGING
         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                        "3)IP-Match: %s[%s] <-> ", found, inet_ntoa(*ip_list));
@@ -978,19 +972,19 @@ static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r)
         ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                        "%s", inet_ntoa(This->mask));
 #endif
-        return 1;
-        }
+               return 1;
+           }
 #if DEBUGGING
-        else {
-        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
+           else {
+                ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                        "3)IP-NoMatch: %s[%s] <-> ", found, inet_ntoa(*ip_list));
-        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
+                ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                        "%s/", inet_ntoa(This->addr));
-        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
+                ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                        "%s", inet_ntoa(This->mask));
-        }
+           }
 #endif
-    }
+       }
     }
 
     return 0;
@@ -1004,26 +998,26 @@ int ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p)
 
     /* Domain name must start with a '.' */
     if (addr[0] != '.')
-    return 0;
+       return 0;
 
     /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
     for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i)
-    continue;
+       continue;
 
 #if 0
     if (addr[i] == ':') {
-    ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
+    ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                      "@@@@ handle optional port in proxy_is_domainname()");
-    /* @@@@ handle optional port */
+       /* @@@@ handle optional port */
     }
 #endif
 
     if (addr[i] != '\0')
-    return 0;
+       return 0;
 
     /* Strip trailing dots */
     for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
-    addr[i] = '\0';
+       addr[i] = '\0';
 
     This->matcher = proxy_match_domainname;
     return 1;
@@ -1035,19 +1029,19 @@ static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r)
     const char *host = proxy_get_host_of_request(r);
     int d_len = strlen(This->name), h_len;
 
-    if (host == NULL)        /* some error was logged already */
-    return 0;
+    if (host == NULL)          /* some error was logged already */
+       return 0;
 
     h_len = strlen(host);
 
     /* @@@ do this within the setup? */
     /* Ignore trailing dots in domain comparison: */
     while (d_len > 0 && This->name[d_len - 1] == '.')
-    --d_len;
+       --d_len;
     while (h_len > 0 && host[h_len - 1] == '.')
-    --h_len;
+       --h_len;
     return h_len > d_len
-    && strncasecmp(&host[h_len - d_len], This->name, d_len) == 0;
+       && strncasecmp(&host[h_len - d_len], This->name, d_len) == 0;
 }
 
 /* Return TRUE if addr represents a host name */
@@ -1059,27 +1053,27 @@ int ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p)
 
     /* Host names must not start with a '.' */
     if (addr[0] == '.')
-    return 0;
+       return 0;
 
     /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
     for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i);
 
 #if 0
     if (addr[i] == ':') {
-    ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
+    ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
                      "@@@@ handle optional port in proxy_is_hostname()");
-    /* @@@@ handle optional port */
+       /* @@@@ handle optional port */
     }
 #endif
 
     if (addr[i] != '\0' || ap_proxy_host2addr(addr, &host) != NULL)
-    return 0;
+       return 0;
 
     This->hostentry = ap_pduphostent (p, &host);
 
     /* Strip trailing dots */
     for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
-    addr[i] = '\0';
+       addr[i] = '\0';
 
     This->matcher = proxy_match_hostname;
     return 1;
@@ -1104,17 +1098,17 @@ static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r)
 
     /* Try to deal with multiple IP addr's for a host */
     for (ip_list = *This->hostentry->h_addr_list; *ip_list != 0UL; ++ip_list)
-    if (*ip_list == ? ? ? ? ? ? ? ? ? ? ? ? ?)
-        return 1;
+       if (*ip_list == ? ? ? ? ? ? ? ? ? ? ? ? ?)
+           return 1;
 #endif
 
     /* Ignore trailing dots in host2 comparison: */
     while (h2_len > 0 && host2[h2_len - 1] == '.')
-    --h2_len;
+       --h2_len;
     while (h1_len > 0 && host[h1_len - 1] == '.')
-    --h1_len;
+       --h1_len;
     return h1_len == h2_len
-    && strncasecmp(host, host2, h1_len) == 0;
+       && strncasecmp(host, host2, h1_len) == 0;
 }
 
 /* Return TRUE if addr is to be matched as a word */
@@ -1134,6 +1128,7 @@ static int proxy_match_word(struct dirconn_entry *This, request_rec *r)
 int ap_proxy_doconnect(apr_socket_t *sock, char *host, apr_uint32_t port, request_rec *r)
 {
     int i;
+
     for (i = 0; host[i] != '\0'; i++)
         if (!apr_isdigit(host[i]) && host[i] != '.')
             break;
@@ -1151,14 +1146,15 @@ int ap_proxy_doconnect(apr_socket_t *sock, char *host, apr_uint32_t port, reques
         else if (rv == APR_SUCCESS)
             return 0;
         else {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "proxy connect to %s port %d failed", host, port);
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+                "proxy connect to %s port %d failed", host, port);
             return -1;
         }
     }
     return -1;
 }
 
-/* This function is called by apr_table_do() for all header lines */
+/* This function is called by ap_table_do() for all header lines */
 /* (from proxy_http.c and proxy_ftp.c) */
 /* It is passed a table_do_args struct pointer and a MIME field and value pair */
 int ap_proxy_send_hdr_line(void *p, const char *key, const char *value)
@@ -1168,20 +1164,65 @@ int ap_proxy_send_hdr_line(void *p, const char *key, const char *value)
         return 1;
     if (!r->assbackwards)
         ap_rvputs(r, key, ": ", value, CRLF, NULL);
-    return 1; /* tell apr_table_do() to continue calling us for more headers */
+    return 1; /* tell ap_table_do() to continue calling us for more headers */
 }
 
 /* send a text line to one or two BUFF's; return line length */
-unsigned ap_proxy_bputs2(const char *data, BUFF *client, ap_cache_el  *cache)
+unsigned ap_proxy_bputs2(const char *data, BUFF *client, ap_cache_el *cache)
 {
     unsigned len = ap_bputs(data, client);
     apr_file_t *cachefp = NULL;
-    
+
     if (ap_cache_el_data(cache, &cachefp) == APR_SUCCESS)
-        apr_puts(data, cachefp);
+       apr_puts(data, cachefp);
     return len;
 }
 
+#if defined WIN32
+
+static DWORD tls_index;
+
+BOOL WINAPI DllMain (HINSTANCE dllhandle, DWORD reason, LPVOID reserved)
+{
+    LPVOID memptr;
+
+    switch (reason) {
+    case DLL_PROCESS_ATTACH:
+       tls_index = TlsAlloc();
+    case DLL_THREAD_ATTACH: /* intentional no break */
+       TlsSetValue (tls_index, malloc (sizeof (struct per_thread_data)));
+       break;
+    case DLL_THREAD_DETACH:
+       memptr = TlsGetValue (tls_index);
+       if (memptr) {
+           free (memptr);
+           TlsSetValue (tls_index, 0);
+       }
+       break;
+    }
+
+    return TRUE;
+}
+
+#endif
+
+static struct per_thread_data *get_per_thread_data(void)
+{
+#if 0
+#if defined(WIN32)
+
+    return (struct per_thread_data *) TlsGetValue (tls_index);
+
+#else
+
+    static APACHE_TLS struct per_thread_data sptd;
+    return &sptd;
+
+#endif
+#endif
+    return NULL;
+}
+
 int ap_proxy_cache_send(request_rec *r, ap_cache_el *c)
 {
     apr_file_t *cachefp = NULL;