diff options
Diffstat (limited to 'rubbos/app/tomcat-connectors-1.2.32-src/native/apache-2.0/mod_jk.c')
-rw-r--r-- | rubbos/app/tomcat-connectors-1.2.32-src/native/apache-2.0/mod_jk.c | 3748 |
1 files changed, 0 insertions, 3748 deletions
diff --git a/rubbos/app/tomcat-connectors-1.2.32-src/native/apache-2.0/mod_jk.c b/rubbos/app/tomcat-connectors-1.2.32-src/native/apache-2.0/mod_jk.c deleted file mode 100644 index 40f08e47..00000000 --- a/rubbos/app/tomcat-connectors-1.2.32-src/native/apache-2.0/mod_jk.c +++ /dev/null @@ -1,3748 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/*************************************************************************** - * Description: Apache 2 plugin for Tomcat * - * Author: Gal Shachor <shachor@il.ibm.com> * - * Henri Gomez <hgomez@apache.org> * - * Version: $Revision: 1126561 $ * - ***************************************************************************/ - -/* - * mod_jk: keeps all servlet related ramblings together. - */ - -#include "ap_config.h" -#include "apr_lib.h" -#include "apr_date.h" -#include "apr_file_info.h" -#include "apr_file_io.h" -#include "httpd.h" -#include "http_config.h" -#include "http_request.h" -#include "http_core.h" -#include "http_protocol.h" -#include "http_main.h" -#include "http_log.h" -#include "util_script.h" -#include "ap_mpm.h" - -#if defined(AS400) && !defined(AS400_UTF8) -#include "ap_charset.h" -#include "util_charset.h" /* ap_hdrs_from_ascii */ -#endif - -/* deprecated with apr 0.9.3 */ - -#include "apr_version.h" -#if (APR_MAJOR_VERSION == 0) && \ - (APR_MINOR_VERSION <= 9) && \ - (APR_PATCH_VERSION < 3) -#define apr_filepath_name_get apr_filename_of_pathname -#endif - -#include "apr_strings.h" - -/* Yes; sorta sucks - with luck we will clean this up before httpd-2.2 - * ships, leaving AP_NEED_SET_MUTEX_PERMS def'd as 1 or 0 on all platforms. - */ -#ifdef AP_NEED_SET_MUTEX_PERMS -# define JK_NEED_SET_MUTEX_PERMS AP_NEED_SET_MUTEX_PERMS -#else - /* A special case for httpd-2.0 */ -# if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE) && !defined(AS400) -# define JK_NEED_SET_MUTEX_PERMS 1 -# else -# define JK_NEED_SET_MUTEX_PERMS 0 -# endif -#endif - -#if JK_NEED_SET_MUTEX_PERMS -#include "unixd.h" /* for unixd_set_global_mutex_perms */ -#endif -/* - * jk_ include files - */ -#ifdef NETWARE -#define __sys_types_h__ -#define __sys_socket_h__ -#define __netdb_h__ -#define __netinet_in_h__ -#define __arpa_inet_h__ -#define __sys_timeval_h__ -#endif - -#include "jk_global.h" -#include "jk_ajp13.h" -#include "jk_logger.h" -#include "jk_map.h" -#include "jk_pool.h" -#include "jk_service.h" -#include "jk_uri_worker_map.h" -#include "jk_util.h" -#include "jk_worker.h" -#include "jk_shm.h" -#include "jk_url.h" - -#define JK_LOG_DEF_FILE ("logs/mod_jk.log") -#define JK_SHM_DEF_FILE ("logs/jk-runtime-status") -#define JK_ENV_REMOTE_ADDR ("JK_REMOTE_ADDR") -#define JK_ENV_REMOTE_PORT ("JK_REMOTE_PORT") -#define JK_ENV_REMOTE_HOST ("JK_REMOTE_HOST") -#define JK_ENV_REMOTE_USER ("JK_REMOTE_USER") -#define JK_ENV_AUTH_TYPE ("JK_AUTH_TYPE") -#define JK_ENV_LOCAL_NAME ("JK_LOCAL_NAME") -#define JK_ENV_LOCAL_PORT ("JK_LOCAL_PORT") -#define JK_ENV_HTTPS ("HTTPS") -#define JK_ENV_CERTS ("SSL_CLIENT_CERT") -#define JK_ENV_CIPHER ("SSL_CIPHER") -#define JK_ENV_SESSION ("SSL_SESSION_ID") -#define JK_ENV_KEY_SIZE ("SSL_CIPHER_USEKEYSIZE") -#define JK_ENV_CERTCHAIN_PREFIX ("SSL_CLIENT_CERT_CHAIN_") -#define JK_ENV_REPLY_TIMEOUT ("JK_REPLY_TIMEOUT") -#define JK_ENV_WORKER_NAME ("JK_WORKER_NAME") -#define JK_NOTE_WORKER_NAME ("JK_WORKER_NAME") -#define JK_NOTE_WORKER_TYPE ("JK_WORKER_TYPE") -#define JK_NOTE_REQUEST_DURATION ("JK_REQUEST_DURATION") -#define JK_NOTE_WORKER_ROUTE ("JK_WORKER_ROUTE") -#define JK_HANDLER ("jakarta-servlet") -#define JK_MAGIC_TYPE ("application/x-jakarta-servlet") -#define NULL_FOR_EMPTY(x) ((x && !strlen(x)) ? NULL : x) -#define STRNULL_FOR_NULL(x) ((x) ? (x) : "(null)") -#define JK_LOG_LOCK_KEY ("jk_log_lock_key") -#define JKLOG_MARK __FILE__,__LINE__ - -/* - * If you are not using SSL, comment out the following line. It will make - * apache run faster. - * - * Personally, I (DM), think this may be a lie. - */ -#define ADD_SSL_INFO - -/* Needed for Apache 2.3/2.4 per-module log config */ -#ifdef APLOG_USE_MODULE -APLOG_USE_MODULE(jk); -#endif - -/* module MODULE_VAR_EXPORT jk_module; */ -AP_MODULE_DECLARE_DATA module jk_module; - -/* - * Environment variable forward object - */ -typedef struct -{ - int has_default; - char *name; - char *value; -} envvar_item; - -/* - * Configuration object for the mod_jk module. - */ -typedef struct -{ - - /* - * Log stuff - */ - char *log_file; - int log_level; - jk_logger_t *log; - apr_file_t *jklogfp; - - /* - * Mount stuff - */ - char *mount_file; - int mount_file_reload; - jk_map_t *uri_to_context; - - int mountcopy; - - jk_uri_worker_map_t *uw_map; - - int was_initialized; - - /* - * Automatic context path apache alias - */ - char *alias_dir; - - /* - * Request Logging - */ - - char *stamp_format_string; - char *format_string; - apr_array_header_t *format; - - /* - * Setting target worker via environment - */ - char *worker_indicator; - - /* - * Configurable environment variables to overwrite - * request information using meta data send by a - * proxy in front of us. - */ - char *remote_addr_indicator; - char *remote_port_indicator; - char *remote_host_indicator; - char *remote_user_indicator; - char *auth_type_indicator; - char *local_name_indicator; - char *local_port_indicator; - - /* - * SSL Support - */ - int ssl_enable; - char *https_indicator; - char *certs_indicator; - char *cipher_indicator; - char *session_indicator; /* Servlet API 2.3 requirement */ - char *key_size_indicator; /* Servlet API 2.3 requirement */ - char *certchain_prefix; /* Client certificate chain prefix */ - - /* - * Jk Options - */ - int options; - int exclude_options; - - int strip_session; - char *strip_session_name; - /* - * Environment variables support - */ - int envvars_has_own; - apr_table_t *envvars; - apr_table_t *envvars_def; - apr_array_header_t *envvar_items; - - server_rec *s; -} jk_server_conf_t; - -struct apache_private_data -{ - jk_pool_t p; - - int read_body_started; - request_rec *r; -}; -typedef struct apache_private_data apache_private_data_t; - -static server_rec *main_server = NULL; -static jk_logger_t *main_log = NULL; -static apr_hash_t *jk_log_fps = NULL; -static jk_worker_env_t worker_env; -static apr_global_mutex_t *jk_log_lock = NULL; -static char *jk_shm_file = NULL; -static size_t jk_shm_size = 0; -static int jk_shm_size_set = 0; -static volatile int jk_watchdog_interval = 0; -static volatile int jk_watchdog_running = 0; - -/* - * Worker stuff -*/ -static jk_map_t *jk_worker_properties = NULL; -static char *jk_worker_file = NULL; -static int jk_mount_copy_all = JK_FALSE; - -static int JK_METHOD ws_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 ws_read(jk_ws_service_t *s, - void *b, unsigned len, unsigned *actually_read); - -static int init_jk(apr_pool_t * pconf, jk_server_conf_t * conf, - server_rec * s); - -static int JK_METHOD ws_write(jk_ws_service_t *s, const void *b, unsigned l); - -static void JK_METHOD ws_add_log_items(jk_ws_service_t *s, - const char *const *log_names, - const char *const *log_values, - unsigned num_of_log_items); - -static void * JK_METHOD ws_next_vhost(void *d); - -static void JK_METHOD ws_vhost_to_text(void *d, char *buf, size_t len); - -static jk_uri_worker_map_t * JK_METHOD ws_vhost_to_uw_map(void *d); - -/* ========================================================================= */ -/* JK Service step callbacks */ -/* ========================================================================= */ - -static int JK_METHOD ws_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) -{ - unsigned h; - apache_private_data_t *p = s->ws_private; - request_rec *r = p->r; - - /* If we use proxy error pages, still pass - * through context headers needed for special status codes. - */ - if (s->extension.use_server_error_pages && - status >= s->extension.use_server_error_pages) { - if (status == HTTP_UNAUTHORIZED) { - int found = JK_FALSE; - for (h = 0; h < num_of_headers; h++) { - if (!strcasecmp(header_names[h], "WWW-Authenticate")) { - char *tmp = apr_pstrdup(r->pool, header_values[h]); - apr_table_set(r->err_headers_out, - "WWW-Authenticate", tmp); - found = JK_TRUE; - } - } - if (found == JK_FALSE) { - jk_server_conf_t *xconf = (jk_server_conf_t *) - ap_get_module_config(r->server->module_config, - &jk_module); - jk_log(xconf->log, JK_LOG_INFO, - "origin server sent 401 without" - " WWW-Authenticate header"); - } - } - return JK_TRUE; - } - - /* If there is no reason given (or an empty one), - * we'll try to guess a good one. - */ - if (!reason || *reason == '\0') { - /* We ask Apache httpd about a good reason phrase. */ - reason = ap_get_status_line(status); - /* Unfortunately it returns with a 500 reason phrase, - * whenever it does not know about the given status code, - * e.g. in the case of custom status codes. - */ - if (status != 500 && !strncmp(reason, "500 ", 4)) { - reason = "Unknown Reason"; - } else { - /* Apache httpd returns a full status line, - * but we only want a reason phrase, so skip - * the prepended status code. - */ - reason = reason + 4; - } - } - r->status = status; - r->status_line = apr_psprintf(r->pool, "%d %s", status, reason); - - for (h = 0; h < num_of_headers; h++) { - if (!strcasecmp(header_names[h], "Content-type")) { - char *tmp = apr_pstrdup(r->pool, header_values[h]); - ap_content_type_tolower(tmp); - /* It should be done like this in Apache 2.0 */ - /* This way, Apache 2.0 will be able to set the output filter */ - /* and it make jk useable with deflate using */ - /* AddOutputFilterByType DEFLATE text/html */ - ap_set_content_type(r, tmp); - } - else if (!strcasecmp(header_names[h], "Location")) { -#if defined(AS400) && !defined(AS400_UTF8) - /* Fix escapes in Location Header URL */ - ap_fixup_escapes((char *)header_values[h], - strlen(header_values[h]), ap_hdrs_from_ascii); -#endif - apr_table_set(r->headers_out, header_names[h], header_values[h]); - } - else if (!strcasecmp(header_names[h], "Content-Length")) { - apr_table_set(r->headers_out, header_names[h], header_values[h]); - } - else if (!strcasecmp(header_names[h], "Transfer-Encoding")) { - apr_table_set(r->headers_out, header_names[h], header_values[h]); - } - else if (!strcasecmp(header_names[h], "Last-Modified")) { - /* - * If the script gave us a Last-Modified header, we can't just - * pass it on blindly because of restrictions on future values. - */ - ap_update_mtime(r, apr_date_parse_http(header_values[h])); - ap_set_last_modified(r); - } - else { - apr_table_add(r->headers_out, header_names[h], header_values[h]); - } - } - - /* this NOP function was removed in apache 2.0 alpha14 */ - /* ap_send_http_header(r); */ - s->response_started = JK_TRUE; - - return JK_TRUE; -} - -/* - * Read a chunk of the request body into a buffer. Attempt to read len - * bytes into the buffer. Write the number of bytes actually read into - * actually_read. - * - * Think of this function as a method of the apache1.3-specific subclass of - * the jk_ws_service class. Think of the *s param as a "this" or "self" - * pointer. - */ -static int JK_METHOD ws_read(jk_ws_service_t *s, - void *b, unsigned len, unsigned *actually_read) -{ - if (s && s->ws_private && b && actually_read) { - apache_private_data_t *p = s->ws_private; - if (!p->read_body_started) { - if (ap_should_client_block(p->r)) { - p->read_body_started = JK_TRUE; - } - } - - if (p->read_body_started) { -#if defined(AS400) && !defined(AS400_UTF8) - int long rv = OK; - if (rv = ap_change_request_body_xlate(p->r, 65535, 65535)) { /* turn off request body translation */ - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_CRIT, 0, NULL, - "mod_jk: Error on ap_change_request_body_xlate, rc=%d", - rv); - return JK_FALSE; - } -#else - long rv; -#endif - - if ((rv = ap_get_client_block(p->r, b, len)) < 0) { - *actually_read = 0; - } - else { - *actually_read = (unsigned)rv; - } - return JK_TRUE; - } - } - return JK_FALSE; -} - -static void JK_METHOD ws_flush(jk_ws_service_t *s) -{ -#if ! (defined(AS400) && !defined(AS400_UTF8)) - if (s && s->ws_private) { - apache_private_data_t *p = s->ws_private; - ap_rflush(p->r); - } -#endif -} - -static void JK_METHOD ws_done(jk_ws_service_t *s) -{ -#if ! (defined(AS400) && !defined(AS400_UTF8)) - if (s && s->ws_private) { - apache_private_data_t *p = s->ws_private; - ap_finalize_request_protocol(p->r); - } -#endif -} - -/* - * Write a chunk of response data back to the browser. If the headers - * haven't yet been sent over, send over default header values (Status = - * 200, basically). - * - * Write len bytes from buffer b. - * - * Think of this function as a method of the apache1.3-specific subclass of - * the jk_ws_service class. Think of the *s param as a "this" or "self" - * pointer. - */ -/* Works with 4096, fails with 8192 */ -#ifndef CHUNK_SIZE -#define CHUNK_SIZE 4096 -#endif - -static int JK_METHOD ws_write(jk_ws_service_t *s, const void *b, unsigned int l) -{ -#if defined(AS400) && !defined(AS400_UTF8) - int rc; -#endif - - if (s && s->ws_private && b) { - apache_private_data_t *p = s->ws_private; - - if (l) { - /* BUFF *bf = p->r->connection->client; */ - int r = 0; - int ll = l; - const char *bb = (const char *)b; - - if (!s->response_started) { - if (main_log) - jk_log(main_log, JK_LOG_INFO, - "Write without start, starting with defaults"); - if (!s->start_response(s, 200, NULL, NULL, NULL, 0)) { - return JK_FALSE; - } - } - if (p->r->header_only) { -#if ! (defined(AS400) && !defined(AS400_UTF8)) - ap_rflush(p->r); -#endif - return JK_TRUE; - } -#if defined(AS400) && !defined(AS400_UTF8) - /* turn off response body translation */ - rc = ap_change_response_body_xlate(p->r, 65535, 65535); - if (rc) { - ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_CRIT, 0, NULL, - "mod_jk: Error on ap_change_response_body_xlate, rc=%d", - rc); - return JK_FALSE; - } -#endif - - while (ll > 0 && !p->r->connection->aborted) { -#if 0 - /* Apache 2 output filter does not write - * directly to the wire. - */ - int toSend = (ll > CHUNK_SIZE) ? CHUNK_SIZE : ll; - r = ap_rwrite(bb, toSend, p->r); -#else - r = ap_rwrite(bb, ll, p->r); -#endif - if (JK_IS_DEBUG_LEVEL(main_log)) - jk_log(main_log, JK_LOG_DEBUG, - "written %d out of %d", r, ll); - - if (r < 0) - return JK_FALSE; - ll -= r; - bb += r; - } - if (ll && p->r->connection->aborted) { - /* Fail if there is something left to send and - * the connection was aborted by the client - */ - return JK_FALSE; - } - } - - return JK_TRUE; - } - return JK_FALSE; -} - -static void JK_METHOD ws_add_log_items(jk_ws_service_t *s, - const char *const *log_names, - const char *const *log_values, - unsigned num_of_log_items) -{ - unsigned h; - apache_private_data_t *p = s->ws_private; - request_rec *r = p->r; - - for (h = 0; h < num_of_log_items; h++) { - if (log_names[h] && log_values[h]) { - apr_table_setn(r->notes, log_names[h], log_values[h]); - } - } -} - -static void * JK_METHOD ws_next_vhost(void *d) -{ - server_rec *s = (server_rec *)d; - if (s == NULL) - return main_server; - return s->next; -} - -static void JK_METHOD ws_vhost_to_text(void *d, char *buf, size_t len) -{ - server_rec *s = (server_rec *)d; - size_t used = 0; - - if (s->server_hostname) - used += strlen(s->server_hostname); - if (!s->is_virtual) { - if (s->port) - used += strlen(":XXXXX"); - } - else if (s->addrs) { - used += strlen(" ["); - if (s->addrs->virthost) - used += strlen(s->addrs->virthost); - if (s->addrs->host_port) - used += strlen(":XXXXX"); - used += strlen("]"); - } - - if (len < used && len > strlen("XXX")) { - strcpy(buf, "XXX"); - return; - } - - used = 0; - - if (s->server_hostname) { - strcpy(buf + used, s->server_hostname); - used += strlen(s->server_hostname); - } - if (!s->is_virtual) { - if (s->port) { - sprintf(buf + used, ":%hu", s->port); - used = strlen(buf); - } - } - else if (s->addrs) { - strcpy(buf + used, " ["); - used += strlen(" ["); - if (s->addrs->virthost) { - strcpy(buf + used, s->addrs->virthost); - used += strlen(s->addrs->virthost); - } - if (s->addrs->host_port) { - sprintf(buf + used, ":%hu", s->addrs->host_port); - used = strlen(buf); - } - strcpy(buf + used, "]"); - used += strlen("]"); - } -} - -static jk_uri_worker_map_t * JK_METHOD ws_vhost_to_uw_map(void *d) -{ - server_rec *s = (server_rec *)d; - jk_server_conf_t *conf = NULL; - if (s == NULL) - return NULL; - conf = (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - return conf->uw_map; -} - -/* ========================================================================= */ -/* Utility functions */ -/* ========================================================================= */ - -/* ========================================================================= */ -/* Log something to Jk log file then exit */ -static void jk_error_exit(const char *file, - int line, - int level, - const server_rec * s, - apr_pool_t * p, const char *fmt, ...) -{ - va_list ap; - char *res; - char *ch; - - va_start(ap, fmt); - res = apr_pvsprintf(s->process->pool, fmt, ap); - va_end(ap); - /* Replace all format characters in the resulting message */ - /* because we feed the message to ap_log_error(). */ - ch = res; - while (*ch) { - if (*ch == '%') { - *ch = '#'; - } - ch++; - } - -#if (MODULE_MAGIC_NUMBER_MAJOR >= 20100606) - ap_log_error(file, line, APLOG_MODULE_INDEX, level, 0, s, res); -#else - ap_log_error(file, line, level, 0, s, res); -#endif - if ( s ) { -#if (MODULE_MAGIC_NUMBER_MAJOR >= 20100606) - ap_log_error(file, line, APLOG_MODULE_INDEX, level, 0, NULL, res); -#else - ap_log_error(file, line, level, 0, NULL, res); -#endif - } - - /* Exit process */ - exit(1); -} - -static jk_uint64_t get_content_length(request_rec * r) -{ - if (r->clength > 0) { - return (jk_uint64_t)r->clength; - } - else if (r->main == NULL || r->main == r) { - char *lenp = (char *)apr_table_get(r->headers_in, "Content-Length"); - - if (lenp) { - jk_uint64_t rc = 0; - if (sscanf(lenp, "%" JK_UINT64_T_FMT, &rc) > 0 && rc > 0) { - return rc; - } - } - } - - return 0; -} - -/* Retrieve string value from env var, use default if env var does not exist. */ -static const char *get_env_string(request_rec *r, const char *def, - char *env, int null_for_empty) -{ - char *value = (char *)apr_table_get(r->subprocess_env, env); - if (value) - return null_for_empty ? NULL_FOR_EMPTY(value) : value; - return null_for_empty ? NULL_FOR_EMPTY(def) : def; -} - -/* Retrieve integer value from env var, use default if env var does not exist. */ -static int get_env_int(request_rec *r, int def, char *env) -{ - char *value = (char *)apr_table_get(r->subprocess_env, env); - if (value) - return atoi(value); - return def; -} - -static int init_ws_service(apache_private_data_t * private_data, - jk_ws_service_t *s, jk_server_conf_t * conf) -{ - int size; - request_rec *r = private_data->r; - char *ssl_temp = NULL; - const char *reply_timeout = NULL; - rule_extension_t *e; - - /* Copy in function pointers (which are really methods) */ - s->start_response = ws_start_response; - s->read = ws_read; - s->write = ws_write; - s->flush = ws_flush; - s->done = ws_done; - s->add_log_items = ws_add_log_items; - s->next_vhost = ws_next_vhost; - s->vhost_to_text = ws_vhost_to_text; - s->vhost_to_uw_map = ws_vhost_to_uw_map; - - s->auth_type = get_env_string(r, r->ap_auth_type, - conf->auth_type_indicator, 1); - s->remote_user = get_env_string(r, r->user, - conf->remote_user_indicator, 1); - - s->protocol = r->protocol; - s->remote_host = (char *)ap_get_remote_host(r->connection, - r->per_dir_config, - REMOTE_HOST, NULL); - s->remote_host = get_env_string(r, s->remote_host, - conf->remote_host_indicator, 1); - if (conf->options & JK_OPT_FWDLOCAL) { - s->remote_addr = r->connection->local_ip; - /* We don't know the client port of the backend connection. */ - s->remote_port = "0"; - } - else { - s->remote_addr = r->connection->remote_ip; - s->remote_port = apr_itoa(r->pool, r->connection->remote_addr->port); - } - s->remote_addr = get_env_string(r, s->remote_addr, - conf->remote_addr_indicator, 1); - s->remote_port = get_env_string(r, s->remote_port, - conf->remote_port_indicator, 1); - - if (conf->options & JK_OPT_FLUSHPACKETS) - s->flush_packets = 1; - if (conf->options & JK_OPT_FLUSHEADER) - s->flush_header = 1; - - e = (rule_extension_t *)ap_get_module_config(r->request_config, &jk_module); - if (e) { - s->extension.reply_timeout = e->reply_timeout; - s->extension.use_server_error_pages = e->use_server_error_pages; - if (e->activation) { - s->extension.activation = apr_palloc(r->pool, e->activation_size * sizeof(int)); - memcpy(s->extension.activation, e->activation, e->activation_size * sizeof(int)); - } - if (e->fail_on_status_size > 0) { - s->extension.fail_on_status_size = e->fail_on_status_size; - s->extension.fail_on_status = apr_palloc(r->pool, e->fail_on_status_size * sizeof(int)); - memcpy(s->extension.fail_on_status, e->fail_on_status, e->fail_on_status_size * sizeof(int)); - } - } - reply_timeout = apr_table_get(r->subprocess_env, "JK_REPLY_TIMEOUT"); - if (reply_timeout) { - int r = atoi(reply_timeout); - if (r >= 0) - s->extension.reply_timeout = r; - } - - if (conf->options & JK_OPT_DISABLEREUSE) - s->disable_reuse = 1; - - /* get server name */ - s->server_name = get_env_string(r, (char *)ap_get_server_name(r), - conf->local_name_indicator, 0); - - /* get the real port (otherwise redirect failed) */ - /* XXX: use apache API for getting server port - * - * Pre 1.2.7 versions used: - * s->server_port = r->connection->local_addr->port; - */ - s->server_port = get_env_int(r, ap_get_server_port(r), - conf->local_port_indicator); - -#if ((AP_MODULE_MAGIC_AT_LEAST(20051115,4)) && !defined(API_COMPATIBILITY)) || (MODULE_MAGIC_NUMBER_MAJOR >= 20060905) - s->server_software = (char *)ap_get_server_description(); -#else - s->server_software = (char *)ap_get_server_version(); -#endif - s->method = (char *)r->method; - s->content_length = get_content_length(r); - s->is_chunked = r->read_chunked; - s->no_more_chunks = 0; -#if defined(AS400) && !defined(AS400_UTF8) - /* Get the query string that is not translated to EBCDIC */ - s->query_string = ap_get_original_query_string(r); -#else - s->query_string = r->args; -#endif - - /* - * The 2.2 servlet spec errata says the uri from - * HttpServletRequest.getRequestURI() should remain encoded. - * [http://java.sun.com/products/servlet/errata_042700.html] - * - * We use JkOptions to determine which method to be used - * - * ap_escape_uri is the latest recommanded but require - * some java decoding (in TC 3.3 rc2) - * - * unparsed_uri is used for strict compliance with spec and - * old Tomcat (3.2.3 for example) - * - * uri is use for compatibilty with mod_rewrite with old Tomcats - */ - - switch (conf->options & JK_OPT_FWDURIMASK) { - - case JK_OPT_FWDURICOMPATUNPARSED: - s->req_uri = r->unparsed_uri; - if (s->req_uri != NULL) { - char *query_str = strchr(s->req_uri, '?'); - if (query_str != NULL) { - *query_str = 0; - } - } - - break; - - case JK_OPT_FWDURICOMPAT: - s->req_uri = r->uri; - break; - - case JK_OPT_FWDURIPROXY: - size = 3 * strlen(r->uri) + 1; - s->req_uri = apr_palloc(r->pool, size); - jk_canonenc(r->uri, s->req_uri, size); - break; - - case JK_OPT_FWDURIESCAPED: - s->req_uri = ap_escape_uri(r->pool, r->uri); - break; - - default: - return JK_FALSE; - } - - if (conf->ssl_enable || conf->envvars) { - ap_add_common_vars(r); - - if (conf->ssl_enable) { - ssl_temp = - (char *)apr_table_get(r->subprocess_env, - conf->https_indicator); - if (ssl_temp && !strcasecmp(ssl_temp, "on")) { - s->is_ssl = JK_TRUE; - s->ssl_cert = - (char *)apr_table_get(r->subprocess_env, - conf->certs_indicator); - - if (conf->options & JK_OPT_FWDCERTCHAIN) { - const apr_array_header_t *t = apr_table_elts(r->subprocess_env); - if (t && t->nelts) { - int i; - const apr_table_entry_t *elts = (const apr_table_entry_t *) t->elts; - apr_array_header_t *certs = apr_array_make(r->pool, 1, sizeof(char *)); - *(const char **)apr_array_push(certs) = s->ssl_cert; - for (i = 0; i < t->nelts; i++) { - if (!elts[i].key) - continue; - if (!strncasecmp(elts[i].key, conf->certchain_prefix, - strlen(conf->certchain_prefix))) - *(const char **)apr_array_push(certs) = elts[i].val; - } - s->ssl_cert = apr_array_pstrcat(r->pool, certs, '\0'); - } - } - - if (s->ssl_cert) { - s->ssl_cert_len = strlen(s->ssl_cert); - if (JK_IS_DEBUG_LEVEL(conf->log)) { - jk_log(conf->log, JK_LOG_DEBUG, - "SSL client certificate (%d bytes): %s", - s->ssl_cert_len, s->ssl_cert); - } - } - /* Servlet 2.3 API */ - s->ssl_cipher = - (char *)apr_table_get(r->subprocess_env, - conf->cipher_indicator); - s->ssl_session = - (char *)apr_table_get(r->subprocess_env, - conf->session_indicator); - - if (conf->options & JK_OPT_FWDKEYSIZE) { - /* Servlet 2.3 API */ - ssl_temp = (char *)apr_table_get(r->subprocess_env, - conf-> - key_size_indicator); - if (ssl_temp) - s->ssl_key_size = atoi(ssl_temp); - } - - - } - } - - if (conf->envvars) { - const apr_array_header_t *t = conf->envvar_items; - if (t && t->nelts) { - int i; - int j = 0; - envvar_item *elts = (envvar_item *) t->elts; - s->attributes_names = apr_palloc(r->pool, - sizeof(char *) * t->nelts); - s->attributes_values = apr_palloc(r->pool, - sizeof(char *) * t->nelts); - - for (i = 0; i < t->nelts; i++) { - s->attributes_names[i - j] = elts[i].name; - s->attributes_values[i - j] = - (char *)apr_table_get(r->subprocess_env, elts[i].name); - if (!s->attributes_values[i - j]) { - if (elts[i].has_default) { - s->attributes_values[i - j] = elts[i].value; - } - else { - s->attributes_values[i - j] = ""; - s->attributes_names[i - j] = ""; - j++; - } - } - } - - s->num_attributes = t->nelts - j; - } - } - } - - if (r->headers_in && apr_table_elts(r->headers_in)) { - int need_content_length_header = (!s->is_chunked - && s->content_length == - 0) ? JK_TRUE : JK_FALSE; - const apr_array_header_t *t = apr_table_elts(r->headers_in); - if (t && t->nelts) { - int i; - apr_table_entry_t *elts = (apr_table_entry_t *) t->elts; - s->num_headers = t->nelts; - /* allocate an extra header slot in case we need to add a content-length header */ - s->headers_names = - apr_palloc(r->pool, sizeof(char *) * (t->nelts + 1)); - s->headers_values = - apr_palloc(r->pool, sizeof(char *) * (t->nelts + 1)); - if (!s->headers_names || !s->headers_values) - return JK_FALSE; - for (i = 0; i < t->nelts; i++) { - char *hname = apr_pstrdup(r->pool, elts[i].key); - s->headers_values[i] = apr_pstrdup(r->pool, elts[i].val); - s->headers_names[i] = hname; - if (need_content_length_header && - !strcasecmp(s->headers_names[i], "content-length")) { - need_content_length_header = JK_FALSE; - } - } - /* Add a content-length = 0 header if needed. - * Ajp13 assumes an absent content-length header means an unknown, - * but non-zero length body. - */ - if (need_content_length_header) { - s->headers_names[s->num_headers] = "content-length"; - s->headers_values[s->num_headers] = "0"; - s->num_headers++; - } - } - /* Add a content-length = 0 header if needed. */ - else if (need_content_length_header) { - s->headers_names = apr_palloc(r->pool, sizeof(char *)); - s->headers_values = apr_palloc(r->pool, sizeof(char *)); - if (!s->headers_names || !s->headers_values) - return JK_FALSE; - s->headers_names[0] = "content-length"; - s->headers_values[0] = "0"; - s->num_headers++; - } - } - s->uw_map = conf->uw_map; - - /* Dump all connection param so we can trace what's going to - * the remote tomcat - */ - if (JK_IS_DEBUG_LEVEL(conf->log)) { - jk_log(conf->log, JK_LOG_DEBUG, - "Service protocol=%s method=%s ssl=%s host=%s addr=%s name=%s port=%d auth=%s user=%s laddr=%s raddr=%s uri=%s", - STRNULL_FOR_NULL(s->protocol), - STRNULL_FOR_NULL(s->method), - s->is_ssl ? "true" : "false", - STRNULL_FOR_NULL(s->remote_host), - STRNULL_FOR_NULL(s->remote_addr), - STRNULL_FOR_NULL(s->server_name), - s->server_port, - STRNULL_FOR_NULL(s->auth_type), - STRNULL_FOR_NULL(s->remote_user), - STRNULL_FOR_NULL(r->connection->local_ip), - STRNULL_FOR_NULL(r->connection->remote_ip), - STRNULL_FOR_NULL(s->req_uri)); - } - - return JK_TRUE; -} - -/* - * The JK module command processors - * - * The below are all installed so that Apache calls them while it is - * processing its config files. This allows configuration info to be - * copied into a jk_server_conf_t object, which is then used for request - * filtering/processing. - * - * See jk_cmds definition below for explanations of these options. - */ - -/* - * JkMountCopy directive handling - * - * JkMountCopy On/Off/All - */ - -static const char *jk_set_mountcopy(cmd_parms * cmd, - void *dummy, const char *mount_copy) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - if (! strcasecmp(mount_copy, "all")) { - const char *err_string = ap_check_cmd_context(cmd, GLOBAL_ONLY); - if (err_string != NULL) { - return err_string; - } - jk_mount_copy_all = JK_TRUE; - } - else if (strcasecmp(mount_copy, "on") && strcasecmp(mount_copy, "off")) { - return "JkMountCopy must be All, On or Off"; - } - else { - conf->mountcopy = strcasecmp(mount_copy, "off") ? JK_TRUE : JK_FALSE; - } - - return NULL; -} - -/* - * JkMount directive handling - * - * JkMount URI(context) worker - */ - -static const char *jk_mount_context(cmd_parms * cmd, - void *dummy, - const char *context, - const char *worker) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - const char *c, *w; - - if (worker != NULL && cmd->path == NULL ) { - c = context; - w = worker; - } - else if (worker == NULL && cmd->path != NULL) { - c = cmd->path; - w = context; - } - else { - if (worker == NULL) - return "JkMount needs a path when not defined in a location"; - else - return "JkMount can not have a path when defined in a location"; - } - - if (c[0] != '/') - return "JkMount context should start with /"; - - if (!conf->uri_to_context) { - if (!jk_map_alloc(&(conf->uri_to_context))) { - return "JkMount Memory error"; - } - } - /* - * Add the new worker to the alias map. - */ - jk_map_put(conf->uri_to_context, c, w, NULL); - return NULL; -} - -/* - * JkUnMount directive handling - * - * JkUnMount URI(context) worker - */ - -static const char *jk_unmount_context(cmd_parms * cmd, - void *dummy, - const char *context, - const char *worker) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - char *uri; - const char *c, *w; - - if (worker != NULL && cmd->path == NULL ) { - c = context; - w = worker; - } - else if (worker == NULL && cmd->path != NULL) { - c = cmd->path; - w = context; - } - else { - if (worker == NULL) - return "JkUnMount needs a path when not defined in a location"; - else - return "JkUnMount can not have a path when defined in a location"; - } - - if (c[0] != '/') - return "JkUnMount context should start with /"; - - uri = apr_pstrcat(cmd->temp_pool, "!", c, NULL); - - if (!conf->uri_to_context) { - if (!jk_map_alloc(&(conf->uri_to_context))) { - return "JkUnMount Memory error"; - } - } - /* - * Add the new worker to the alias map. - */ - jk_map_put(conf->uri_to_context, uri, w, NULL); - return NULL; -} - - -/* - * JkWorkersFile Directive Handling - * - * JkWorkersFile file - */ - -static const char *jk_set_worker_file(cmd_parms * cmd, - void *dummy, const char *worker_file) -{ - const char *err_string = ap_check_cmd_context(cmd, GLOBAL_ONLY); - if (err_string != NULL) { - return err_string; - } - - if (jk_worker_file != NULL) - return "JkWorkersFile only allowed once"; - - /* we need an absolute path (ap_server_root_relative does the ap_pstrdup) */ - jk_worker_file = ap_server_root_relative(cmd->pool, worker_file); - - if (jk_worker_file == NULL) - return "JkWorkersFile file name invalid"; - - if (jk_file_exists(jk_worker_file) != JK_TRUE) - return "JkWorkersFile: Can't find the workers file specified"; - - return NULL; -} - -/* - * JkMountFile Directive Handling - * - * JkMountFile file - */ - -static const char *jk_set_mount_file(cmd_parms * cmd, - void *dummy, const char *mount_file) -{ - server_rec *s = cmd->server; - - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - /* we need an absolute path (ap_server_root_relative does the ap_pstrdup) */ - conf->mount_file = ap_server_root_relative(cmd->pool, mount_file); - - if (conf->mount_file == NULL) - return "JkMountFile file name invalid"; - - if (jk_file_exists(conf->mount_file) != JK_TRUE) - return "JkMountFile: Can't find the mount file specified"; - - if (!conf->uri_to_context) { - if (!jk_map_alloc(&(conf->uri_to_context))) { - return "JkMountFile Memory error"; - } - } - - return NULL; -} - -/* - * JkMountFileReload Directive Handling - * - * JkMountFileReload seconds - */ - -static const char *jk_set_mount_file_reload(cmd_parms * cmd, - void *dummy, const char *mount_file_reload) -{ - server_rec *s = cmd->server; - int interval; - - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - interval = atoi(mount_file_reload); - if (interval < 0) { - interval = 0; - } - - conf->mount_file_reload = interval; - - return NULL; -} - -/* - * JkWatchdogInterval Directive Handling - * - * JkWatchdogInterval seconds - */ - -static const char *jk_set_watchdog_interval(cmd_parms * cmd, - void *dummy, const char *watchdog_interval) -{ - const char *err_string = ap_check_cmd_context(cmd, GLOBAL_ONLY); - if (err_string != NULL) { - return err_string; - } - -#if APR_HAS_THREADS - jk_watchdog_interval = atoi(watchdog_interval); - if (jk_watchdog_interval < 0) { - jk_watchdog_interval = 0; - } - return NULL; -#else - return "JkWatchdogInterval: APR was compiled without threading support. Cannot create watchdog thread"; -#endif -} - -/* - * JkLogFile Directive Handling - * - * JkLogFile file - */ - -static const char *jk_set_log_file(cmd_parms * cmd, - void *dummy, const char *log_file) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - /* we need an absolute path */ - if (*log_file != '|') - conf->log_file = ap_server_root_relative(cmd->pool, log_file); - else - conf->log_file = apr_pstrdup(cmd->pool, log_file); - - if (conf->log_file == NULL) - return "JkLogFile file name invalid"; - - return NULL; -} - -/* - * JkShmFile Directive Handling - * - * JkShmFile file - */ - -static const char *jk_set_shm_file(cmd_parms * cmd, - void *dummy, const char *shm_file) -{ - const char *err_string = ap_check_cmd_context(cmd, GLOBAL_ONLY); - if (err_string != NULL) { - return err_string; - } - - /* we need an absolute path */ - jk_shm_file = ap_server_root_relative(cmd->pool, shm_file); - if (jk_shm_file == NULL) - return "JkShmFile file name invalid"; - - return NULL; -} - -/* - * JkShmSize Directive Handling - * - * JkShmSize size in kilobytes - */ - -static const char *jk_set_shm_size(cmd_parms * cmd, - void *dummy, const char *shm_size) -{ - int sz = 0; - const char *err_string = ap_check_cmd_context(cmd, GLOBAL_ONLY); - if (err_string != NULL) { - return err_string; - } - - sz = atoi(shm_size) * 1024; - if (sz < JK_SHM_DEF_SIZE) - sz = JK_SHM_DEF_SIZE; - else - sz = JK_SHM_ALIGN(sz); - jk_shm_size = (size_t)sz; - if (jk_shm_size) - jk_shm_size_set = 1; - return NULL; -} - -/* - * JkLogLevel Directive Handling - * - * JkLogLevel debug/info/error/emerg - */ - -static const char *jk_set_log_level(cmd_parms * cmd, - void *dummy, const char *log_level) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - conf->log_level = jk_parse_log_level(log_level); - - return NULL; -} - -/* - * JkLogStampFormat Directive Handling - * - * JkLogStampFormat "[%a %b %d %H:%M:%S %Y] " - */ - -static const char *jk_set_log_fmt(cmd_parms * cmd, - void *dummy, const char *log_format) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - conf->stamp_format_string = apr_pstrdup(cmd->pool, log_format); - - return NULL; -} - - -/* - * JkAutoAlias Directive Handling - * - * JkAutoAlias application directory - */ - -static const char *jk_set_auto_alias(cmd_parms * cmd, - void *dummy, const char *directory) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - conf->alias_dir = apr_pstrdup(cmd->pool, directory); - - if (conf->alias_dir == NULL) - return "JkAutoAlias directory invalid"; - - return NULL; -} - -/* - * JkStripSession directive handling - * - * JkStripSession On/Off [session path identifier] - */ - -static const char *jk_set_strip_session(cmd_parms * cmd, void *dummy, - const char *flag, const char *name) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - if (strcasecmp(flag, "on") && strcasecmp(flag, "off")) { - return "JkStripSession must be On or Off"; - } - else { - conf->strip_session = strcasecmp(flag, "off") ? JK_TRUE : JK_FALSE; - } - - /* Check for optional path value */ - if (name) - conf->strip_session_name = apr_pstrdup(cmd->pool, name); - else - conf->strip_session_name = apr_pstrdup(cmd->pool, JK_PATH_SESSION_IDENTIFIER); - - return NULL; -} - -/***************************************************************** - * - * Actually logging. - */ - -typedef const char *(*item_key_func) (request_rec *, char *); - -typedef struct -{ - item_key_func func; - char *arg; -} request_log_format_item; - -static const char *process_item(request_rec * r, - request_log_format_item * item) -{ - const char *cp; - - cp = (*item->func) (r, item->arg); - return cp ? cp : "-"; -} - -static void request_log_transaction(request_rec * r, jk_server_conf_t * conf) -{ - request_log_format_item *items; - char *str, *s; - int i; - int len = 0; - const char **strs; - int *strl; - apr_array_header_t *format = conf->format; - - strs = apr_palloc(r->pool, sizeof(char *) * (format->nelts)); - strl = apr_palloc(r->pool, sizeof(int) * (format->nelts)); - items = (request_log_format_item *) format->elts; - for (i = 0; i < format->nelts; ++i) { - strs[i] = process_item(r, &items[i]); - } - for (i = 0; i < format->nelts; ++i) { - len += strl[i] = strlen(strs[i]); - } - str = apr_palloc(r->pool, len + 1); - for (i = 0, s = str; i < format->nelts; ++i) { - memcpy(s, strs[i], strl[i]); - s += strl[i]; - } - *s = 0; - - jk_log(conf->log, JK_LOG_REQUEST, "%s", str); - -} - -/***************************************************************** - * - * Parsing the log format string - */ - -static char *format_integer(apr_pool_t * p, int i) -{ - return apr_psprintf(p, "%d", i); -} - -static char *pfmt(apr_pool_t * p, int i) -{ - if (i <= 0) { - return "-"; - } - else { - return format_integer(p, i); - } -} - -static const char *constant_item(request_rec * dummy, char *stuff) -{ - return stuff; -} - -static const char *log_worker_name(request_rec * r, char *a) -{ - return apr_table_get(r->notes, JK_NOTE_WORKER_NAME); -} - -static const char *log_worker_route(request_rec * r, char *a) -{ - return apr_table_get(r->notes, JK_NOTE_WORKER_ROUTE); -} - - -static const char *log_request_duration(request_rec * r, char *a) -{ - return apr_table_get(r->notes, JK_NOTE_REQUEST_DURATION); -} - -static const char *log_request_line(request_rec * r, char *a) -{ - /* NOTE: If the original request contained a password, we - * re-write the request line here to contain XXXXXX instead: - * (note the truncation before the protocol string for HTTP/0.9 requests) - * (note also that r->the_request contains the unmodified request) - */ - return (r->parsed_uri.password) ? apr_pstrcat(r->pool, r->method, " ", - apr_uri_unparse(r->pool, - &r-> - parsed_uri, - 0), - r-> - assbackwards ? NULL : " ", - r->protocol, NULL) - : r->the_request; -} - -/* These next two routines use the canonical name:port so that log - * parsers don't need to duplicate all the vhost parsing crud. - */ -static const char *log_virtual_host(request_rec * r, char *a) -{ - return r->server->server_hostname; -} - -static const char *log_server_port(request_rec * r, char *a) -{ - return apr_psprintf(r->pool, "%u", - r->server->port ? r->server-> - port : ap_default_port(r)); -} - -/* This respects the setting of UseCanonicalName so that - * the dynamic mass virtual hosting trick works better. - */ -static const char *log_server_name(request_rec * r, char *a) -{ - return ap_get_server_name(r); -} - -static const char *log_request_uri(request_rec * r, char *a) -{ - return r->uri; -} -static const char *log_request_method(request_rec * r, char *a) -{ - return r->method; -} - -static const char *log_request_protocol(request_rec * r, char *a) -{ - return r->protocol; -} -static const char *log_request_query(request_rec * r, char *a) -{ - return (r->args != NULL) ? apr_pstrcat(r->pool, "?", r->args, NULL) - : ""; -} -static const char *log_status(request_rec * r, char *a) -{ - return pfmt(r->pool, r->status); -} - -static const char *clf_log_bytes_sent(request_rec * r, char *a) -{ - if (!r->sent_bodyct) { - return "-"; - } - else { - return apr_off_t_toa(r->pool, r->bytes_sent); - } -} - -static const char *log_bytes_sent(request_rec * r, char *a) -{ - if (!r->sent_bodyct) { - return "0"; - } - else { - return apr_psprintf(r->pool, "%" APR_OFF_T_FMT, r->bytes_sent); - } -} - -static struct log_item_list -{ - char ch; - item_key_func func; -} log_item_keys[] = { - - { - 'T', log_request_duration}, { - 'r', log_request_line}, { - 'U', log_request_uri}, { - 's', log_status}, { - 'b', clf_log_bytes_sent}, { - 'B', log_bytes_sent}, { - 'V', log_server_name}, { - 'v', log_virtual_host}, { - 'p', log_server_port}, { - 'H', log_request_protocol}, { - 'm', log_request_method}, { - 'q', log_request_query}, { - 'w', log_worker_name}, { - 'R', log_worker_route}, { - '\0'} -}; - -static struct log_item_list *find_log_func(char k) -{ - int i; - - for (i = 0; log_item_keys[i].ch; ++i) - if (k == log_item_keys[i].ch) { - return &log_item_keys[i]; - } - - return NULL; -} - -static char *parse_request_log_misc_string(apr_pool_t * p, - request_log_format_item * it, - const char **sa) -{ - const char *s; - char *d; - - it->func = constant_item; - - s = *sa; - while (*s && *s != '%') { - s++; - } - /* - * This might allocate a few chars extra if there's a backslash - * escape in the format string. - */ - it->arg = apr_palloc(p, s - *sa + 1); - - d = it->arg; - s = *sa; - while (*s && *s != '%') { - if (*s != '\\') { - *d++ = *s++; - } - else { - s++; - switch (*s) { - case '\\': - *d++ = '\\'; - s++; - break; - case 'n': - *d++ = '\n'; - s++; - break; - case 't': - *d++ = '\t'; - s++; - break; - default: - /* copy verbatim */ - *d++ = '\\'; - /* - * Allow the loop to deal with this *s in the normal - * fashion so that it handles end of string etc. - * properly. - */ - break; - } - } - } - *d = '\0'; - - *sa = s; - return NULL; -} - -static char *parse_request_log_item(apr_pool_t * p, - request_log_format_item * it, - const char **sa) -{ - const char *s = *sa; - struct log_item_list *l; - - if (*s != '%') { - return parse_request_log_misc_string(p, it, sa); - } - - ++s; - it->arg = ""; /* For safety's sake... */ - - l = find_log_func(*s++); - if (!l) { - char dummy[2]; - - dummy[0] = s[-1]; - dummy[1] = '\0'; - return apr_pstrcat(p, "Unrecognized JkRequestLogFormat directive %", - dummy, NULL); - } - it->func = l->func; - *sa = s; - return NULL; -} - -static apr_array_header_t *parse_request_log_string(apr_pool_t * p, - const char *s, - const char **err) -{ - apr_array_header_t *a = - apr_array_make(p, 0, sizeof(request_log_format_item)); - char *res; - - while (*s) { - if ((res = - parse_request_log_item(p, - (request_log_format_item *) - apr_array_push(a), &s))) { - *err = res; - return NULL; - } - } - - return a; -} - -/* - * JkRequestLogFormat Directive Handling - * - * JkRequestLogFormat format string - * - * %b - Bytes sent, excluding HTTP headers. In CLF format - * %B - Bytes sent, excluding HTTP headers. - * %H - The request protocol - * %m - The request method - * %p - The canonical Port of the server serving the request - * %q - The query string (prepended with a ? if a query string exists, - * otherwise an empty string) - * %r - First line of request - * %s - request HTTP status code - * %T - Requset duration, elapsed time to handle request in seconds '.' micro seconds - * %U - The URL path requested, not including any query string. - * %v - The canonical ServerName of the server serving the request. - * %V - The server name according to the UseCanonicalName setting. - * %w - Tomcat worker name - */ - -static const char *jk_set_request_log_format(cmd_parms * cmd, - void *dummy, const char *format) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - conf->format_string = apr_pstrdup(cmd->pool, format); - - return NULL; -} - - -/* - * JkWorkerIndicator Directive Handling - * - * JkWorkerIndicator JkWorker - */ - -static const char *jk_set_worker_indicator(cmd_parms * cmd, - void *dummy, const char *indicator) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - conf->worker_indicator = apr_pstrdup(cmd->pool, indicator); - - return NULL; -} - -/* - * Directives Handling for setting various environment names - * used to overwrite the following request information: - * - remote_addr - * - remote_port - * - remote_host - * - remote_user - * - auth_type - * - server_name - * - server_port - */ -static const char *jk_set_remote_addr_indicator(cmd_parms * cmd, - void *dummy, const char *indicator) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, &jk_module); - conf->remote_addr_indicator = apr_pstrdup(cmd->pool, indicator); - return NULL; -} - -static const char *jk_set_remote_port_indicator(cmd_parms * cmd, - void *dummy, const char *indicator) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, &jk_module); - conf->remote_port_indicator = apr_pstrdup(cmd->pool, indicator); - return NULL; -} - -static const char *jk_set_remote_host_indicator(cmd_parms * cmd, - void *dummy, const char *indicator) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, &jk_module); - conf->remote_host_indicator = apr_pstrdup(cmd->pool, indicator); - return NULL; -} - -static const char *jk_set_remote_user_indicator(cmd_parms * cmd, - void *dummy, const char *indicator) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, &jk_module); - conf->remote_user_indicator = apr_pstrdup(cmd->pool, indicator); - return NULL; -} - -static const char *jk_set_auth_type_indicator(cmd_parms * cmd, - void *dummy, const char *indicator) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, &jk_module); - conf->auth_type_indicator = apr_pstrdup(cmd->pool, indicator); - return NULL; -} - -static const char *jk_set_local_name_indicator(cmd_parms * cmd, - void *dummy, const char *indicator) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, &jk_module); - conf->local_name_indicator = apr_pstrdup(cmd->pool, indicator); - return NULL; -} - -static const char *jk_set_local_port_indicator(cmd_parms * cmd, - void *dummy, const char *indicator) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, &jk_module); - conf->local_port_indicator = apr_pstrdup(cmd->pool, indicator); - return NULL; -} - -/* - * JkExtractSSL Directive Handling - * - * JkExtractSSL On/Off - */ - -static const char *jk_set_enable_ssl(cmd_parms * cmd, void *dummy, int flag) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - /* Set up our value */ - conf->ssl_enable = flag ? JK_TRUE : JK_FALSE; - - return NULL; -} - -/* - * JkHTTPSIndicator Directive Handling - * - * JkHTTPSIndicator HTTPS - */ - -static const char *jk_set_https_indicator(cmd_parms * cmd, - void *dummy, const char *indicator) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - conf->https_indicator = apr_pstrdup(cmd->pool, indicator); - - return NULL; -} - -/* - * JkCERTSIndicator Directive Handling - * - * JkCERTSIndicator SSL_CLIENT_CERT - */ - -static const char *jk_set_certs_indicator(cmd_parms * cmd, - void *dummy, const char *indicator) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - conf->certs_indicator = apr_pstrdup(cmd->pool, indicator); - - return NULL; -} - -/* - * JkCIPHERIndicator Directive Handling - * - * JkCIPHERIndicator SSL_CIPHER - */ - -static const char *jk_set_cipher_indicator(cmd_parms * cmd, - void *dummy, const char *indicator) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - conf->cipher_indicator = apr_pstrdup(cmd->pool, indicator); - - return NULL; -} - -/* - * JkCERTCHAINPrefix Directive Handling - * - * JkCERTCHAINPrefix SSL_CLIENT_CERT_CHAIN_ - */ - -static const char *jk_set_certchain_prefix(cmd_parms * cmd, - void *dummy, const char *prefix) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - conf->certchain_prefix = apr_pstrdup(cmd->pool, prefix); - - return NULL; -} - -/* - * JkSESSIONIndicator Directive Handling - * - * JkSESSIONIndicator SSL_SESSION_ID - */ - -static const char *jk_set_session_indicator(cmd_parms * cmd, - void *dummy, - const char *indicator) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - conf->session_indicator = apr_pstrdup(cmd->pool, indicator); - - return NULL; -} - -/* - * JkKEYSIZEIndicator Directive Handling - * - * JkKEYSIZEIndicator SSL_CIPHER_USEKEYSIZE - */ - -static const char *jk_set_key_size_indicator(cmd_parms * cmd, - void *dummy, - const char *indicator) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - conf->key_size_indicator = apr_pstrdup(cmd->pool, indicator); - - return NULL; -} - -/* - * JkOptions Directive Handling - * - * - * +ForwardSSLKeySize => Forward SSL Key Size, to follow 2.3 specs but may broke old TC 3.2 - * -ForwardSSLKeySize => Don't Forward SSL Key Size, will make mod_jk works with all TC release - * ForwardURICompat => Forward URI normally, less spec compliant but mod_rewrite compatible (old TC) - * ForwardURICompatUnparsed => Forward URI as unparsed, spec compliant but broke mod_rewrite (old TC) - * ForwardURIEscaped => Forward URI escaped and Tomcat (3.3 rc2) stuff will do the decoding part - * ForwardDirectories => Forward all directory requests with no index files to Tomcat - * +ForwardSSLCertChain => Forward SSL Cert Chain - * -ForwardSSLCertChain => Don't Forward SSL Cert Chain (default) - */ - -static const char *jk_set_options(cmd_parms * cmd, void *dummy, - const char *line) -{ - int opt = 0; - int mask = 0; - char action; - char *w; - - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - while (line[0] != 0) { - w = ap_getword_conf(cmd->pool, &line); - action = 0; - - if (*w == '+' || *w == '-') { - action = *(w++); - } - - mask = 0; - - if (action == '-' && !strncasecmp(w, "ForwardURI", strlen("ForwardURI"))) - return apr_pstrcat(cmd->pool, "JkOptions: Illegal option '-", w, - "': ForwardURI* options can not be disabled", NULL); - - if (!strcasecmp(w, "ForwardURICompat")) { - opt = JK_OPT_FWDURICOMPAT; - mask = JK_OPT_FWDURIMASK; - } - else if (!strcasecmp(w, "ForwardURICompatUnparsed")) { - opt = JK_OPT_FWDURICOMPATUNPARSED; - mask = JK_OPT_FWDURIMASK; - } - else if (!strcasecmp(w, "ForwardURIEscaped")) { - opt = JK_OPT_FWDURIESCAPED; - mask = JK_OPT_FWDURIMASK; - } - else if (!strcasecmp(w, "ForwardURIProxy")) { - opt = JK_OPT_FWDURIPROXY; - mask = JK_OPT_FWDURIMASK; - } - else if (!strcasecmp(w, "ForwardDirectories")) { - opt = JK_OPT_FWDDIRS; - } - else if (!strcasecmp(w, "ForwardLocalAddress")) { - opt = JK_OPT_FWDLOCAL; - } - else if (!strcasecmp(w, "FlushPackets")) { - opt = JK_OPT_FLUSHPACKETS; - } - else if (!strcasecmp(w, "FlushHeader")) { - opt = JK_OPT_FLUSHEADER; - } - else if (!strcasecmp(w, "DisableReuse")) { - opt = JK_OPT_DISABLEREUSE; - } - else if (!strcasecmp(w, "ForwardSSLCertChain")) { - opt = JK_OPT_FWDCERTCHAIN; - } - else if (!strcasecmp(w, "ForwardKeySize")) { - opt = JK_OPT_FWDKEYSIZE; - } - else if (!strcasecmp(w, "RejectUnsafeURI")) { - opt = JK_OPT_REJECTUNSAFE; - } - else - return apr_pstrcat(cmd->pool, "JkOptions: Illegal option '", w, - "'", NULL); - - conf->options &= ~mask; - - if (action == '-') { - conf->exclude_options |= opt; - } - else if (action == '+') { - conf->options |= opt; - } - else { /* for now +Opt == Opt */ - conf->options |= opt; - } - } - return NULL; -} - -/* - * JkEnvVar Directive Handling - * - * JkEnvVar MYOWNDIR - */ - -static const char *jk_add_env_var(cmd_parms * cmd, - void *dummy, - const char *env_name, - const char *default_value) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - conf->envvars_has_own = JK_TRUE; - if (!conf->envvars) { - conf->envvars = apr_table_make(cmd->pool, 0); - conf->envvars_def = apr_table_make(cmd->pool, 0); - conf->envvar_items = apr_array_make(cmd->pool, 0, - sizeof(envvar_item)); - } - - /* env_name is mandatory, default_value is optional. - * No value means send the attribute only, if the env var is set during runtime. - */ - apr_table_setn(conf->envvars, env_name, default_value ? default_value : ""); - apr_table_setn(conf->envvars_def, env_name, default_value ? "1" : "0"); - - return NULL; -} - -/* - * JkWorkerProperty Directive Handling - * - * JkWorkerProperty name=value - */ - -static const char *jk_set_worker_property(cmd_parms * cmd, - void *dummy, - const char *line) -{ - server_rec *s = cmd->server; - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - const char *err_string = ap_check_cmd_context(cmd, GLOBAL_ONLY); - if (err_string != NULL) { - return err_string; - } - - if (!jk_worker_properties) - jk_map_alloc(&jk_worker_properties); - if (jk_map_read_property(jk_worker_properties, NULL, line, - JK_MAP_HANDLE_DUPLICATES, conf->log) == JK_FALSE) - return apr_pstrcat(cmd->temp_pool, "Invalid JkWorkerProperty ", line, NULL); - - return NULL; -} - -static const command_rec jk_cmds[] = { - /* - * JkWorkersFile specifies a full path to the location of the worker - * properties file. - * - * This file defines the different workers used by apache to redirect - * servlet requests. - */ - AP_INIT_TAKE1("JkWorkersFile", jk_set_worker_file, NULL, RSRC_CONF, - "The name of a worker file for the Tomcat servlet containers"), - - /* - * JkMountFile specifies a full path to the location of the - * uriworker properties file. - * - * This file defines the different mapping for workers used by apache - * to redirect servlet requests. - */ - AP_INIT_TAKE1("JkMountFile", jk_set_mount_file, NULL, RSRC_CONF, - "The name of a mount file for the Tomcat servlet uri mapping"), - - /* - * JkMountFileReload specifies the reload check interval for the - * uriworker properties file. - * - * Default value is: JK_URIMAP_DEF_RELOAD - */ - AP_INIT_TAKE1("JkMountFileReload", jk_set_mount_file_reload, NULL, RSRC_CONF, - "The reload check interval of the mount file"), - - /* - * JkWatchdogInterval specifies the maintain interval for the - * watchdog thread. - * - * Default value is: 0 meaning watchdog thread will not be created - */ - AP_INIT_TAKE1("JkWatchdogInterval", jk_set_watchdog_interval, NULL, RSRC_CONF, - "The maintain interval of the watchdog thread"), - - /* - * JkMount mounts a url prefix to a worker (the worker need to be - * defined in the worker properties file. - */ - AP_INIT_TAKE12("JkMount", jk_mount_context, NULL, RSRC_CONF|ACCESS_CONF, - "A mount point from a context to a Tomcat worker"), - - /* - * JkUnMount unmounts a url prefix to a worker (the worker need to be - * defined in the worker properties file. - */ - AP_INIT_TAKE12("JkUnMount", jk_unmount_context, NULL, RSRC_CONF|ACCESS_CONF, - "A no mount point from a context to a Tomcat worker"), - - /* - * JkMountCopy specifies if mod_jk should copy the mount points - * from the main server to the virtual servers. - */ - AP_INIT_TAKE1("JkMountCopy", jk_set_mountcopy, NULL, RSRC_CONF, - "Should the base server mounts be copied to the virtual server"), - - /* - * JkStripSession specifies if mod_jk should strip the ;jsessionid - * from the unmapped urls - */ - AP_INIT_TAKE12("JkStripSession", jk_set_strip_session, NULL, RSRC_CONF, - "Should the server strip the jsessionid from unmapped URLs"), - - /* - * JkLogFile & JkLogLevel specifies to where should the plugin log - * its information and how much. - * JkLogStampFormat specify the time-stamp to be used on log - */ - AP_INIT_TAKE1("JkLogFile", jk_set_log_file, NULL, RSRC_CONF, - "Full path to the Tomcat module log file"), - - AP_INIT_TAKE1("JkShmFile", jk_set_shm_file, NULL, RSRC_CONF, - "Full path to the Tomcat module shared memory file"), - - AP_INIT_TAKE1("JkShmSize", jk_set_shm_size, NULL, RSRC_CONF, - "Size of the shared memory file in KBytes"), - - AP_INIT_TAKE1("JkLogLevel", jk_set_log_level, NULL, RSRC_CONF, - "The Tomcat module log level, can be debug, " - "info, error or emerg"), - AP_INIT_TAKE1("JkLogStampFormat", jk_set_log_fmt, NULL, RSRC_CONF, - "The Tomcat module log format, follow strftime syntax"), - AP_INIT_TAKE1("JkRequestLogFormat", jk_set_request_log_format, NULL, - RSRC_CONF, - "The mod_jk module request log format string"), - - /* - * Automatically Alias webapp context directories into the Apache - * document space. - */ - AP_INIT_TAKE1("JkAutoAlias", jk_set_auto_alias, NULL, RSRC_CONF, - "The mod_jk module automatic context apache alias directory"), - - /* - * Enable worker name to be set in an environment variable. - * This way one can use LocationMatch together with mod_env, - * mod_setenvif and mod_rewrite to set the target worker. - * Use this in combination with SetHandler jakarta-servlet to - * make mod_jk the handler for the request. - * - */ - AP_INIT_TAKE1("JkWorkerIndicator", jk_set_worker_indicator, NULL, RSRC_CONF, - "Name of the Apache environment that contains the worker name"), - - /* - * Environment variables used to overwrite the following - * request information which gets forwarded: - * - remote_addr - * - remote_port - * - remote_host - * - remote_user - * - auth_type - * - server_name - * - server_port - */ - AP_INIT_TAKE1("JkRemoteAddrIndicator", jk_set_remote_addr_indicator, NULL, RSRC_CONF, - "Name of the Apache environment that contains the remote address"), - AP_INIT_TAKE1("JkRemotePortIndicator", jk_set_remote_port_indicator, NULL, RSRC_CONF, - "Name of the Apache environment that contains the remote port"), - AP_INIT_TAKE1("JkRemoteHostIndicator", jk_set_remote_host_indicator, NULL, RSRC_CONF, - "Name of the Apache environment that contains the remote host name"), - AP_INIT_TAKE1("JkRemoteUserIndicator", jk_set_remote_user_indicator, NULL, RSRC_CONF, - "Name of the Apache environment that contains the remote user name"), - AP_INIT_TAKE1("JkAuthTypeIndicator", jk_set_auth_type_indicator, NULL, RSRC_CONF, - "Name of the Apache environment that contains the type of authentication"), - AP_INIT_TAKE1("JkLocalNameIndicator", jk_set_local_name_indicator, NULL, RSRC_CONF, - "Name of the Apache environment that contains the local name"), - AP_INIT_TAKE1("JkLocalPortIndicator", jk_set_local_port_indicator, NULL, RSRC_CONF, - "Name of the Apache environment that contains the local port"), - - /* - * Apache has multiple SSL modules (for example apache_ssl, stronghold - * IHS ...). Each of these can have a different SSL environment names - * The following properties let the administrator specify the envoiroment - * variables names. - * - * HTTPS - indication for SSL - * CERTS - Base64-Der-encoded client certificates. - * CIPHER - A string specifing the ciphers suite in use. - * KEYSIZE - Size of Key used in dialogue (#bits are secure) - * SESSION - A string specifing the current SSL session. - */ - AP_INIT_TAKE1("JkHTTPSIndicator", jk_set_https_indicator, NULL, RSRC_CONF, - "Name of the Apache environment that contains SSL indication"), - AP_INIT_TAKE1("JkCERTSIndicator", jk_set_certs_indicator, NULL, RSRC_CONF, - "Name of the Apache environment that contains SSL client certificates"), - AP_INIT_TAKE1("JkCIPHERIndicator", jk_set_cipher_indicator, NULL, - RSRC_CONF, - "Name of the Apache environment that contains SSL client cipher"), - AP_INIT_TAKE1("JkSESSIONIndicator", jk_set_session_indicator, NULL, - RSRC_CONF, - "Name of the Apache environment that contains SSL session"), - AP_INIT_TAKE1("JkKEYSIZEIndicator", jk_set_key_size_indicator, NULL, - RSRC_CONF, - "Name of the Apache environment that contains SSL key size in use"), - AP_INIT_TAKE1("JkCERTCHAINPrefix", jk_set_certchain_prefix, NULL, RSRC_CONF, - "Name of the Apache environment (prefix) that contains SSL client chain certificates"), - AP_INIT_FLAG("JkExtractSSL", jk_set_enable_ssl, NULL, RSRC_CONF, - "Turns on SSL processing and information gathering by mod_jk"), - - /* - * Options to tune mod_jk configuration - * for now we understand : - * +ForwardSSLKeySize => Forward SSL Key Size, to follow 2.3 specs but may broke old TC 3.2 - * -ForwardSSLKeySize => Don't Forward SSL Key Size, will make mod_jk works with all TC release - * ForwardURICompat => Forward URI normally, less spec compliant but mod_rewrite compatible (old TC) - * ForwardURICompatUnparsed => Forward URI as unparsed, spec compliant but broke mod_rewrite (old TC) - * ForwardURIEscaped => Forward URI escaped and Tomcat (3.3 rc2) stuff will do the decoding part - * +ForwardSSLCertChain => Forward SSL certificate chain - * -ForwardSSLCertChain => Don't forward SSL certificate chain - */ - AP_INIT_RAW_ARGS("JkOptions", jk_set_options, NULL, RSRC_CONF, - "Set one of more options to configure the mod_jk module"), - - /* - * JkEnvVar let user defines envs var passed from WebServer to - * Servlet Engine - */ - AP_INIT_TAKE12("JkEnvVar", jk_add_env_var, NULL, RSRC_CONF, - "Adds a name of environment variable and an optional value " - "that should be sent to servlet-engine"), - - AP_INIT_RAW_ARGS("JkWorkerProperty", jk_set_worker_property, - NULL, RSRC_CONF, - "Set workers.properties formated directive"), - - {NULL} -}; - -/* ========================================================================= */ -/* The JK module handlers */ -/* ========================================================================= */ - -/** Util - cleanup shmem. - */ -static apr_status_t jk_cleanup_shmem(void *data) -{ - /* Force the watchdog thread exit */ - if (jk_watchdog_interval > 0) { - jk_watchdog_interval = 0; - while (jk_watchdog_running) - apr_sleep(apr_time_from_sec(1)); - } - jk_shm_close(); - return APR_SUCCESS; -} - -/** Main service method, called to forward a request to tomcat - */ -static int jk_handler(request_rec * r) -{ - const char *worker_name; - jk_server_conf_t *xconf; - int rc, dmt = 1; - - /* We do DIR_MAGIC_TYPE here to make sure TC gets all requests, even - * if they are directory requests, in case there are no static files - * visible to Apache and/or DirectoryIndex was not used. This is only - * used when JkOptions has ForwardDirectories set. */ - /* Not for me, try next handler */ - if (strcmp(r->handler, JK_HANDLER) - && (dmt = strcmp(r->handler, DIR_MAGIC_TYPE))) - return DECLINED; - - xconf = (jk_server_conf_t *) ap_get_module_config(r->server->module_config, - &jk_module); - JK_TRACE_ENTER(xconf->log); - if (apr_table_get(r->subprocess_env, "no-jk")) { - if (JK_IS_DEBUG_LEVEL(xconf->log)) - jk_log(xconf->log, JK_LOG_DEBUG, - "Into handler no-jk env var detected for uri=%s, declined", - r->uri); - - JK_TRACE_EXIT(xconf->log); - return DECLINED; - } - - /* Was the option to forward directories to Tomcat set? */ - if (!dmt && !(xconf->options & JK_OPT_FWDDIRS)) { - JK_TRACE_EXIT(xconf->log); - return DECLINED; - } - worker_name = apr_table_get(r->notes, JK_NOTE_WORKER_NAME); - - /* Set up r->read_chunked flags for chunked encoding, if present */ - if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != APR_SUCCESS) { - JK_TRACE_EXIT(xconf->log); - return rc; - } - - if (worker_name == NULL) { - /* we may be here because of a manual directive ( that overrides - translate and - sets the handler directly ). We still need to know the worker. - */ - worker_name = apr_table_get(r->subprocess_env, xconf->worker_indicator); - if (worker_name) { - /* The JkWorkerIndicator environment variable has - * been used to explicitely set the worker without JkMount. - * This is useful in combination with LocationMatch or mod_rewrite. - */ - if (JK_IS_DEBUG_LEVEL(xconf->log)) - jk_log(xconf->log, JK_LOG_DEBUG, - "Retrieved worker (%s) from env %s for %s", - worker_name, xconf->worker_indicator, r->uri); - } - else if (worker_env.num_of_workers == 1) { - /** We have a single worker ( the common case ). - ( lb is a bit special, it should count as a single worker but - I'm not sure how ). We also have a manual config directive that - explicitely give control to us. */ - worker_name = worker_env.worker_list[0]; - if (JK_IS_DEBUG_LEVEL(xconf->log)) - jk_log(xconf->log, JK_LOG_DEBUG, - "Single worker (%s) configuration for %s", - worker_name, r->uri); - } - else { - if (!xconf->uw_map) { - if (JK_IS_DEBUG_LEVEL(xconf->log)) - jk_log(xconf->log, JK_LOG_DEBUG, - "missing uri map for %s:%s", - xconf->s->server_hostname ? xconf->s->server_hostname : "_default_", - r->uri); - } - else { - rule_extension_t *e; - worker_name = map_uri_to_worker_ext(xconf->uw_map, r->uri, - NULL, &e, NULL, xconf->log); - ap_set_module_config(r->request_config, &jk_module, e); - } - - if (worker_name == NULL && worker_env.num_of_workers) { - worker_name = worker_env.worker_list[0]; - if (JK_IS_DEBUG_LEVEL(xconf->log)) - jk_log(xconf->log, JK_LOG_DEBUG, - "Using first worker (%s) from %d workers for %s", - worker_name, worker_env.num_of_workers, r->uri); - } - } - if (worker_name) - apr_table_setn(r->notes, JK_NOTE_WORKER_NAME, worker_name); - } - - if (JK_IS_DEBUG_LEVEL(xconf->log)) - jk_log(xconf->log, JK_LOG_DEBUG, "Into handler %s worker=%s" - " r->proxyreq=%d", - r->handler, STRNULL_FOR_NULL(worker_name), r->proxyreq); - - /* If this is a proxy request, we'll notify an error */ - if (r->proxyreq) { - jk_log(xconf->log, JK_LOG_INFO, "Proxy request for worker=%s" - " is not allowed", - STRNULL_FOR_NULL(worker_name)); - JK_TRACE_EXIT(xconf->log); - return HTTP_INTERNAL_SERVER_ERROR; - } - - if (worker_name) { - jk_worker_t *worker = wc_get_worker_for_name(worker_name, xconf->log); - - /* If the remote client has aborted, just ignore the request */ - if (r->connection->aborted) { - jk_log(xconf->log, JK_LOG_INFO, "Client connection aborted for" - " worker=%s", - worker_name); - JK_TRACE_EXIT(xconf->log); - return OK; - } - - if (worker) { - long micro, seconds; - char *duration = NULL; - apr_time_t rd; - apr_time_t request_begin = 0; - int is_error = HTTP_INTERNAL_SERVER_ERROR; - int rc = JK_FALSE; - apache_private_data_t private_data; - jk_ws_service_t s; - jk_pool_atom_t buf[SMALL_POOL_SIZE]; - jk_open_pool(&private_data.p, buf, sizeof(buf)); - - private_data.read_body_started = JK_FALSE; - private_data.r = r; - - /* Maintain will be done by watchdog thread */ - if (!jk_watchdog_interval) - wc_maintain(xconf->log); - jk_init_ws_service(&s); - s.ws_private = &private_data; - s.pool = &private_data.p; - apr_table_setn(r->notes, JK_NOTE_WORKER_TYPE, - wc_get_name_for_type(worker->type, xconf->log)); - - request_begin = apr_time_now(); - - if (init_ws_service(&private_data, &s, xconf)) { - jk_endpoint_t *end = NULL; - - /* Use per/thread pool ( or "context" ) to reuse the - endpoint. It's a bit faster, but I don't know - how to deal with load balancing - but it's usefull for JNI - */ - - /* worker->get_endpoint might fail if we are out of memory so check */ - /* and handle it */ - if (worker->get_endpoint(worker, &end, xconf->log)) { - rc = end->service(end, &s, xconf->log, - &is_error); - end->done(&end, xconf->log); - if (s.content_read < s.content_length || - (s.is_chunked && !s.no_more_chunks)) { - /* - * If the servlet engine didn't consume all of the - * request data, consume and discard all further - * characters left to read from client - */ - char *buff = apr_palloc(r->pool, 2048); - int consumed = 0; - if (buff != NULL) { - int rd; - while ((rd = - ap_get_client_block(r, buff, 2048)) > 0) { - s.content_read += rd; - consumed += rd; - } - } - if (JK_IS_DEBUG_LEVEL(xconf->log)) { - jk_log(xconf->log, JK_LOG_DEBUG, - "Consumed %d bytes of remaining request data for worker=%s", - consumed, STRNULL_FOR_NULL(worker_name)); - } - } - } - else { /* this means we couldn't get an endpoint */ - jk_log(xconf->log, JK_LOG_ERROR, "Could not get endpoint" - " for worker=%s", - worker_name); - rc = 0; /* just to make sure that we know we've failed */ - } - } - else { - jk_log(xconf->log, JK_LOG_ERROR, "Could not init service" - " for worker=%s", - worker_name); - jk_close_pool(&private_data.p); - JK_TRACE_EXIT(xconf->log); - return HTTP_INTERNAL_SERVER_ERROR; - } - rd = apr_time_now() - request_begin; - seconds = (long)apr_time_sec(rd); - micro = (long)(rd - apr_time_from_sec(seconds)); - - duration = apr_psprintf(r->pool, "%.1ld.%.6ld", seconds, micro); - apr_table_setn(r->notes, JK_NOTE_REQUEST_DURATION, duration); - if (s.route && *s.route) - apr_table_setn(r->notes, JK_NOTE_WORKER_ROUTE, s.route); - - if (xconf->format != NULL) { - request_log_transaction(r, xconf); - } - - jk_close_pool(&private_data.p); - - if (rc > 0) { - if (s.extension.use_server_error_pages && - s.http_response_status >= s.extension.use_server_error_pages) { - if (JK_IS_DEBUG_LEVEL(xconf->log)) - jk_log(xconf->log, JK_LOG_DEBUG, "Forwarding status=%d" - " for worker=%s", - s.http_response_status, worker_name); - JK_TRACE_EXIT(xconf->log); - return s.http_response_status; - } - /* If tomcat returned no body and the status is not OK, - let apache handle the error code */ - - if (!r->sent_bodyct && r->status >= HTTP_BAD_REQUEST) { - jk_log(xconf->log, JK_LOG_INFO, "No body with status=%d" - " for worker=%s", - r->status, worker_name); - JK_TRACE_EXIT(xconf->log); - return r->status; - } - if (JK_IS_DEBUG_LEVEL(xconf->log)) - jk_log(xconf->log, JK_LOG_DEBUG, "Service finished" - " with status=%d for worker=%s", - r->status, worker_name); - JK_TRACE_EXIT(xconf->log); - return OK; /* NOT r->status, even if it has changed. */ - } - else if (rc == JK_CLIENT_ERROR) { - if (is_error != HTTP_REQUEST_ENTITY_TOO_LARGE) - r->connection->aborted = 1; - jk_log(xconf->log, JK_LOG_INFO, "Aborting connection" - " for worker=%s", - worker_name); - JK_TRACE_EXIT(xconf->log); - return is_error; - } - else { - jk_log(xconf->log, JK_LOG_INFO, "Service error=%d" - " for worker=%s", - rc, worker_name); - JK_TRACE_EXIT(xconf->log); - return is_error; - } - } - else { - jk_log(xconf->log, JK_LOG_INFO, "Could not find a worker" - " for worker name=%s", - worker_name); - JK_TRACE_EXIT(xconf->log); - return HTTP_INTERNAL_SERVER_ERROR; - } - } - - JK_TRACE_EXIT(xconf->log); - return DECLINED; -} - -/** Standard apache hook, cleanup jk - */ -static apr_status_t jk_apr_pool_cleanup(void *data) -{ - server_rec *s = data; - - if (jk_worker_properties) { - jk_map_free(&jk_worker_properties); - jk_worker_properties = NULL; - jk_worker_file = NULL; - jk_mount_copy_all = JK_FALSE; - } - - while (NULL != s) { - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(s->module_config, - &jk_module); - - if (conf && conf->was_initialized == JK_TRUE) { - /* On pool cleanup pass NULL for the jk_logger to - prevent segmentation faults on Windows because - we can't guarantee what order pools get cleaned - up between APR implementations. */ - wc_close(NULL); - if (conf->uri_to_context) { - jk_map_free(&conf->uri_to_context); - /* We cannot have allocated uw_map - * unless we've allocated uri_to_context - */ - if (conf->uw_map) - uri_worker_map_free(&conf->uw_map, NULL); - } - conf->was_initialized = JK_FALSE; - } - s = s->next; - } - return APR_SUCCESS; -} - -/** Create default jk_config. XXX This is mostly server-independent, - all servers are using something similar - should go to common. - */ -static void *create_jk_config(apr_pool_t * p, server_rec * s) -{ - jk_server_conf_t *c = - (jk_server_conf_t *) apr_pcalloc(p, sizeof(jk_server_conf_t)); - - c->was_initialized = JK_FALSE; - - if (s->is_virtual) { - c->mountcopy = JK_UNSET; - c->mount_file_reload = JK_UNSET; - c->log_level = JK_UNSET; - c->ssl_enable = JK_UNSET; - c->strip_session = JK_UNSET; - } else { - if (!jk_map_alloc(&(c->uri_to_context))) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Memory error"); - } - c->mountcopy = JK_FALSE; - c->mount_file_reload = JK_URIMAP_DEF_RELOAD; - c->log_level = JK_LOG_DEF_LEVEL; - c->options = JK_OPT_DEFAULT; - c->worker_indicator = JK_ENV_WORKER_NAME; - - /* - * Configurable environment variables to overwrite - * request information using meta data send by a - * proxy in front of us. - */ - c->remote_addr_indicator = JK_ENV_REMOTE_ADDR; - c->remote_port_indicator = JK_ENV_REMOTE_PORT; - c->remote_host_indicator = JK_ENV_REMOTE_HOST; - c->remote_user_indicator = JK_ENV_REMOTE_USER; - c->auth_type_indicator = JK_ENV_AUTH_TYPE; - c->local_name_indicator = JK_ENV_LOCAL_NAME; - c->local_port_indicator = JK_ENV_LOCAL_PORT; - - /* - * By default we will try to gather SSL info. - * Disable this functionality through JkExtractSSL - */ - c->ssl_enable = JK_TRUE; - /* - * The defaults ssl indicators match those in mod_ssl (seems - * to be in more use). - */ - c->https_indicator = JK_ENV_HTTPS; - c->certs_indicator = JK_ENV_CERTS; - c->cipher_indicator = JK_ENV_CIPHER; - c->certchain_prefix = JK_ENV_CERTCHAIN_PREFIX; - c->session_indicator = JK_ENV_SESSION; - c->key_size_indicator = JK_ENV_KEY_SIZE; - c->strip_session = JK_FALSE; - } - c->envvars_has_own = JK_FALSE; - - c->s = s; - apr_pool_cleanup_register(p, s, jk_apr_pool_cleanup, apr_pool_cleanup_null); - return c; -} - - -/* - * Utility - copy items from apr table src to dst, - * for keys that exist in src but not in dst. - */ -static void merge_apr_table(apr_table_t *src, apr_table_t *dst) -{ - int i; - const apr_array_header_t *arr; - const apr_table_entry_t *elts; - - arr = apr_table_elts(src); - elts = (const apr_table_entry_t *)arr->elts; - for (i = 0; i < arr->nelts; ++i) { - if (!apr_table_get(dst, elts[i].key)) { - apr_table_setn(dst, elts[i].key, elts[i].val); - } - } -} - - -/** Standard apache callback, merge jk options specified in <Directory> - context or <Host>. - */ -static void *merge_jk_config(apr_pool_t * p, void *basev, void *overridesv) -{ - jk_server_conf_t *base = (jk_server_conf_t *) basev; - jk_server_conf_t *overrides = (jk_server_conf_t *) overridesv; - - if (!overrides->log_file) - overrides->log_file = base->log_file; - if (overrides->log_level == JK_UNSET) - overrides->log_level = base->log_level; - - if (!overrides->stamp_format_string) - overrides->stamp_format_string = base->stamp_format_string; - if (!overrides->format_string) - overrides->format_string = base->format_string; - - if (!overrides->worker_indicator) - overrides->worker_indicator = base->worker_indicator; - - if (!overrides->remote_addr_indicator) - overrides->remote_addr_indicator = base->remote_addr_indicator; - if (!overrides->remote_port_indicator) - overrides->remote_port_indicator = base->remote_port_indicator; - if (!overrides->remote_host_indicator) - overrides->remote_host_indicator = base->remote_host_indicator; - if (!overrides->remote_user_indicator) - overrides->remote_user_indicator = base->remote_user_indicator; - if (!overrides->auth_type_indicator) - overrides->auth_type_indicator = base->auth_type_indicator; - if (!overrides->local_name_indicator) - overrides->local_name_indicator = base->local_name_indicator; - if (!overrides->local_port_indicator) - overrides->local_port_indicator = base->local_port_indicator; - - if (overrides->ssl_enable == JK_UNSET) - overrides->ssl_enable = base->ssl_enable; - if (!overrides->https_indicator) - overrides->https_indicator = base->https_indicator; - if (!overrides->certs_indicator) - overrides->certs_indicator = base->certs_indicator; - if (!overrides->cipher_indicator) - overrides->cipher_indicator = base->cipher_indicator; - if (!overrides->certchain_prefix) - overrides->certchain_prefix = base->certchain_prefix; - if (!overrides->session_indicator) - overrides->session_indicator = base->session_indicator; - if (!overrides->key_size_indicator) - overrides->key_size_indicator = base->key_size_indicator; - -/* Don't simply accumulate bits in the JK_OPT_FWDURIMASK region, */ -/* because those are multi-bit values. */ - if (overrides->options & JK_OPT_FWDURIMASK) - overrides->options |= (base->options & ~base->exclude_options) & ~JK_OPT_FWDURIMASK; - else - overrides->options |= (base->options & ~base->exclude_options); - - if (base->envvars) { - if (overrides->envvars && overrides->envvars_has_own) { -/* merge_apr_table() preserves existing entries in overrides table */ - merge_apr_table(base->envvars, overrides->envvars); - merge_apr_table(base->envvars_def, overrides->envvars_def); - } - else { - overrides->envvars = base->envvars; - overrides->envvars_def = base->envvars_def; - overrides->envvar_items = base->envvar_items; - } - } - - if (overrides->mountcopy == JK_UNSET && jk_mount_copy_all == JK_TRUE) { - overrides->mountcopy = JK_TRUE; - } - if (overrides->uri_to_context && overrides->mountcopy == JK_TRUE) { -/* jk_map_copy() preserves existing entries in overrides map */ - if (jk_map_copy(base->uri_to_context, overrides->uri_to_context) == JK_FALSE) { - jk_error_exit(JKLOG_MARK, APLOG_EMERG, overrides->s, p, "Memory error"); - } - if (!overrides->mount_file) - overrides->mount_file = base->mount_file; - } - if (overrides->mountcopy == JK_TRUE) { - if (!overrides->alias_dir) - overrides->alias_dir = base->alias_dir; - } - if (overrides->mount_file_reload == JK_UNSET) - overrides->mount_file_reload = base->mount_file_reload; - if (overrides->strip_session == JK_UNSET) { - overrides->strip_session = base->strip_session; - overrides->strip_session_name = base->strip_session_name; - } - return overrides; -} - -static int JK_METHOD jk_log_to_file(jk_logger_t *l, int level, - int used, char *what) -{ - if (l && - (l->level <= level || level == JK_LOG_REQUEST_LEVEL) && - l->logger_private && what && used > 0) { - jk_file_logger_t *p = l->logger_private; - if (p->jklogfp) { - apr_status_t rv; - apr_size_t wrote; -#if defined(WIN32) - what[used++] = '\r'; -#endif - what[used++] = '\n'; - wrote = used; - rv = apr_global_mutex_lock(jk_log_lock); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, - "apr_global_mutex_lock(jk_log_lock) failed"); - /* XXX: Maybe this should be fatal? */ - } - rv = apr_file_write(p->jklogfp, what, &wrote); - if (rv != APR_SUCCESS) { - char error[256]; - apr_strerror(rv, error, 254); - ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, - "mod_jk: jk_log_to_file %s failed: %s", - what, error); - } - rv = apr_global_mutex_unlock(jk_log_lock); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, - "apr_global_mutex_unlock(jk_log_lock) failed"); - /* XXX: Maybe this should be fatal? */ - } - } - - return JK_TRUE; - } - - return JK_FALSE; -} - -/* -** +-------------------------------------------------------+ -** | | -** | jk logfile support | -** | | -** +-------------------------------------------------------+ -*/ - -static apr_status_t jklog_cleanup(void *d) -{ - /* hgomez@20070425 */ - /* Clean up pointer content */ - if (d != NULL) - *(jk_logger_t **)d = NULL; - - return APR_SUCCESS; -} - -static int open_jklog(server_rec * s, apr_pool_t * p) -{ - jk_server_conf_t *conf; - const char *fname; - apr_status_t rc; - apr_file_t *jklogfp; - piped_log *pl; - jk_logger_t *jkl; - jk_file_logger_t *flp; - int jklog_flags = (APR_WRITE | APR_APPEND | APR_CREATE); - apr_fileperms_t jklog_mode = - (APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD); - - conf = ap_get_module_config(s->module_config, &jk_module); - - if (conf->log_file == NULL) { - conf->log_file = ap_server_root_relative(p, JK_LOG_DEF_FILE); - if (conf->log_file) - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, - "No JkLogFile defined in httpd.conf. " - "Using default %s", conf->log_file); - } - if (*(conf->log_file) == '\0') { - ap_log_error(APLOG_MARK, APLOG_ERR, APR_EBADPATH, s, - "mod_jk: Invalid JkLogFile EMPTY"); - conf->log = main_log; - return 0; - } - - jklogfp = apr_hash_get(jk_log_fps, conf->log_file, APR_HASH_KEY_STRING); - if (!jklogfp) { - if (*conf->log_file == '|') { - if ((pl = ap_open_piped_log(p, conf->log_file + 1)) == NULL) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "mod_jk: could not open reliable pipe " - "to jk log %s", conf->log_file + 1); - return -1; - } - jklogfp = (void *)ap_piped_log_write_fd(pl); - } - else { - fname = ap_server_root_relative(p, conf->log_file); - if (!fname) { - ap_log_error(APLOG_MARK, APLOG_ERR, APR_EBADPATH, s, - "mod_jk: Invalid JkLog " "path %s", conf->log_file); - return -1; - } - if ((rc = apr_file_open(&jklogfp, fname, - jklog_flags, jklog_mode, p)) - != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rc, s, - "mod_jk: could not open JkLog " "file %s", fname); - return -1; - } - } - apr_file_inherit_set(jklogfp); - apr_hash_set(jk_log_fps, conf->log_file, APR_HASH_KEY_STRING, jklogfp); - } - conf->jklogfp = jklogfp; - jkl = (jk_logger_t *)apr_palloc(p, sizeof(jk_logger_t)); - flp = (jk_file_logger_t *) apr_palloc(p, sizeof(jk_file_logger_t)); - if (jkl && flp) { - jkl->log = jk_log_to_file; - jkl->level = conf->log_level; - jkl->logger_private = flp; - flp->jklogfp = conf->jklogfp; - conf->log = jkl; - jk_set_time_fmt(conf->log, conf->stamp_format_string); - if (main_log == NULL) { - main_log = conf->log; - - /* hgomez@20070425 */ - /* Shouldn't we clean both conf->log and main_log ? */ - /* Also should we pass pointer (ie: main_log) or handle (*main_log) ? */ - apr_pool_cleanup_register(p, &main_log, - jklog_cleanup, - apr_pool_cleanup_null); - } - - return 0; - } - - return -1; -} - -#if APR_HAS_THREADS - -static void * APR_THREAD_FUNC jk_watchdog_func(apr_thread_t *thd, void *data) -{ - int i; - jk_server_conf_t *conf = (jk_server_conf_t *)data; - - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "Watchdog thread initialized with %d second interval", - jk_watchdog_interval); - for (;;) { - for (i = 0; i < (jk_watchdog_interval * 10); i++) { - /* apr_sleep() uses microseconds */ - apr_sleep((apr_time_t)(100000)); - if (!jk_watchdog_interval) - break; - } - if (!jk_watchdog_interval) - break; - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "Watchdog thread running"); - jk_watchdog_running = 1; - wc_maintain(conf->log); - if (!jk_watchdog_interval) - break; - } - jk_watchdog_running = 0; - return NULL; -} - -#endif - -/** Standard apache callback, initialize jk. - */ -static void jk_child_init(apr_pool_t * pconf, server_rec * s) -{ - jk_server_conf_t *conf; - apr_status_t rv; - int rc; - apr_thread_t *wdt; - - conf = ap_get_module_config(s->module_config, &jk_module); - - rv = apr_global_mutex_child_init(&jk_log_lock, NULL, pconf); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, - "mod_jk: could not init JK log lock in child"); - } - - JK_TRACE_ENTER(conf->log); - - if (jk_watchdog_interval) { -#if APR_HAS_THREADS - rv = apr_thread_create(&wdt, NULL, jk_watchdog_func, conf, pconf); - if (rv != APR_SUCCESS) { - jk_log(conf->log, JK_LOG_ERROR, - "Could not init watchdog thread, error=%d", rv); - jk_watchdog_interval = 0; - } - apr_thread_detach(wdt); -#endif - } - - if ((rc = jk_shm_attach(jk_shm_file, jk_shm_size, conf->log)) == 0) { - apr_pool_cleanup_register(pconf, conf->log, jk_cleanup_shmem, - apr_pool_cleanup_null); - } - else - jk_log(conf->log, JK_LOG_ERROR, "Attaching shm:%s errno=%d", - jk_shm_name(), rc); - - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, "Initialized %s", JK_FULL_EXPOSED_VERSION); - JK_TRACE_EXIT(conf->log); -} - -/** Initialize jk, using worker.properties. - We also use apache commands ( JkWorker, etc), but this use is - deprecated, as we'll try to concentrate all config in - workers.properties, urimap.properties, and ajp14 autoconf. - - Apache config will only be used for manual override, using - SetHandler and normal apache directives ( but minimal jk-specific - stuff ) -*/ -static int init_jk(apr_pool_t * pconf, jk_server_conf_t * conf, - server_rec * s) -{ - int rc; - int is_threaded; - int mpm_threads = 1; - - if (!jk_worker_properties) - jk_map_alloc(&jk_worker_properties); - jk_map_put(jk_worker_properties, "ServerRoot", ap_server_root, NULL); - - /* Set default connection cache size for multi-threaded MPMs */ - if (ap_mpm_query(AP_MPMQ_IS_THREADED, &is_threaded) == APR_SUCCESS && - is_threaded != AP_MPMQ_NOT_SUPPORTED) { - if (ap_mpm_query(AP_MPMQ_MAX_THREADS, &mpm_threads) != APR_SUCCESS) - mpm_threads = 1; - } - if (mpm_threads > 1) { -#if _MT_CODE - /* _MT_CODE */ - if (JK_IS_DEBUG_LEVEL(conf->log)) { -#if !defined(WIN32) && !defined(NETWARE) -#if USE_FLOCK_LK - jk_log(conf->log, JK_LOG_DEBUG, - "Using flock() for locking."); -#else - jk_log(conf->log, JK_LOG_DEBUG, - "Using fcntl() for locking."); -#endif /* USE_FLOCK_LK */ -#else /* WIN32 */ - jk_log(conf->log, JK_LOG_DEBUG, - "Not using locking."); -#endif - } -#else - /* !_MT_CODE */ - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, - "Cannot run prefork mod_jk on threaded server."); - return JK_FALSE; -#endif - } - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "Setting default connection pool max size to %d", - mpm_threads); - jk_set_worker_def_cache_size(mpm_threads); - - if ((jk_worker_file != NULL) && - !jk_map_read_properties(jk_worker_properties, NULL, jk_worker_file, NULL, - JK_MAP_HANDLE_DUPLICATES, conf->log)) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, - "Error in reading worker properties from '%s'", - jk_worker_file); - return JK_FALSE; - } - - if (jk_map_resolve_references(jk_worker_properties, "worker.", - 1, 1, conf->log) == JK_FALSE) { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, - "Error in resolving configuration references"); - return JK_FALSE; - } - -#if !defined(WIN32) && !defined(NETWARE) - if (!jk_shm_file) { - jk_shm_file = ap_server_root_relative(pconf, JK_SHM_DEF_FILE); - if (jk_shm_file) - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, - "No JkShmFile defined in httpd.conf. " - "Using default %s", jk_shm_file); - } -#endif - if (jk_shm_size == 0) - jk_shm_size = jk_shm_calculate_size(jk_worker_properties, conf->log); - else if (jk_shm_size_set) { - jk_log(conf->log, JK_LOG_WARNING, - "The optimal shared memory size can now be determined automatically."); - jk_log(conf->log, JK_LOG_WARNING, - "You can remove the JkShmSize directive if you want to use the optimal size."); - } - if ((rc = jk_shm_open(jk_shm_file, jk_shm_size, conf->log)) == 0) { - apr_pool_cleanup_register(pconf, conf->log, - jk_cleanup_shmem, - apr_pool_cleanup_null); - } - else - jk_log(conf->log, JK_LOG_ERROR, - "Initializing shm:%s errno=%d. Load balancing workers will not function properly.", - jk_shm_name(), rc); - - /* we add the URI->WORKER MAP since workers using AJP14 - will feed it */ - worker_env.uri_to_worker = conf->uw_map; - worker_env.virtual = "*"; /* for now */ -#if ((AP_MODULE_MAGIC_AT_LEAST(20051115,4)) && !defined(API_COMPATIBILITY)) || (MODULE_MAGIC_NUMBER_MAJOR >= 20060905) - worker_env.server_name = (char *)ap_get_server_description(); -#else - worker_env.server_name = (char *)ap_get_server_version(); -#endif - worker_env.pool = pconf; - - if (wc_open(jk_worker_properties, &worker_env, conf->log)) { - ap_add_version_component(pconf, JK_EXPOSED_VERSION); - jk_log(conf->log, JK_LOG_INFO, - "%s initialized", - JK_FULL_EXPOSED_VERSION); - } - else { - ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, - "Error in creating the workers." - " Please consult your mod_jk log file '%s'.", conf->log_file); - return JK_FALSE; - } - return JK_TRUE; -} - -static int jk_post_config(apr_pool_t * pconf, - apr_pool_t * plog, - apr_pool_t * ptemp, server_rec * s) -{ - apr_status_t rv; - jk_server_conf_t *conf; - server_rec *srv = s; - const char *err_string = NULL; - void *data = NULL; - - apr_pool_userdata_get(&data, JK_LOG_LOCK_KEY, s->process->pool); - if (data == NULL) { - /* create the jk log lockfiles in the parent */ - if ((rv = apr_global_mutex_create(&jk_log_lock, NULL, - APR_LOCK_DEFAULT, - s->process->pool)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, - "mod_jk: could not create jk_log_lock"); - return HTTP_INTERNAL_SERVER_ERROR; - } - -#if JK_NEED_SET_MUTEX_PERMS -#if (MODULE_MAGIC_NUMBER_MAJOR >= 20090208) - rv = ap_unixd_set_global_mutex_perms(jk_log_lock); -#else - rv = unixd_set_global_mutex_perms(jk_log_lock); -#endif - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, - "mod_jk: Could not set permissions on " - "jk_log_lock; check User and Group directives"); - return HTTP_INTERNAL_SERVER_ERROR; - } -#endif - apr_pool_userdata_set((const void *)jk_log_lock, JK_LOG_LOCK_KEY, - apr_pool_cleanup_null, s->process->pool); - } else { - jk_log_lock = (apr_global_mutex_t *)data; - } - - main_server = s; - jk_log_fps = apr_hash_make(pconf); - - if (!s->is_virtual) { - conf = (jk_server_conf_t *)ap_get_module_config(s->module_config, - &jk_module); - if (conf->was_initialized == JK_FALSE) { - /* step through the servers and open each jk logfile - * and do additional post config initialization. - */ - for (; srv; srv = srv->next) { - jk_server_conf_t *sconf = (jk_server_conf_t *)ap_get_module_config(srv->module_config, - &jk_module); - -/* - * If a virtual server contains no JK directive, httpd shares - * the config structure. But we don't want to share some settings - * by default, especially the JkMount rules. - * Therefore we check, if this config structure really belongs to this - * vhost, otherwise we create a new one and merge. - */ - if (sconf && sconf->s != srv) { - jk_server_conf_t *srvconf = (jk_server_conf_t *)create_jk_config(pconf, srv); - sconf = (jk_server_conf_t *)merge_jk_config(pconf, sconf, srvconf); - ap_set_module_config(srv->module_config, &jk_module, sconf); - - } - - if (sconf && sconf->was_initialized == JK_FALSE) { - sconf->was_initialized = JK_TRUE; - if (open_jklog(srv, pconf)) - return HTTP_INTERNAL_SERVER_ERROR; - sconf->options &= ~sconf->exclude_options; - if (sconf->uri_to_context) { - if (!uri_worker_map_alloc(&(sconf->uw_map), - sconf->uri_to_context, sconf->log)) - jk_error_exit(JKLOG_MARK, APLOG_EMERG, srv, - srv->process->pool, "Memory error"); - if (sconf->options & JK_OPT_REJECTUNSAFE) - sconf->uw_map->reject_unsafe = 1; - else - sconf->uw_map->reject_unsafe = 0; - if (sconf->mount_file) { - sconf->uw_map->fname = sconf->mount_file; - sconf->uw_map->reload = sconf->mount_file_reload; - uri_worker_map_switch(sconf->uw_map, sconf->log); - uri_worker_map_load(sconf->uw_map, sconf->log); - } - } - else { - if (sconf->mountcopy == JK_TRUE) { - sconf->uw_map = conf->uw_map; - } - } - if (sconf->format_string) { - sconf->format = - parse_request_log_string(pconf, sconf->format_string, &err_string); - if (sconf->format == NULL) - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "JkRequestLogFormat format array NULL"); - } - if (sconf->envvars && sconf->envvars_has_own) { - int i; - const apr_array_header_t *arr; - const apr_table_entry_t *elts; - envvar_item *item; - const char *envvar_def; - - arr = apr_table_elts(sconf->envvars); - if (arr) { - elts = (const apr_table_entry_t *)arr->elts; - for (i = 0; i < arr->nelts; ++i) { - item = (envvar_item *)apr_array_push(sconf->envvar_items); - if (!item) - return HTTP_INTERNAL_SERVER_ERROR; - item->name = elts[i].key; - envvar_def = apr_table_get(sconf->envvars_def, elts[i].key); - if (envvar_def && !strcmp("1", envvar_def) ) { - item->value = elts[i].val; - item->has_default = 1; - } - else { - item->value = ""; - item->has_default = 0; - } - } - } - } - } - } - conf->was_initialized = JK_TRUE; - if (init_jk(pconf, conf, s) == JK_FALSE) - return HTTP_INTERNAL_SERVER_ERROR; - if (conf->uw_map) { - uri_worker_map_ext(conf->uw_map, conf->log); - uri_worker_map_switch(conf->uw_map, conf->log); - } - for (srv = s; srv; srv = srv->next) { - jk_server_conf_t *sconf = (jk_server_conf_t *)ap_get_module_config(srv->module_config, - &jk_module); - if (conf->uw_map != sconf->uw_map && sconf->uw_map) { - uri_worker_map_ext(sconf->uw_map, sconf->log); - uri_worker_map_switch(sconf->uw_map, sconf->log); - } - } - - } - } - - return OK; -} - -/** Use the internal mod_jk mappings to find if this is a request for - * tomcat and what worker to use. - */ -static int jk_translate(request_rec * r) -{ - ap_set_module_config(r->request_config, &jk_module, NULL); - - if (!r->proxyreq) { - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(r->server-> - module_config, - &jk_module); - - if (conf) { - const char *worker; - if ((r->handler != NULL) && (!strcmp(r->handler, JK_HANDLER))) { - /* Somebody already set the handler, probably manual config - * or "native" configuration, no need for extra overhead - */ - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "Manually mapped, no need to call uri_to_worker"); - return DECLINED; - } - - if (apr_table_get(r->subprocess_env, "no-jk")) { - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "Into translate no-jk env var detected for uri=%s, declined", - r->uri); - - return DECLINED; - } - - /* Special case to make sure that apache can serve a directory - listing if there are no matches for the DirectoryIndex and - Tomcat webapps are mapped into apache using JkAutoAlias. */ - if (r->main != NULL && r->main->handler != NULL && - (conf->alias_dir != NULL) && - !strcmp(r->main->handler, DIR_MAGIC_TYPE)) { - - /* Append the request uri to the JkAutoAlias directory and - determine if the file exists. */ - char *clean_uri; - apr_finfo_t finfo; - finfo.filetype = APR_NOFILE; - clean_uri = apr_pstrdup(r->pool, r->uri); - ap_no2slash(clean_uri); - /* Map uri to a context static file */ - if (strlen(clean_uri) > 1) { - char *context_path = NULL; - - context_path = apr_pstrcat(r->pool, conf->alias_dir, - ap_os_escape_path(r->pool, - clean_uri, - 1), NULL); - if (context_path != NULL) { - apr_stat(&finfo, context_path, APR_FINFO_TYPE, - r->pool); - } - } - if (finfo.filetype != APR_REG) { - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "JkAutoAlias, no DirectoryIndex file for URI %s", - r->uri); - return DECLINED; - } - } - if (!conf->uw_map) { - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "missing uri map for %s:%s", - conf->s->server_hostname ? conf->s->server_hostname : "_default_", - r->uri); - return DECLINED; - } - else { - rule_extension_t *e; - worker = map_uri_to_worker_ext(conf->uw_map, r->uri, - NULL, &e, NULL, conf->log); - ap_set_module_config(r->request_config, &jk_module, e); - } - - if (worker) { - r->handler = apr_pstrdup(r->pool, JK_HANDLER); - apr_table_setn(r->notes, JK_NOTE_WORKER_NAME, worker); - - /* This could be a sub-request, possibly from mod_dir */ - /* Also add the the HANDLER to the main request */ - if (r->main) { - r->main->handler = apr_pstrdup(r->main->pool, JK_HANDLER); - apr_table_setn(r->main->notes, JK_NOTE_WORKER_NAME, worker); - } - - return OK; - } - else if (conf->alias_dir != NULL) { - char *clean_uri = apr_pstrdup(r->pool, r->uri); - ap_no2slash(clean_uri); - /* Automatically map uri to a context static file */ - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "check alias_dir: %s", - conf->alias_dir); - if (strlen(clean_uri) > 1) { - /* Get the context directory name */ - char *context_dir = NULL; - char *context_path = NULL; - char *child_dir = NULL; - char *index = clean_uri; - char *suffix = strchr(index + 1, '/'); - if (suffix != NULL) { - int size = suffix - index; - context_dir = apr_pstrndup(r->pool, index, size); - /* Get the context child directory name */ - index = index + size + 1; - suffix = strchr(index, '/'); - if (suffix != NULL) { - size = suffix - index; - child_dir = apr_pstrndup(r->pool, index, size); - } - else { - child_dir = index; - } - /* Deny access to WEB-INF and META-INF directories */ - if (child_dir != NULL) { - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "AutoAlias child_dir: %s", - child_dir); - if (!strcasecmp(child_dir, "WEB-INF") - || !strcasecmp(child_dir, "META-INF")) { - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "AutoAlias HTTP_NOT_FOUND for URI: %s", - r->uri); - return HTTP_NOT_FOUND; - } - } - } - else { - context_dir = apr_pstrdup(r->pool, index); - } - - context_path = apr_pstrcat(r->pool, conf->alias_dir, - ap_os_escape_path(r->pool, - context_dir, - 1), NULL); - if (context_path != NULL) { - apr_finfo_t finfo; - finfo.filetype = APR_NOFILE; - apr_stat(&finfo, context_path, APR_FINFO_TYPE, - r->pool); - if (finfo.filetype == APR_DIR) { - char *escurl = - ap_os_escape_path(r->pool, clean_uri, 1); - char *ret = - apr_pstrcat(r->pool, conf->alias_dir, escurl, - NULL); - /* Add code to verify real path ap_os_canonical_name */ - if (ret != NULL) { - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "AutoAlias OK for file: %s", - ret); - r->filename = ret; - return OK; - } - } - else { - /* Deny access to war files in web app directory */ - int size = strlen(context_dir); - if (size > 4 - && !strcasecmp(context_dir + (size - 4), - ".war")) { - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "AutoAlias HTTP_FORBIDDEN for URI: %s", - r->uri); - return HTTP_FORBIDDEN; - } - } - } - } - } - else { - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "no match for %s found", - r->uri); - } - } - } - - return DECLINED; -} - -/* bypass the directory_walk and file_walk for non-file requests */ -static int jk_map_to_storage(request_rec * r) -{ - - if (!r->proxyreq && !apr_table_get(r->notes, JK_NOTE_WORKER_NAME)) { - jk_server_conf_t *conf = - (jk_server_conf_t *) ap_get_module_config(r->server-> - module_config, - &jk_module); - - if (conf) { - const char *worker; - if ((r->handler != NULL) && (!strcmp(r->handler, JK_HANDLER))) { - /* Somebody already set the handler, probably manual config - * or "native" configuration, no need for extra overhead - */ - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "Manually mapped, no need to call uri_to_worker"); - return DECLINED; - } - - if (apr_table_get(r->subprocess_env, "no-jk")) { - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "Into map_to_storage no-jk env var detected for uri=%s, declined", - r->uri); - - return DECLINED; - } - if (!conf->uw_map) { - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "missing uri map for %s:%s", - conf->s->server_hostname ? conf->s->server_hostname : "_default_", - r->uri); - return DECLINED; - } - else { - rule_extension_t *e; - worker = map_uri_to_worker_ext(conf->uw_map, r->uri, - NULL, &e, NULL, conf->log); - ap_set_module_config(r->request_config, &jk_module, e); - } - - if (worker) { - r->handler = apr_pstrdup(r->pool, JK_HANDLER); - apr_table_setn(r->notes, JK_NOTE_WORKER_NAME, worker); - - /* This could be a sub-request, possibly from mod_dir */ - if (r->main) - apr_table_setn(r->main->notes, JK_NOTE_WORKER_NAME, worker); - - } - else { - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "no match for %s found", - r->uri); - if (conf->strip_session == JK_TRUE && - conf->strip_session_name) { - char *jsessionid; - if (r->uri) { - jsessionid = strstr(r->uri, conf->strip_session_name); - if (jsessionid) { - if (JK_IS_DEBUG_LEVEL(conf->log)) - jk_log(conf->log, JK_LOG_DEBUG, - "removing session identifier [%s] for non servlet url [%s]", - jsessionid, r->uri); - *jsessionid = '\0'; - } - } - if (r->filename) { - jsessionid = strstr(r->filename, conf->strip_session_name); - if (jsessionid) - *jsessionid = '\0'; - } - return DECLINED; - } - } - } - } - - if (apr_table_get(r->notes, JK_NOTE_WORKER_NAME)) { - - /* First find just the name of the file, no directory */ - r->filename = (char *)apr_filepath_name_get(r->uri); - - /* Only if sub-request for a directory, most likely from mod_dir */ - if (r->main && r->main->filename && - (!apr_filepath_name_get(r->main->filename) || - !strlen(apr_filepath_name_get(r->main->filename)))) { - - /* The filename from the main request will be set to what should - * be picked up, aliases included. Tomcat will need to know about - * those aliases or things won't work for them. Normal files should - * be fine. */ - - /* Need absolute path to stat */ - if (apr_filepath_merge(&r->filename, - r->main->filename, r->filename, - APR_FILEPATH_SECUREROOT | - APR_FILEPATH_TRUENAME, r->pool) - != APR_SUCCESS) { - return DECLINED; /* We should never get here, very bad */ - } - - /* Stat the file so that mod_dir knows it's there */ - apr_stat(&r->finfo, r->filename, APR_FINFO_TYPE, r->pool); - } - - return OK; - } - return DECLINED; -} - -static void jk_register_hooks(apr_pool_t * p) -{ - ap_hook_handler(jk_handler, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_post_config(jk_post_config, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_child_init(jk_child_init, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_translate_name(jk_translate, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_map_to_storage(jk_map_to_storage, NULL, NULL, APR_HOOK_MIDDLE); -} - -module AP_MODULE_DECLARE_DATA jk_module = { - STANDARD20_MODULE_STUFF, - NULL, /* dir config creater */ - NULL, /* dir merger --- default is to override */ - create_jk_config, /* server config */ - merge_jk_config, /* merge server config */ - jk_cmds, /* command ap_table_t */ - jk_register_hooks /* register hooks */ -}; |