From: Chuck Murcko Date: Sat, 11 Nov 2000 11:07:03 +0000 (+0000) Subject: This is the 1.3.x current proxy into 2.0 - first stage X-Git-Tag: APACHE_2_0_ALPHA_8~99 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=31c42a957cd3a52aa6cd3ec6d6726d15e343a403;p=apache This is the 1.3.x current proxy into 2.0 - first stage 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 --- diff --git a/modules/proxy/proxy_connect.c b/modules/proxy/proxy_connect.c index 00ae97ceb6..4de7ab5e83 100644 --- a/modules/proxy/proxy_connect.c +++ b/modules/proxy/proxy_connect.c @@ -58,13 +58,12 @@ /* 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 /* for IRIX, FD_SET calls bzero() */ +#include /* 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:
", - strerror(errno), NULL)); + apr_pstrcat(r->pool, "Could not connect to remote machine:
", + 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; diff --git a/modules/proxy/proxy_http.c b/modules/proxy/proxy_http.c index ff5e28634a..b26a2ed131 100644 --- a/modules/proxy/proxy_http.c +++ b/modules/proxy/proxy_http.c @@ -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); diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index 5b6a18331f..4b6b2139b5 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -57,21 +57,18 @@ */ /* 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 +#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 " - "pool, r->uri), - "\">", ap_escape_html(r->pool, r->method), - " ", - ap_escape_html(r->pool, r->uri), ".

\n" - "Reason: ", - ap_escape_html(r->pool, message), - "", NULL)); + apr_pstrcat(r->pool, + "The proxy server could not handle the request " + "pool, r->uri), + "\">", ap_escape_html(r->pool, r->method), + " ", + ap_escape_html(r->pool, r->uri), ".

\n" + "Reason: ", + ap_escape_html(r->pool, message), + "", 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;