Return-Path: Delivered-To: apmail-jakarta-tomcat-dev-archive@jakarta.apache.org Received: (qmail 74735 invoked by uid 500); 26 Mar 2001 18:00:44 -0000 Mailing-List: contact tomcat-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: list-post: Reply-To: tomcat-dev@jakarta.apache.org Delivered-To: mailing list tomcat-dev@jakarta.apache.org Delivered-To: moderator for tomcat-dev@jakarta.apache.org Received: (qmail 8988 invoked from network); 26 Mar 2001 13:38:28 -0000 From: =?iso-8859-1?Q?Jens_M=F8nster_S=F8rensen?= To: Cc: Subject: IIS redirector error handling Date: Mon, 26 Mar 2001 15:46:32 +0200 Message-ID: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_004D_01C0B60B.EE742B20" X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2919.6700 Importance: Normal X-Spam-Rating: h31.sny.collab.net 1.6.2 0/1000/N This is a multi-part message in MIME format. ------=_NextPart_000_004D_01C0B60B.EE742B20 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Hi We have been using JServ now Tomcat for some years now and are quite happy about it. But alas some of our customers want thier stuff running on Win NT or Win 2000, so we have also been using the IIS redirector. And we have found it pretty unsatisfactory that when the tomcat/java process for some reason dies, the only thing client recives is a broken connection and no response. Which for instance by the MS Internet Explorer is interpreted as a DNS error. So we wanted to change the redirector to write some kind of configurable response to the client before cutting the connection. Without beeing an expert on IIS, it is my impression that IIS has a standard way of handling this. For each site and its "virtual dirs" you can for each http error code set up a response (a local file, a URI or a URL). Therefore my first idea was to change the redirector to just set the error code to 503 "Service Unavailable" when it failed to connect to the Tomcat process, and thus utilising the IIS standard way of doing it. But I was not able to get this working. So instead I changed the redirector to read a new string value "error_uri" from the "Jakarta Isapi Redirector/1.0" registry key (i.e. similar to the "extension_uri" setting), and then send this URI to the client when it is unable to connect to the Tomcat Process. I made the change in the jk_isapi_plugin.c which I have attached to this mail. It has been tested and works fine on Win 2000 Server. I regretfully haven't got the time to get very much more involved than this, and trust that sending this mail to the tomcat-dev list should be enough to get this change proposal (or somthing similar to it) considered for addition to the code-base. Thanks in advance /Jens ------=_NextPart_000_004D_01C0B60B.EE742B20 Content-Type: application/octet-stream; name="jk_isapi_plugin.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="jk_isapi_plugin.c" /* * Copyright (c) 1997-1999 The Java Apache Project. All rights = reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Java Apache=20 * Project for use in the Apache JServ servlet engine project * ." * * 4. The names "Apache JServ", "Apache JServ Servlet Engine" and=20 * "Java Apache Project" must not be used to endorse or promote = products=20 * derived from this software without prior written permission. * * 5. Products derived from this software may not be called "Apache = JServ" * nor may "Apache" nor "Apache JServ" appear in their names without=20 * prior written permission of the Java Apache Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Java Apache=20 * Project for use in the Apache JServ servlet engine project * ." * =20 * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JAVA APACHE PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many * individuals on behalf of the Java Apache Group. For more information * on the Java Apache Project and the Apache JServ Servlet Engine = project, * please see . * =B4 */ /************************************************************************= *** * Description: ISAPI plugin for IIS/PWS = * * Author: Gal Shachor = * * Version: $Revision: 1.5.2.1 $ = * = *************************************************************************= **/ #include #include #include #include "jk_global.h" #include "jk_util.h" #include "jk_map.h" #include "jk_pool.h" #include "jk_service.h" #include "jk_worker.h" #include "jk_ajp12_worker.h" #include "jk_uri_worker_map.h" #define VERSION_STRING "Jakarta/ISAPI/1.0b1" /* * We use special two headers to pass values from the filter to the=20 * extension. These values are: * * 1. The real URI before redirection took place * 2. The name of the worker to be used. * */ #define URI_HEADER_NAME ("TOMCATURI:") #define WORKER_HEADER_NAME ("TOMCATWORKER:") #define HTTP_URI_HEADER_NAME ("HTTP_TOMCATURI") #define HTTP_WORKER_HEADER_NAME ("HTTP_TOMCATWORKER") #define REGISTRY_LOCATION ("Software\\Apache Software = Foundation\\Jakarta Isapi Redirector\\1.0") #define EXTENSION_URI_TAG ("extension_uri") #define ERROR_URI_TAG ("error_uri") #define GET_SERVER_VARIABLE_VALUE(name, place) { \ (place) =3D NULL; \ huge_buf_sz =3D sizeof(huge_buf); \ if(get_server_value(private_data->lpEcb, \ (name), \ huge_buf, \ huge_buf_sz, \ "")) { \ (place) =3D jk_pool_strdup(&private_data->p, huge_buf); \ } \ }\ #define GET_SERVER_VARIABLE_VALUE_INT(name, place, def) { \ huge_buf_sz =3D sizeof(huge_buf); \ if(get_server_value(private_data->lpEcb, \ (name), \ huge_buf, \ huge_buf_sz, \ "")) { \ (place) =3D atoi(huge_buf); \ if(0 =3D=3D (place)) { \ (place) =3D def; \ } \ } else { \ (place) =3D def; \ } \ }\ static int is_inited =3D JK_FALSE; static jk_uri_worker_map_t *uw_map =3D NULL;=20 static jk_logger_t *logger =3D NULL;=20 static char extension_uri[INTERNET_MAX_URL_LENGTH] =3D = "/jakarta/isapi_redirect.dll"; static char error_uri[INTERNET_MAX_URL_LENGTH] =3D "/error.html"; static char log_file[MAX_PATH * 2]; static int log_level =3D JK_LOG_EMERG_LEVEL; static char worker_file[MAX_PATH * 2]; static char worker_mount_file[MAX_PATH * 2]; struct isapi_private_data { jk_pool_t p; =20 int request_started; unsigned bytes_read_so_far; LPEXTENSION_CONTROL_BLOCK lpEcb; }; typedef struct isapi_private_data isapi_private_data_t; static int JK_METHOD start_response(jk_ws_service_t *s, int status, const char *reason, const char * const *header_names, const char * const *header_values, unsigned num_of_headers); static int JK_METHOD read(jk_ws_service_t *s, void *b, unsigned l, unsigned *a); static int JK_METHOD write(jk_ws_service_t *s, const void *b, unsigned l); static int init_ws_service(isapi_private_data_t *private_data, jk_ws_service_t *s, char **worker_name); static int initialize_extension(void); static int read_registry_init_data(void); static int get_registry_config_parameter(HKEY hkey, const char *tag,=20 char *b, DWORD sz); static int get_server_value(LPEXTENSION_CONTROL_BLOCK lpEcb, char *name, char *buf, DWORD bufsz, char *def_val); static int uri_is_web_inf(char *uri) { char *c =3D uri; while(*c) { *c =3D tolower(*c); c++; } =20 if(strstr(uri, "web-inf")) { return JK_TRUE; } return JK_FALSE; } static int JK_METHOD start_response(jk_ws_service_t *s, int status, const char *reason, const char * const *header_names, const char * const *header_values, unsigned num_of_headers) { static char crlf[3] =3D { (char)13, (char)10, '\0' }; jk_log(logger, JK_LOG_DEBUG,=20 "Into jk_ws_service_t::start_response\n"); if(status < 100 || status > 1000) { jk_log(logger, JK_LOG_ERROR,=20 "jk_ws_service_t::start_response, invalid status %d\n", = status); return JK_FALSE; } if(s && s->ws_private) { isapi_private_data_t *p =3D s->ws_private; if(!p->request_started) { DWORD len_of_status; char *status_str; char *headers_str; p->request_started =3D JK_TRUE; /* * Create the status line */ if(!reason) { reason =3D ""; } status_str =3D (char *)_alloca((6 + strlen(reason)) * = sizeof(char)); sprintf(status_str, "%d %s", status, reason); len_of_status =3D strlen(status_str);=20 =20 /* * Create response headers string */ if(num_of_headers) { unsigned i; unsigned len_of_headers; for(i =3D 0 , len_of_headers =3D 0 ; i < num_of_headers = ; i++) { len_of_headers +=3D strlen(header_names[i]); len_of_headers +=3D strlen(header_values[i]); len_of_headers +=3D 4; /* extra for colon, space and = crlf */ } len_of_headers +=3D 3; /* crlf and terminating null = char */ headers_str =3D (char *)_alloca(len_of_headers * = sizeof(char)); headers_str[0] =3D '\0'; for(i =3D 0 ; i < num_of_headers ; i++) { strcat(headers_str, header_names[i]); strcat(headers_str, ": "); strcat(headers_str, header_values[i]); strcat(headers_str, crlf); } strcat(headers_str, crlf); } else { headers_str =3D crlf; } if(!p->lpEcb->ServerSupportFunction(p->lpEcb->ConnID,=20 = HSE_REQ_SEND_RESPONSE_HEADER, status_str, (LPDWORD)&len_of_status, (LPDWORD)headers_str)) { jk_log(logger, JK_LOG_ERROR,=20 "jk_ws_service_t::start_response, = ServerSupportFunction failed\n"); return JK_FALSE; } =20 } return JK_TRUE; } jk_log(logger, JK_LOG_ERROR,=20 "jk_ws_service_t::start_response, NULL parameters\n"); return JK_FALSE; } static int JK_METHOD read(jk_ws_service_t *s, void *b, unsigned l, unsigned *a) { jk_log(logger, JK_LOG_DEBUG,=20 "Into jk_ws_service_t::read\n"); if(s && s->ws_private && b && a) { isapi_private_data_t *p =3D s->ws_private; =20 *a =3D 0; if(l) { char *buf =3D b; DWORD already_read =3D p->lpEcb->cbAvailable - = p->bytes_read_so_far; =20 if(already_read >=3D l) { memcpy(buf, p->lpEcb->lpbData + p->bytes_read_so_far, = l); p->bytes_read_so_far +=3D l; *a =3D l; } else { /* * Try to copy what we already have=20 */ if(already_read > 0) { memcpy(buf, p->lpEcb->lpbData + = p->bytes_read_so_far, already_read); buf +=3D already_read; l -=3D already_read; p->bytes_read_so_far =3D p->lpEcb->cbAvailable; =20 *a =3D already_read; } =20 /* * Now try to read from the client ... */ if(p->lpEcb->ReadClient(p->lpEcb->ConnID, buf, &l)) { *a +=3D l; =20 } else { jk_log(logger, JK_LOG_ERROR,=20 "jk_ws_service_t::read, ReadClient = failed\n"); return JK_FALSE; } =20 } } return JK_TRUE; } jk_log(logger, JK_LOG_ERROR,=20 "jk_ws_service_t::read, NULL parameters\n"); return JK_FALSE; } static int JK_METHOD write(jk_ws_service_t *s, const void *b, unsigned l) { jk_log(logger, JK_LOG_DEBUG,=20 "Into jk_ws_service_t::write\n"); if(s && s->ws_private && b) { isapi_private_data_t *p =3D s->ws_private; if(l) { unsigned written =3D 0; =20 char *buf =3D (char *)b; if(!p->request_started) { start_response(s, 200, NULL, NULL, NULL, 0); } while(written < l) { DWORD try_to_write =3D l - written; if(!p->lpEcb->WriteClient(p->lpEcb->ConnID,=20 buf + written,=20 &try_to_write,=20 0)) { jk_log(logger, JK_LOG_ERROR,=20 "jk_ws_service_t::write, WriteClient = failed\n"); return JK_FALSE; } written +=3D try_to_write; } } return JK_TRUE; } jk_log(logger, JK_LOG_ERROR,=20 "jk_ws_service_t::write, NULL parameters\n"); return JK_FALSE; } BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer) { ULONG http_filter_revision =3D HTTP_FILTER_REVISION=20 pVer->dwFilterVersion =3D pVer->dwServerFilterVersion; =20 if(pVer->dwFilterVersion > http_filter_revision) { pVer->dwFilterVersion =3D http_filter_revision; } pVer->dwFlags =3D SF_NOTIFY_ORDER_HIGH |=20 SF_NOTIFY_SECURE_PORT |=20 SF_NOTIFY_NONSECURE_PORT | SF_NOTIFY_PREPROC_HEADERS; =20 strcpy(pVer->lpszFilterDesc, VERSION_STRING); if(!is_inited) { return initialize_extension(); } return TRUE; } DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD dwNotificationType,=20 LPVOID pvNotification) { if(is_inited && (SF_NOTIFY_PREPROC_HEADERS =3D=3D dwNotificationType)) {=20 PHTTP_FILTER_PREPROC_HEADERS p =3D = (PHTTP_FILTER_PREPROC_HEADERS)pvNotification; char uri[INTERNET_MAX_URL_LENGTH];=20 char *query; DWORD sz =3D sizeof(uri); jk_log(logger, JK_LOG_DEBUG,=20 "HttpFilterProc started\n"); /* * Just in case somebody set these headers in the request! */ p->SetHeader(pfc, URI_HEADER_NAME, NULL); p->SetHeader(pfc, WORKER_HEADER_NAME, NULL); =20 if(!p->GetHeader(pfc, "url", (LPVOID)uri, (LPDWORD)&sz)) { jk_log(logger, JK_LOG_ERROR,=20 "HttpFilterProc error while getting the url\n"); return SF_STATUS_REQ_ERROR; } if(strlen(uri)) { char *worker; query =3D strchr(uri, '?'); if(query) { *query =3D '\0'; } jk_log(logger, JK_LOG_DEBUG,=20 "In HttpFilterProc test redirection of %s\n",=20 uri); worker =3D map_uri_to_worker(uw_map, uri, logger); =20 if(query) { *query =3D '?'; } if(worker) { /* This is a servlet, should redirect ... */ jk_log(logger, JK_LOG_DEBUG,=20 "HttpFilterProc [%s] is a servlet url - should redirect = to %s\n",=20 uri, worker); =20 if(!p->AddHeader(pfc, URI_HEADER_NAME, uri) ||=20 !p->AddHeader(pfc, WORKER_HEADER_NAME, worker) || !p->SetHeader(pfc, "url", extension_uri)) { jk_log(logger, JK_LOG_ERROR,=20 "HttpFilterProc error while adding request headers\n"); return SF_STATUS_REQ_ERROR; } } else { jk_log(logger, JK_LOG_DEBUG,=20 "HttpFilterProc [%s] is not a servlet url\n",=20 uri); } /* * Check if somebody is feading us with his own TOMCAT data = headers. * We reject such postings ! */ jk_log(logger, JK_LOG_DEBUG,=20 "HttpFilterProc check if [%s] is points to the web-inf = directory\n",=20 uri); if(uri_is_web_inf(uri)) { char crlf[3] =3D { (char)13, (char)10, '\0' }; char ctype[30]; char *msg =3D "

Access is = Forbidden

"; DWORD len =3D strlen(msg); jk_log(logger, JK_LOG_EMERG,=20 "HttpFilterProc [%s] points to the web-inf = directory.\nSomebody try to hack into the site!!!\n",=20 uri); sprintf(ctype,=20 "Content-Type:text/html%s%s",=20 crlf,=20 crlf); /* reject !!! */ pfc->ServerSupportFunction(pfc,=20 SF_REQ_SEND_RESPONSE_HEADER, "403 Forbidden", (DWORD)crlf, (DWORD)ctype); pfc->WriteClient(pfc, msg, &len, 0); return SF_STATUS_REQ_FINISHED; } } } return SF_STATUS_REQ_NEXT_NOTIFICATION; } BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer) { pVer->dwExtensionVersion =3D MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR ); strcpy(pVer->lpszExtensionDesc, VERSION_STRING); if(!is_inited) { return initialize_extension(); } return TRUE; } DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpEcb) { =20 DWORD rc =3D HSE_STATUS_ERROR; lpEcb->dwHttpStatusCode =3D HTTP_STATUS_SERVER_ERROR; jk_log(logger, JK_LOG_DEBUG,=20 "HttpExtensionProc started\n"); if(is_inited) { isapi_private_data_t private_data; jk_ws_service_t s; jk_pool_atom_t buf[SMALL_POOL_SIZE]; char *worker_name; jk_init_ws_service(&s); jk_open_pool(&private_data.p, buf, sizeof(buf)); private_data.request_started =3D JK_FALSE; private_data.bytes_read_so_far =3D 0; private_data.lpEcb =3D lpEcb; s.ws_private =3D &private_data; s.pool =3D &private_data.p; if(init_ws_service(&private_data, &s, &worker_name)) { jk_worker_t *worker =3D wc_get_worker_for_name(worker_name, = logger); jk_log(logger, JK_LOG_DEBUG,=20 "HttpExtensionProc %s a worker for name %s\n",=20 worker ? "got" : "could not get", worker_name); if(worker) { jk_endpoint_t *e =3D NULL; if(worker->get_endpoint(worker, &e, logger)) { int recover =3D JK_FALSE; if(e->service(e, &s, logger, &recover)) { rc =3D HSE_STATUS_SUCCESS_AND_KEEP_CONN; lpEcb->dwHttpStatusCode =3D HTTP_STATUS_OK; jk_log(logger, JK_LOG_DEBUG,=20 "HttpExtensionProc service() returned = OK\n"); } else { rc =3D HSE_STATUS_ERROR; lpEcb->dwHttpStatusCode =3D = HTTP_STATUS_SERVICE_UNAVAIL;=20 jk_log(logger, JK_LOG_ERROR,=20 "HttpExtensionProc error, service() = failed\n"); = lpEcb->ServerSupportFunction(lpEcb,HSE_REQ_SEND_URL, error_uri,0,0); } e->done(&e, logger); } } else { jk_log(logger, JK_LOG_ERROR,=20 "HttpExtensionProc error, could not get a worker = for name %s\n", worker_name); } } jk_close_pool(&private_data.p); =20 } else { jk_log(logger, JK_LOG_ERROR,=20 "HttpExtensionProc error, not initialized\n"); } return rc; } =20 BOOL WINAPI TerminateExtension(DWORD dwFlags)=20 { return TerminateFilter(dwFlags); } BOOL WINAPI TerminateFilter(DWORD dwFlags)=20 { if(is_inited) { is_inited =3D JK_FALSE; uri_worker_map_free(&uw_map, logger); wc_close(logger); if(logger) { jk_close_file_logger(&logger); } } =20 return TRUE; } BOOL WINAPI DllMain(HINSTANCE hInst, // Instance Handle of the = DLL ULONG ulReason, // Reason why NT called this = DLL LPVOID lpReserved) // Reserved parameter for = future use { BOOL fReturn =3D TRUE; switch (ulReason) { case DLL_PROCESS_DETACH: __try { TerminateFilter(HSE_TERM_MUST_UNLOAD); } __except(1) { } break; default: break; }=20 return fReturn; } static int initialize_extension(void) { int rc =3D JK_FALSE; =20 if(read_registry_init_data()) { jk_map_t *map; if(!jk_open_file_logger(&logger, log_file, log_level)) { logger =3D NULL; } =20 if(map_alloc(&map)) { if(map_read_properties(map, worker_mount_file)) { if(uri_worker_map_alloc(&uw_map, map, logger)) { rc =3D JK_TRUE; } } map_free(&map); } if(rc) { rc =3D JK_FALSE; if(map_alloc(&map)) { if(map_read_properties(map, worker_file)) { if(wc_open(map, logger)) { rc =3D JK_TRUE; } } map_free(&map); } } } if(rc) { is_inited =3D JK_TRUE; } return rc; } static int read_registry_init_data(void) { char tmpbuf[INTERNET_MAX_URL_LENGTH]; HKEY hkey; long rc; int ok =3D JK_TRUE; rc =3D RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_LOCATION, (DWORD)0, =20 KEY_READ, =20 &hkey); =20 if(ERROR_SUCCESS !=3D rc) { return JK_FALSE; }=20 if(get_registry_config_parameter(hkey, JK_LOG_FILE_TAG,=20 tmpbuf, sizeof(log_file))) { strcpy(log_file, tmpbuf); } else { ok =3D JK_FALSE; } =20 if(get_registry_config_parameter(hkey, JK_LOG_LEVEL_TAG,=20 tmpbuf, sizeof(tmpbuf))) { log_level =3D jk_parse_log_level(tmpbuf); } else { ok =3D JK_FALSE; } if(get_registry_config_parameter(hkey, EXTENSION_URI_TAG,=20 tmpbuf, sizeof(extension_uri))) { strcpy(extension_uri, tmpbuf); } else { ok =3D JK_FALSE; } if(get_registry_config_parameter(hkey, ERROR_URI_TAG,=20 tmpbuf, sizeof(error_uri))) { strcpy(error_uri, tmpbuf); } else { ok =3D JK_FALSE; } if(get_registry_config_parameter(hkey, JK_WORKER_FILE_TAG,=20 tmpbuf, sizeof(worker_file))) { strcpy(worker_file, tmpbuf); } else { ok =3D JK_FALSE; } if(get_registry_config_parameter(hkey, JK_MOUNT_FILE_TAG,=20 tmpbuf, sizeof(worker_mount_file))) { strcpy(worker_mount_file, tmpbuf); } else { ok =3D JK_FALSE; } RegCloseKey(hkey); return ok; } static int get_registry_config_parameter(HKEY hkey, const char *tag,=20 char *b, DWORD sz) { =20 DWORD type =3D 0; LONG lrc; lrc =3D RegQueryValueEx(hkey, =20 tag, =20 (LPDWORD)0, &type, =20 (LPBYTE)b, &sz);=20 if((ERROR_SUCCESS !=3D lrc) || (type !=3D REG_SZ)) { return JK_FALSE; =20 } =20 b[sz] =3D '\0'; return JK_TRUE; =20 } static int init_ws_service(isapi_private_data_t *private_data, jk_ws_service_t *s, char **worker_name)=20 { char huge_buf[16 * 1024]; /* should be enough for all */ DWORD huge_buf_sz; s->jvm_route =3D NULL; s->start_response =3D start_response; s->read =3D read; s->write =3D write; GET_SERVER_VARIABLE_VALUE(HTTP_WORKER_HEADER_NAME, (*worker_name)); = =20 GET_SERVER_VARIABLE_VALUE(HTTP_URI_HEADER_NAME, s->req_uri); =20 if(s->req_uri) { char *t =3D strchr(s->req_uri, '?'); if(t) { *t =3D '\0'; t++; if(!strlen(t)) { t =3D NULL; } } s->query_string =3D t; } else { s->query_string =3D private_data->lpEcb->lpszQueryString; *worker_name =3D JK_AJP12_WORKER_NAME; GET_SERVER_VARIABLE_VALUE("URL", s->req_uri); =20 } =20 GET_SERVER_VARIABLE_VALUE("AUTH_TYPE", s->auth_type); GET_SERVER_VARIABLE_VALUE("REMOTE_USER", s->remote_user); GET_SERVER_VARIABLE_VALUE("SERVER_PROTOCOL", s->protocol); GET_SERVER_VARIABLE_VALUE("REMOTE_HOST", s->remote_host); GET_SERVER_VARIABLE_VALUE("REMOTE_ADDR", s->remote_addr); GET_SERVER_VARIABLE_VALUE("SERVER_NAME", s->server_name); GET_SERVER_VARIABLE_VALUE_INT("SERVER_PORT", s->server_port, 80) GET_SERVER_VARIABLE_VALUE("SERVER_SOFTWARE", s->server_software); GET_SERVER_VARIABLE_VALUE_INT("SERVER_PORT_SECURE", s->is_ssl, 0); s->method =3D private_data->lpEcb->lpszMethod; s->content_length =3D private_data->lpEcb->cbTotalBytes; s->ssl_cert =3D NULL; s->ssl_cert_len =3D 0; s->ssl_cipher =3D NULL; s->ssl_session =3D NULL; s->headers_names =3D NULL; s->headers_values =3D NULL; s->num_headers =3D 0; =20 /* * Add SSL IIS environment */ if(s->is_ssl) { =20 char *ssl_env_names[9] =3D { "CERT_ISSUER",=20 "CERT_SUBJECT",=20 "CERT_COOKIE",=20 "HTTPS_SERVER_SUBJECT",=20 "CERT_FLAGS",=20 "HTTPS_SECRETKEYSIZE",=20 "CERT_SERIALNUMBER",=20 "HTTPS_SERVER_ISSUER",=20 "HTTPS_KEYSIZE" }; char *ssl_env_values[9] =3D { NULL,=20 NULL,=20 NULL,=20 NULL,=20 NULL,=20 NULL,=20 NULL,=20 NULL,=20 NULL }; unsigned i; unsigned num_of_vars =3D 0; for(i =3D 0 ; i < 9 ; i++) { GET_SERVER_VARIABLE_VALUE(ssl_env_names[i], = ssl_env_values[i]); if(ssl_env_values[i]) { num_of_vars++; } } if(num_of_vars) { unsigned j; s->attributes_names =3D=20 jk_pool_alloc(&private_data->p, num_of_vars * = sizeof(char *)); s->attributes_values =3D=20 jk_pool_alloc(&private_data->p, num_of_vars * = sizeof(char *)); j =3D 0; for(i =3D 0 ; i < 9 ; i++) { =20 if(ssl_env_values[i]) { s->attributes_names[j] =3D ssl_env_names[i]; s->attributes_values[j] =3D ssl_env_values[i]; j++; } } s->num_attributes =3D num_of_vars; } } huge_buf_sz =3D sizeof(huge_buf); =20 if(get_server_value(private_data->lpEcb, "ALL_HTTP", =20 huge_buf, =20 huge_buf_sz, =20 "")) { =20 unsigned cnt =3D 0; char *tmp; for(tmp =3D huge_buf ; *tmp ; tmp++) { if(*tmp =3D=3D '\n'){ cnt++; } } if(cnt) { char *headers_buf =3D jk_pool_strdup(&private_data->p, = huge_buf); unsigned i; unsigned len_of_http_prefix =3D strlen("HTTP_"); =20 cnt -=3D 2; /* For our two special headers */ s->headers_names =3D jk_pool_alloc(&private_data->p, cnt * = sizeof(char *)); s->headers_values =3D jk_pool_alloc(&private_data->p, cnt * = sizeof(char *)); if(!s->headers_names || !s->headers_values || !headers_buf) = { return JK_FALSE; } for(i =3D 0, tmp =3D headers_buf ; *tmp && i < cnt ; ) { int real_header =3D JK_TRUE; /* Skipp the HTTP_ prefix to the beginning of th header = name */ tmp +=3D len_of_http_prefix; if(!strnicmp(tmp, URI_HEADER_NAME, = strlen(URI_HEADER_NAME)) || !strnicmp(tmp, WORKER_HEADER_NAME, = strlen(WORKER_HEADER_NAME))) { real_header =3D JK_FALSE; } else { s->headers_names[i] =3D tmp; } while(':' !=3D *tmp && *tmp) { if('_' =3D=3D *tmp) { *tmp =3D '-'; } else { *tmp =3D tolower(*tmp); } tmp++; } *tmp =3D '\0'; tmp++; /* Skipp all the WS chars after the ':' to the beginning = of th header value */ while(' ' =3D=3D *tmp || '\t' =3D=3D *tmp || '\v' =3D=3D = *tmp) { tmp++; } if(real_header) { s->headers_values[i] =3D tmp; } =20 while(*tmp !=3D '\n' && *tmp !=3D '\r') { tmp++; } *tmp =3D '\0'; tmp++; /* skipp CR LF */ while(*tmp =3D=3D '\n' || *tmp =3D=3D '\r') { tmp++; } if(real_header) { i++; } } s->num_headers =3D cnt; } else { /* We must have our two headers */ return JK_FALSE; } } else { return JK_FALSE; } =20 return JK_TRUE; } static int get_server_value(LPEXTENSION_CONTROL_BLOCK lpEcb, char *name, char *buf, DWORD bufsz, char *def_val) { if(!lpEcb->GetServerVariable(lpEcb->ConnID,=20 name, buf, (LPDWORD)&bufsz)) { strcpy(buf, def_val); return JK_FALSE; } if(bufsz > 0) { buf[bufsz - 1] =3D '\0'; } return JK_TRUE; } ------=_NextPart_000_004D_01C0B60B.EE742B20--