· 8 years ago · Apr 18, 2018, 07:24 PM
1static const command_rec jk_cmds[] = {
2 /*
3 * JkWorkersFile specifies a full path to the location of the worker
4 * properties file.
5 *
6 * This file defines the different workers used by apache to redirect
7 * servlet requests.
8 */
9 AP_INIT_TAKE1("JkWorkersFile", jk_set_worker_file, NULL, RSRC_CONF,
10 "the name of a worker file for the Tomcat servlet containers"),
11
12 /*
13 * JkMountFile specifies a full path to the location of the
14 * uriworker properties file.
15 *
16 * This file defines the different mapping for workers used by apache
17 * to redirect servlet requests.
18 */
19 AP_INIT_TAKE1("JkMountFile", jk_set_mount_file, NULL, RSRC_CONF,
20 "the name of a mount file for the Tomcat servlet uri mapping"),
21
22 /*
23 * JkMountFileReload specifies the reload check interval for the
24 * uriworker properties file.
25 *
26 * Default value is: JK_URIMAP_DEF_RELOAD
27 */
28 AP_INIT_TAKE1("JkMountFileReload", jk_set_mount_file_reload, NULL, RSRC_CONF,
29 "the reload check interval of the mount file"),
30
31 /*
32 * JkMount mounts a url prefix to a worker (the worker need to be
33 * defined in the worker properties file.
34 */
35 AP_INIT_TAKE12("JkMount", jk_mount_context, NULL, RSRC_CONF|ACCESS_CONF,
36 "A mount point from a context to a Tomcat worker"),
37
38 /*
39 * JkUnMount unmounts a url prefix to a worker (the worker need to be
40 * defined in the worker properties file.
41 */
42 AP_INIT_TAKE12("JkUnMount", jk_unmount_context, NULL, RSRC_CONF|ACCESS_CONF,
43 "A no mount point from a context to a Tomcat worker"),
44
45 /*
46 * JkMountCopy specifies if mod_jk should copy the mount points
47 * from the main server to the virtual servers.
48 */
49 AP_INIT_TAKE1("JkMountCopy", jk_set_mountcopy, NULL, RSRC_CONF,
50 "Should the base server mounts be copied to the virtual server"),
51
52 /*
53 * JkStripSession specifies if mod_jk should strip the ;jsessionid
54 * from the unmapped urls
55 */
56 AP_INIT_FLAG("JkStripSession", jk_set_strip_session, NULL, RSRC_CONF,
57 "Should the server strip the jsessionid from unmapped URLs"),
58
59 /*
60 * JkLogFile & JkLogLevel specifies to where should the plugin log
61 * its information and how much.
62 * JkLogStampFormat specify the time-stamp to be used on log
63 */
64 AP_INIT_TAKE1("JkLogFile", jk_set_log_file, NULL, RSRC_CONF,
65 "Full path to the Tomcat module log file"),
66
67 AP_INIT_TAKE1("JkShmFile", jk_set_shm_file, NULL, RSRC_CONF,
68 "Full path to the Tomcat module shared memory file"),
69
70 AP_INIT_TAKE1("JkShmSize", jk_set_shm_size, NULL, RSRC_CONF,
71 "Size of the shared memory file in KBytes"),
72
73 AP_INIT_TAKE1("JkLogLevel", jk_set_log_level, NULL, RSRC_CONF,
74 "The Tomcat module log level, can be debug, "
75 "info, error or emerg"),
76 AP_INIT_TAKE1("JkLogStampFormat", jk_set_log_fmt, NULL, RSRC_CONF,
77 "The Tomcat module log format, follow strftime syntax"),
78 AP_INIT_TAKE1("JkRequestLogFormat", jk_set_request_log_format, NULL,
79 RSRC_CONF,
80 "The mod_jk module request log format string"),
81
82 /*
83 * Automatically Alias webapp context directories into the Apache
84 * document space.
85 */
86 AP_INIT_TAKE1("JkAutoAlias", jk_set_auto_alias, NULL, RSRC_CONF,
87 "The mod_jk module automatic context apache alias directory"),
88
89 /*
90 * Enable worker name to be set in an environment variable.
91 * this way one can use LocationMatch together with mod_end,
92 * mod_setenvif and mod_rewrite to set the target worker.
93 * Use this in combination with SetHandler jakarta-servlet to
94 * make mod_jk the handler for the request.
95 *
96 */
97 AP_INIT_TAKE1("JkWorkerIndicator", jk_set_worker_indicator, NULL, RSRC_CONF,
98 "Name of the Apache environment that contains the worker name"),
99
100 /*
101 * Apache has multiple SSL modules (for example apache_ssl, stronghold
102 * IHS ...). Each of these can have a different SSL environment names
103 * The following properties let the administrator specify the envoiroment
104 * variables names.
105 *
106 * HTTPS - indication for SSL
107 * CERTS - Base64-Der-encoded client certificates.
108 * CIPHER - A string specifing the ciphers suite in use.
109 * KEYSIZE - Size of Key used in dialogue (#bits are secure)
110 * SESSION - A string specifing the current SSL session.
111 */
112 AP_INIT_TAKE1("JkHTTPSIndicator", jk_set_https_indicator, NULL, RSRC_CONF,
113 "Name of the Apache environment that contains SSL indication"),
114 AP_INIT_TAKE1("JkCERTSIndicator", jk_set_certs_indicator, NULL, RSRC_CONF,
115 "Name of the Apache environment that contains SSL client certificates"),
116 AP_INIT_TAKE1("JkCIPHERIndicator", jk_set_cipher_indicator, NULL,
117 RSRC_CONF,
118 "Name of the Apache environment that contains SSL client cipher"),
119 AP_INIT_TAKE1("JkSESSIONIndicator", jk_set_session_indicator, NULL,
120 RSRC_CONF,
121 "Name of the Apache environment that contains SSL session"),
122 AP_INIT_TAKE1("JkKEYSIZEIndicator", jk_set_key_size_indicator, NULL,
123 RSRC_CONF,
124 "Name of the Apache environment that contains SSL key size in use"),
125 AP_INIT_TAKE1("JkCERTCHAINPrefix", jk_set_certchain_prefix, NULL, RSRC_CONF,
126 "Name of the Apache environment (prefix) that contains SSL client chain certificates"),
127 AP_INIT_FLAG("JkExtractSSL", jk_set_enable_ssl, NULL, RSRC_CONF,
128 "Turns on SSL processing and information gathering by mod_jk"),
129
130 /*
131 * Options to tune mod_jk configuration
132 * for now we understand :
133 * +ForwardSSLKeySize => Forward SSL Key Size, to follow 2.3 specs but may broke old TC 3.2
134 * -ForwardSSLKeySize => Don't Forward SSL Key Size, will make mod_jk works with all TC release
135 * ForwardURICompat => Forward URI normally, less spec compliant but mod_rewrite compatible (old TC)
136 * ForwardURICompatUnparsed => Forward URI as unparsed, spec compliant but broke mod_rewrite (old TC)
137 * ForwardURIEscaped => Forward URI escaped and Tomcat (3.3 rc2) stuff will do the decoding part
138 * +ForwardSSLCertChain => Forward SSL certificate chain
139 * -ForwardSSLCertChain => Don't forward SSL certificate chain
140 */
141 AP_INIT_RAW_ARGS("JkOptions", jk_set_options, NULL, RSRC_CONF,
142 "Set one of more options to configure the mod_jk module"),
143
144 /*
145 * JkEnvVar let user defines envs var passed from WebServer to
146 * Servlet Engine
147 */
148 AP_INIT_TAKE12("JkEnvVar", jk_add_env_var, NULL, RSRC_CONF,
149 "Adds a name of environment variable and an optional value "
150 "that should be sent to servlet-engine"),
151
152 AP_INIT_RAW_ARGS("JkWorkerProperty", jk_set_worker_property,
153 NULL, RSRC_CONF,
154 "Set workers.properties formated directive"),
155
156 {NULL}
157};
158
159/* ========================================================================= */
160/* The JK module handlers */
161/* ========================================================================= */
162
163/** Util - cleanup shmem.
164 */
165static apr_status_t jk_cleanup_shmem(void *data)
166{
167 jk_shm_close();
168 return APR_SUCCESS;
169}
170
171/** Main service method, called to forward a request to tomcat
172 */
173static int jk_handler(request_rec * r)
174{
175 const char *worker_name;
176 jk_server_conf_t *xconf;
177 int rc, dmt = 1;
178
179 /* We do DIR_MAGIC_TYPE here to make sure TC gets all requests, even
180 * if they are directory requests, in case there are no static files
181 * visible to Apache and/or DirectoryIndex was not used. This is only
182 * used when JkOptions has ForwardDirectories set. */
183 /* Not for me, try next handler */
184 if (strcmp(r->handler, JK_HANDLER)
185 && (dmt = strcmp(r->handler, DIR_MAGIC_TYPE)))
186 return DECLINED;
187
188 xconf = (jk_server_conf_t *) ap_get_module_config(r->server->module_config,
189 &jk_module);
190 JK_TRACE_ENTER(xconf->log);
191 if (apr_table_get(r->subprocess_env, "no-jk")) {
192 if (JK_IS_DEBUG_LEVEL(xconf->log))
193 jk_log(xconf->log, JK_LOG_DEBUG,
194 "Into handler no-jk env var detected for uri=%s, declined",
195 r->uri);
196
197 JK_TRACE_EXIT(xconf->log);
198 return DECLINED;
199 }
200
201 /* Was the option to forward directories to Tomcat set? */
202 if (!dmt && !(xconf->options & JK_OPT_FWDDIRS)) {
203 JK_TRACE_EXIT(xconf->log);
204 return DECLINED;
205 }
206 worker_name = apr_table_get(r->notes, JK_NOTE_WORKER_NAME);
207
208 /* Set up r->read_chunked flags for chunked encoding, if present */
209 if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != APR_SUCCESS) {
210 JK_TRACE_EXIT(xconf->log);
211 return rc;
212 }
213
214 if (worker_name == NULL) {
215 /* we may be here because of a manual directive ( that overrides
216 translate and
217 sets the handler directly ). We still need to know the worker.
218 */
219 worker_name = apr_table_get(r->subprocess_env, xconf->worker_indicator);
220 if (worker_name) {
221 /* The JkWorkerIndicator environment variable has
222 * been used to explicitely set the worker without JkMount.
223 * This is useful in combination with LocationMatch or mod_rewrite.
224 */
225 if (JK_IS_DEBUG_LEVEL(xconf->log))
226 jk_log(xconf->log, JK_LOG_DEBUG,
227 "Retrieved worker (%s) from env %s for %s",
228 worker_name, xconf->worker_indicator, r->uri);
229 }
230 else if (worker_env.num_of_workers == 1) {
231 /** We have a single worker ( the common case ).
232 ( lb is a bit special, it should count as a single worker but
233 I'm not sure how ). We also have a manual config directive that
234 explicitely give control to us. */
235 worker_name = worker_env.worker_list[0];
236 if (JK_IS_DEBUG_LEVEL(xconf->log))
237 jk_log(xconf->log, JK_LOG_DEBUG,
238 "Single worker (%s) configuration for %s",
239 worker_name, r->uri);
240 }
241 else {
242 if (!xconf->uw_map) {
243 if (JK_IS_DEBUG_LEVEL(xconf->log))
244 jk_log(xconf->log, JK_LOG_DEBUG,
245 "missing uri map for %s:%s",
246 xconf->s->server_hostname ? xconf->s->server_hostname : "_default_",
247 r->uri);
248 }
249 else
250 worker_name = map_uri_to_worker(xconf->uw_map, r->uri,
251 NULL, xconf->log);
252
253 if (worker_name == NULL && worker_env.num_of_workers) {
254 worker_name = worker_env.worker_list[0];
255 if (JK_IS_DEBUG_LEVEL(xconf->log))
256 jk_log(xconf->log, JK_LOG_DEBUG,
257 "Using first worker (%s) from %d workers for %s",
258 worker_name, worker_env.num_of_workers, r->uri);
259 }
260 }
261 if (worker_name)
262 apr_table_setn(r->notes, JK_NOTE_WORKER_NAME, worker_name);
263 }
264
265 if (JK_IS_DEBUG_LEVEL(xconf->log))
266 jk_log(xconf->log, JK_LOG_DEBUG, "Into handler %s worker=%s"
267 " r->proxyreq=%d",
268 r->handler, STRNULL_FOR_NULL(worker_name), r->proxyreq);
269
270 /* If this is a proxy request, we'll notify an error */
271 if (r->proxyreq) {
272 jk_log(xconf->log, JK_LOG_INFO, "Proxy request for worker=%s"
273 " is not allowed",
274 STRNULL_FOR_NULL(worker_name));
275 JK_TRACE_EXIT(xconf->log);
276 return HTTP_INTERNAL_SERVER_ERROR;
277 }
278
279 if (worker_name) {
280 jk_worker_t *worker = wc_get_worker_for_name(worker_name, xconf->log);
281
282 /* If the remote client has aborted, just ignore the request */
283 if (r->connection->aborted) {
284 jk_log(xconf->log, JK_LOG_INFO, "Client connection aborted for"
285 " worker=%s",
286 worker_name);
287 JK_TRACE_EXIT(xconf->log);
288 return OK;
289 }
290
291 if (worker) {
292 long micro, seconds;
293 char *duration = NULL;
294 apr_time_t rd;
295 apr_time_t request_begin = 0;
296 int is_error = HTTP_INTERNAL_SERVER_ERROR;
297 int rc = JK_FALSE;
298 apache_private_data_t private_data;
299 jk_ws_service_t s;
300 jk_pool_atom_t buf[SMALL_POOL_SIZE];
301 jk_open_pool(&private_data.p, buf, sizeof(buf));
302
303 private_data.read_body_started = JK_FALSE;
304 private_data.r = r;
305
306 wc_maintain(xconf->log);
307
308 jk_init_ws_service(&s);
309 /* Update retries for this worker */
310 s.retries = worker->retries;
311 s.ws_private = &private_data;
312 s.pool = &private_data.p;
313 apr_table_setn(r->notes, JK_NOTE_WORKER_TYPE,
314 wc_get_name_for_type(worker->type, xconf->log));
315
316 request_begin = apr_time_now();
317
318 if (init_ws_service(&private_data, &s, xconf)) {
319 jk_endpoint_t *end = NULL;
320
321 /* Use per/thread pool ( or "context" ) to reuse the
322 endpoint. It's a bit faster, but I don't know
323 how to deal with load balancing - but it's usefull for JNI
324 */
325
326 /* worker->get_endpoint might fail if we are out of memory so check */
327 /* and handle it */
328 if (worker->get_endpoint(worker, &end, xconf->log)) {
329 rc = end->service(end, &s, xconf->log,
330 &is_error);
331 end->done(&end, xconf->log);
332 if (s.content_read < s.content_length ||
333 (s.is_chunked && !s.no_more_chunks)) {
334
335 /*
336 * If the servlet engine didn't consume all of the
337 * request data, consume and discard all further
338 * characters left to read from client
339 */
340 char *buff = apr_palloc(r->pool, 2048);
341 if (buff != NULL) {
342 int rd;
343 while ((rd =
344 ap_get_client_block(r, buff, 2048)) > 0) {
345 s.content_read += rd;
346 }
347 }
348 }
349 }
350 else { /* this means we couldn't get an endpoint */
351 jk_log(xconf->log, JK_LOG_ERROR, "Could not get endpoint"
352 " for worker=%s",
353 worker_name);
354 rc = 0; /* just to make sure that we know we've failed */
355 }
356 }
357 else {
358 jk_log(xconf->log, JK_LOG_ERROR, "Could not init service"
359 " for worker=%s",
360 worker_name);
361 jk_close_pool(&private_data.p);
362 JK_TRACE_EXIT(xconf->log);
363 return HTTP_INTERNAL_SERVER_ERROR;
364 }
365 rd = apr_time_now() - request_begin;
366 seconds = (long)apr_time_sec(rd);
367 micro = (long)(rd - apr_time_from_sec(seconds));
368
369 duration = apr_psprintf(r->pool, "%.1ld.%.6ld", seconds, micro);
370 apr_table_setn(r->notes, JK_NOTE_REQUEST_DURATION, duration);
371 if (s.route && *s.route)
372 apr_table_setn(r->notes, JK_NOTE_WORKER_ROUTE, s.route);
373
374 if (xconf->format != NULL) {
375 request_log_transaction(r, xconf);
376 }
377
378 jk_close_pool(&private_data.p);
379
380 if (rc > 0) {
381 /* If tomcat returned no body and the status is not OK,
382 let apache handle the error code */
383
384 if (!r->sent_bodyct && r->status >= HTTP_BAD_REQUEST) {
385 jk_log(xconf->log, JK_LOG_INFO, "No body with status=%d"
386 " for worker=%s",
387 r->status, worker_name);
388 JK_TRACE_EXIT(xconf->log);
389 return r->status;
390 }
391 if (JK_IS_DEBUG_LEVEL(xconf->log))
392 jk_log(xconf->log, JK_LOG_DEBUG, "Service finished"
393 " with status=%d for worker=%s",
394 r->status, worker_name);
395 JK_TRACE_EXIT(xconf->log);
396 return OK; /* NOT r->status, even if it has changed. */
397 }
398 else if (rc == JK_CLIENT_ERROR) {
399 if (is_error != HTTP_REQUEST_ENTITY_TOO_LARGE)
400 r->connection->aborted = 1;
401 jk_log(xconf->log, JK_LOG_INFO, "Aborting connection"
402 " for worker=%s",
403 worker_name);
404 JK_TRACE_EXIT(xconf->log);
405 return is_error;
406 }
407 else {
408 jk_log(xconf->log, JK_LOG_INFO, "Service error=%d"
409 " for worker=%s",
410 rc, worker_name);
411 JK_TRACE_EXIT(xconf->log);
412 return is_error;
413 }
414 }
415 else {
416 jk_log(xconf->log, JK_LOG_INFO, "Could not find a worker"
417 " for worker name=%s",
418 worker_name);
419 JK_TRACE_EXIT(xconf->log);
420 return HTTP_INTERNAL_SERVER_ERROR;
421 }
422 }
423
424 JK_TRACE_EXIT(xconf->log);
425 return DECLINED;
426}
427
428/** Standard apache hook, cleanup jk
429 */
430static apr_status_t jk_apr_pool_cleanup(void *data)
431{
432 server_rec *s = data;
433
434 if (jk_worker_properties) {
435 jk_map_free(&jk_worker_properties);
436 jk_worker_properties = NULL;
437 jk_worker_file = NULL;
438 jk_mount_copy_all = JK_FALSE;
439 }
440
441 while (NULL != s) {
442 jk_server_conf_t *conf =
443 (jk_server_conf_t *) ap_get_module_config(s->module_config,
444 &jk_module);
445
446 if (conf && conf->was_initialized == JK_TRUE) {
447 /* On pool cleanup pass NULL for the jk_logger to
448 prevent segmentation faults on Windows because
449 we can't guarantee what order pools get cleaned
450 up between APR implementations. */
451 wc_close(NULL);
452 if (conf->uri_to_context) {
453 jk_map_free(&conf->uri_to_context);
454 /* We cannot have allocated uw_map
455 * unless we've allocated uri_to_context
456 */
457 if (conf->uw_map)
458 uri_worker_map_free(&conf->uw_map, NULL);
459 }
460 conf->was_initialized = JK_FALSE;
461 }
462 s = s->next;
463 }
464 return APR_SUCCESS;
465}
466
467/** Create default jk_config. XXX This is mostly server-independent,
468 all servers are using something similar - should go to common.
469 */
470static void *create_jk_config(apr_pool_t * p, server_rec * s)
471{
472 jk_server_conf_t *c =
473 (jk_server_conf_t *) apr_pcalloc(p, sizeof(jk_server_conf_t));
474
475 c->was_initialized = JK_FALSE;
476
477 if (s->is_virtual) {
478 c->mountcopy = JK_UNSET;
479 c->mount_file_reload = JK_UNSET;
480 c->log_level = JK_UNSET;
481 c->ssl_enable = JK_UNSET;
482 c->strip_session = JK_UNSET;
483 } else {
484 if (!jk_map_alloc(&(c->uri_to_context))) {
485 ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Memory error");
486 }
487 c->mountcopy = JK_FALSE;
488 c->mount_file_reload = JK_URIMAP_DEF_RELOAD;
489 c->log_level = JK_LOG_DEF_LEVEL;
490 c->options = JK_OPT_FWDURIDEFAULT;
491 c->worker_indicator = JK_ENV_WORKER_NAME;
492 /*
493 * By default we will try to gather SSL info.
494 * Disable this functionality through JkExtractSSL
495 */
496 c->ssl_enable = JK_TRUE;
497 /*
498 * The defaults ssl indicators match those in mod_ssl (seems
499 * to be in more use).
500 */
501 c->https_indicator = JK_ENV_HTTPS;
502 c->certs_indicator = JK_ENV_CERTS;
503 c->cipher_indicator = JK_ENV_CIPHER;
504 c->certchain_prefix = JK_ENV_CERTCHAIN_PREFIX;
505 c->session_indicator = JK_ENV_SESSION;
506 c->key_size_indicator = JK_ENV_KEY_SIZE;
507 c->strip_session = JK_FALSE;
508 }
509 c->envvars_has_own = JK_FALSE;
510
511 c->s = s;
512 apr_pool_cleanup_register(p, s, jk_apr_pool_cleanup, jk_apr_pool_cleanup);
513 return c;
514}
515
516
517/*
518 * Utility - copy items from apr table src to dst,
519 * for keys that exist in src but not in dst.
520 */
521static void merge_apr_table(apr_table_t *src, apr_table_t *dst)
522{
523 int i;
524 const apr_array_header_t *arr;
525 const apr_table_entry_t *elts;
526
527 arr = apr_table_elts(src);
528 elts = (const apr_table_entry_t *)arr->elts;
529 for (i = 0; i < arr->nelts; ++i) {
530 if (!apr_table_get(dst, elts[i].key)) {
531 apr_table_setn(dst, elts[i].key, elts[i].val);
532 }
533 }
534}
535
536
537/** Standard apache callback, merge jk options specified in <Directory>
538 context or <Host>.
539 */
540static void *merge_jk_config(apr_pool_t * p, void *basev, void *overridesv)
541{
542 jk_server_conf_t *base = (jk_server_conf_t *) basev;
543 jk_server_conf_t *overrides = (jk_server_conf_t *) overridesv;
544
545 if (!overrides->log_file)
546 overrides->log_file = base->log_file;
547 if (overrides->log_level == JK_UNSET)
548 overrides->log_level = base->log_level;
549
550 if (!overrides->stamp_format_string)
551 overrides->stamp_format_string = base->stamp_format_string;
552 if (!overrides->format_string)
553 overrides->format_string = base->format_string;
554
555 if (!overrides->worker_indicator)
556 overrides->worker_indicator = base->worker_indicator;
557
558 if (overrides->ssl_enable == JK_UNSET)
559 overrides->ssl_enable = base->ssl_enable;
560 if (!overrides->https_indicator)
561 overrides->https_indicator = base->https_indicator;
562 if (!overrides->certs_indicator)
563 overrides->certs_indicator = base->certs_indicator;
564 if (!overrides->cipher_indicator)
565 overrides->cipher_indicator = base->cipher_indicator;
566 if (!overrides->certchain_prefix)
567 overrides->certchain_prefix = base->certchain_prefix;
568 if (!overrides->session_indicator)
569 overrides->session_indicator = base->session_indicator;
570 if (!overrides->key_size_indicator)
571 overrides->key_size_indicator = base->key_size_indicator;
572
573 overrides->options |= (base->options & ~base->exclude_options);
574
575 if (base->envvars) {
576 if (overrides->envvars && overrides->envvars_has_own) {
577/* merge_apr_table() preserves existing entries in overrides table */
578 merge_apr_table(base->envvars, overrides->envvars);
579 merge_apr_table(base->envvars_def, overrides->envvars_def);
580 }
581 else {
582 overrides->envvars = base->envvars;
583 overrides->envvars_def = base->envvars_def;
584 overrides->envvar_items = base->envvar_items;
585 }
586 }
587
588 if (overrides->mountcopy == JK_UNSET && jk_mount_copy_all == JK_TRUE) {
589 overrides->mountcopy = JK_TRUE;
590 }
591 if (overrides->uri_to_context && overrides->mountcopy == JK_TRUE) {
592/* jk_map_copy() preserves existing entries in overrides map */
593 if (jk_map_copy(base->uri_to_context, overrides->uri_to_context) == JK_FALSE) {
594 jk_error_exit(APLOG_MARK, APLOG_EMERG, overrides->s, p, "Memory error");
595 }
596 if (!overrides->mount_file)
597 overrides->mount_file = base->mount_file;
598 if (!overrides->alias_dir)
599 overrides->alias_dir = base->alias_dir;
600 }
601 if (overrides->mount_file_reload == JK_UNSET)
602 overrides->mount_file_reload = base->mount_file_reload;
603 if (overrides->strip_session == JK_UNSET)
604 overrides->strip_session = base->strip_session;
605
606 return overrides;
607}
608
609static int JK_METHOD jk_log_to_file(jk_logger_t *l, int level,
610 int used, char *what)
611{
612 if (l &&
613 (l->level <= level || level == JK_LOG_REQUEST_LEVEL) &&
614 l->logger_private && what && used > 0) {
615 jk_file_logger_t *p = l->logger_private;
616 if (p->jklogfp) {
617 apr_status_t rv;
618 apr_size_t wrote;
619#if defined(WIN32)
620 what[used++] = '\r';
621#endif
622 what[used++] = '\n';
623 wrote = used;
624 rv = apr_global_mutex_lock(jk_log_lock);
625 if (rv != APR_SUCCESS) {
626 ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
627 "apr_global_mutex_lock(jk_log_lock) failed");
628 /* XXX: Maybe this should be fatal? */
629 }
630 rv = apr_file_write(p->jklogfp, what, &wrote);
631 if (rv != APR_SUCCESS) {
632 char error[256];
633 apr_strerror(rv, error, 254);
634 ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
635 "mod_jk: jk_log_to_file %s failed: %s",
636 what, error);
637 }
638 rv = apr_global_mutex_unlock(jk_log_lock);
639 if (rv != APR_SUCCESS) {
640 ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
641 "apr_global_mutex_unlock(jk_log_lock) failed");
642 /* XXX: Maybe this should be fatal? */
643 }
644 }
645
646 return JK_TRUE;
647 }
648
649 return JK_FALSE;
650}
651
652/*
653** +-------------------------------------------------------+
654** | |
655** | jk logfile support |
656** | |
657** +-------------------------------------------------------+
658*/
659
660static apr_status_t jklog_cleanup(void *d)
661{
662 /* hgomez@20070425 */
663 /* Clean up pointer content */
664 if (d != NULL)
665 *(jk_logger_t **)d = NULL;
666
667 return APR_SUCCESS;
668}
669
670static int open_jklog(server_rec * s, apr_pool_t * p)
671{
672 jk_server_conf_t *conf;
673 const char *fname;
674 apr_status_t rc;
675 apr_file_t *jklogfp;
676 piped_log *pl;
677 jk_logger_t *jkl;
678 jk_file_logger_t *flp;
679 int jklog_flags = (APR_WRITE | APR_APPEND | APR_CREATE);
680 apr_fileperms_t jklog_mode =
681 (APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD);
682
683 conf = ap_get_module_config(s->module_config, &jk_module);
684
685 if (conf->log_file == NULL) {
686 conf->log_file = ap_server_root_relative(p, JK_LOG_DEF_FILE);
687 if (conf->log_file)
688 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
689 "No JkLogFile defined in httpd.conf. "
690 "Using default %s", conf->log_file);
691 }
692 if (*(conf->log_file) == '\0') {
693 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EBADPATH, s,
694 "mod_jk: Invalid JkLogFile EMPTY");
695 conf->log = main_log;
696 return 0;
697 }
698
699 jklogfp = apr_hash_get(jk_log_fps, conf->log_file, APR_HASH_KEY_STRING);
700 if (!jklogfp) {
701 if (*conf->log_file == '|') {
702 if ((pl = ap_open_piped_log(p, conf->log_file + 1)) == NULL) {
703 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
704 "mod_jk: could not open reliable pipe "
705 "to jk log %s", conf->log_file + 1);
706 return -1;
707 }
708 jklogfp = (void *)ap_piped_log_write_fd(pl);
709 }
710 else {
711 fname = ap_server_root_relative(p, conf->log_file);
712 if (!fname) {
713 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EBADPATH, s,
714 "mod_jk: Invalid JkLog " "path %s", conf->log_file);
715 return -1;
716 }
717 if ((rc = apr_file_open(&jklogfp, fname,
718 jklog_flags, jklog_mode, p))
719 != APR_SUCCESS) {
720 ap_log_error(APLOG_MARK, APLOG_ERR, rc, s,
721 "mod_jk: could not open JkLog " "file %s", fname);
722 return -1;
723 }
724 }
725 apr_file_inherit_set(jklogfp);
726 apr_hash_set(jk_log_fps, conf->log_file, APR_HASH_KEY_STRING, jklogfp);
727 }
728 conf->jklogfp = jklogfp;
729 jkl = (jk_logger_t *)apr_palloc(p, sizeof(jk_logger_t));
730 flp = (jk_file_logger_t *) apr_palloc(p, sizeof(jk_file_logger_t));
731 if (jkl && flp) {
732 jkl->log = jk_log_to_file;
733 jkl->level = conf->log_level;
734 jkl->logger_private = flp;
735 flp->jklogfp = conf->jklogfp;
736 conf->log = jkl;
737 jk_set_time_fmt(conf->log, conf->stamp_format_string);
738 if (main_log == NULL) {
739 main_log = conf->log;
740
741 /* hgomez@20070425 */
742 /* Shouldn't we clean both conf->log and main_log ? */
743 /* Also should we pass pointer (ie: main_log) or handle (*main_log) ? */
744 apr_pool_cleanup_register(p, &main_log, jklog_cleanup, jklog_cleanup);
745 }
746
747 return 0;
748 }
749
750 return -1;
751}
752
753
754/** Standard apache callback, initialize jk.
755 */
756static void jk_child_init(apr_pool_t * pconf, server_rec * s)
757{
758 jk_server_conf_t *conf;
759 apr_status_t rv;
760 int rc;
761
762 conf = ap_get_module_config(s->module_config, &jk_module);
763
764 rv = apr_global_mutex_child_init(&jk_log_lock, NULL, pconf);
765 if (rv != APR_SUCCESS) {
766 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
767 "mod_jk: could not init JK log lock in child");
768 }
769
770 JK_TRACE_ENTER(conf->log);
771
772 if ((rc = jk_shm_attach(jk_shm_file, jk_shm_size, conf->log)) == 0) {
773 if (JK_IS_DEBUG_LEVEL(conf->log))
774 jk_log(conf->log, JK_LOG_DEBUG, "Attached shm:%s (%d bytes)",
775 jk_shm_name(), (int) jk_shm_size);
776 apr_pool_cleanup_register(pconf, conf->log, jk_cleanup_shmem,
777 jk_cleanup_shmem);
778 }
779 else
780 jk_log(conf->log, JK_LOG_ERROR, "Attaching shm:%s errno=%d",
781 jk_shm_name(), rc);
782
783 if (JK_IS_DEBUG_LEVEL(conf->log))
784 jk_log(conf->log, JK_LOG_DEBUG, "Initialized %s", JK_EXPOSED_VERSION);
785 JK_TRACE_EXIT(conf->log);
786}
787
788/** Initialize jk, using worker.properties.
789 We also use apache commands ( JkWorker, etc), but this use is
790 deprecated, as we'll try to concentrate all config in
791 workers.properties, urimap.properties, and ajp14 autoconf.
792
793 Apache config will only be used for manual override, using
794 SetHandler and normal apache directives ( but minimal jk-specific
795 stuff )
796*/
797static int init_jk(apr_pool_t * pconf, jk_server_conf_t * conf,
798 server_rec * s)
799{
800 int rc;
801 int is_threaded;
802 int mpm_threads = 1;
803
804 if (!jk_worker_properties)
805 jk_map_alloc(&jk_worker_properties);
806 jk_map_put(jk_worker_properties, "ServerRoot", ap_server_root, NULL);
807
808#if !defined(WIN32) && !defined(NETWARE)
809 if (!jk_shm_file) {
810 jk_shm_file = ap_server_root_relative(pconf, JK_SHM_DEF_FILE);
811 if (jk_shm_file)
812 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
813 "No JkShmFile defined in httpd.conf. "
814 "Using default %s", jk_shm_file);
815 }
816#endif
817 if ((rc = jk_shm_open(jk_shm_file, jk_shm_size, conf->log)) == 0) {
818 if (JK_IS_DEBUG_LEVEL(conf->log))
819 jk_log(conf->log, JK_LOG_DEBUG, "Initialized shm:%s (%d bytes)",
820 jk_shm_name(), (int) jk_shm_size, rc);
821 apr_pool_cleanup_register(pconf, conf->log, jk_cleanup_shmem,
822 jk_cleanup_shmem);
823 }
824 else
825 jk_log(conf->log, JK_LOG_ERROR,
826 "Initializing shm:%s errno=%d. Load balancing workers will not function properly.",
827 jk_shm_name(), rc);
828
829 /* Set default connection cache size for multi-threaded MPMs */
830 if (ap_mpm_query(AP_MPMQ_IS_THREADED, &is_threaded) == APR_SUCCESS &&
831 is_threaded != AP_MPMQ_NOT_SUPPORTED) {
832 if (ap_mpm_query(AP_MPMQ_MAX_THREADS, &mpm_threads) != APR_SUCCESS)
833 mpm_threads = 1;
834 }
835 if (JK_IS_DEBUG_LEVEL(conf->log))
836 jk_log(conf->log, JK_LOG_DEBUG,
837 "Setting default connection pool max size to %d",
838 mpm_threads);
839 jk_set_worker_def_cache_size(mpm_threads);
840
841 if ((jk_worker_file != NULL) &&
842 !jk_map_read_properties(jk_worker_properties, jk_worker_file, NULL,
843 JK_MAP_HANDLE_DUPLICATES, conf->log)) {
844 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
845 "Error in reading worker properties from '%s'",
846 jk_worker_file);
847 return JK_FALSE;
848 }
849
850 if (jk_map_resolve_references(jk_worker_properties, "worker.",
851 1, 1, conf->log) == JK_FALSE) {
852 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
853 "Error in resolving configuration references");
854 return JK_FALSE;
855 }
856
857 /* we add the URI->WORKER MAP since workers using AJP14
858 will feed it */
859 worker_env.uri_to_worker = conf->uw_map;
860 worker_env.virtual = "*"; /* for now */
861#if (AP_MODULE_MAGIC_AT_LEAST(20051115,4))
862 worker_env.server_name = (char *)ap_get_server_description();
863#else
864 worker_env.server_name = (char *)ap_get_server_version();
865#endif
866
867 if (wc_open(jk_worker_properties, &worker_env, conf->log)) {
868 ap_add_version_component(pconf, JK_EXPOSED_VERSION);
869 jk_log(conf->log, JK_LOG_INFO,
870 "%s initialized",
871 JK_EXPOSED_VERSION);
872 }
873 else {
874 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
875 "Error in creating the workers."
876 " Please consult your mod_jk log file '%s'.", conf->log_file);
877 return JK_FALSE;
878 }
879 return JK_TRUE;
880}
881
882static int jk_post_config(apr_pool_t * pconf,
883 apr_pool_t * plog,
884 apr_pool_t * ptemp, server_rec * s)
885{
886 apr_status_t rv;
887 jk_server_conf_t *conf;
888 server_rec *srv = s;
889 const char *err_string = NULL;
890
891 /* create the jk log lockfiles in the parent */
892 if ((rv = apr_global_mutex_create(&jk_log_lock, NULL,
893 APR_LOCK_DEFAULT,
894 pconf)) != APR_SUCCESS) {
895 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
896 "mod_jk: could not create jk_log_lock");
897 return HTTP_INTERNAL_SERVER_ERROR;
898 }
899
900#if JK_NEED_SET_MUTEX_PERMS
901 rv = unixd_set_global_mutex_perms(jk_log_lock);
902 if (rv != APR_SUCCESS) {
903 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
904 "mod_jk: Could not set permissions on "
905 "jk_log_lock; check User and Group directives");
906 return HTTP_INTERNAL_SERVER_ERROR;
907 }
908#endif
909
910 main_server = s;
911 jk_log_fps = apr_hash_make(pconf);
912
913 if (!s->is_virtual) {
914 conf = (jk_server_conf_t *)ap_get_module_config(s->module_config,
915 &jk_module);
916 if (conf->was_initialized == JK_FALSE) {
917 /* step through the servers and open each jk logfile
918 * and do additional post config initialization.
919 */
920 for (; srv; srv = srv->next) {
921 jk_server_conf_t *sconf = (jk_server_conf_t *)ap_get_module_config(srv->module_config,
922 &jk_module);
923
924/*
925 * If a virtual server contains no JK directive, httpd shares
926 * the config structure. But we don't want to share some settings
927 * by default, especially the JkMount rules.
928 * Therefore we check, if this config structure really belongs to this
929 * vhost, otherwise we create a new one and merge.
930 */
931 if (sconf && sconf->s != srv) {
932 jk_server_conf_t *srvconf = (jk_server_conf_t *)create_jk_config(pconf, srv);
933 sconf = (jk_server_conf_t *)merge_jk_config(pconf, sconf, srvconf);
934 ap_set_module_config(srv->module_config, &jk_module, sconf);
935
936 }
937
938 if (sconf && sconf->was_initialized == JK_FALSE) {
939 sconf->was_initialized = JK_TRUE;
940 if (open_jklog(srv, pconf))
941 return HTTP_INTERNAL_SERVER_ERROR;
942 sconf->options &= ~sconf->exclude_options;
943 if (sconf->uri_to_context) {
944 if (!uri_worker_map_alloc(&(sconf->uw_map),
945 sconf->uri_to_context, sconf->log))
946 jk_error_exit(APLOG_MARK, APLOG_EMERG, srv,
947 srv->process->pool, "Memory error");
948 if (sconf->options & JK_OPT_REJECTUNSAFE)
949 sconf->uw_map->reject_unsafe = 1;
950 else
951 sconf->uw_map->reject_unsafe = 0;
952 if (sconf->mount_file) {
953 sconf->uw_map->fname = sconf->mount_file;
954 sconf->uw_map->reload = sconf->mount_file_reload;
955 uri_worker_map_load(sconf->uw_map, sconf->log);
956 }
957 }
958 else {
959 if (sconf->mountcopy == JK_TRUE) {
960 sconf->uw_map = conf->uw_map;
961 }
962 }
963 if (sconf->format_string) {
964 sconf->format =
965 parse_request_log_string(pconf, sconf->format_string, &err_string);
966 if (sconf->format == NULL)
967 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
968 "JkRequestLogFormat format array NULL");
969 }
970 if (sconf->envvars && sconf->envvars_has_own) {
971 int i;
972 const apr_array_header_t *arr;
973 const apr_table_entry_t *elts;
974 envvar_item *item;
975 const char *envvar_def;
976
977 arr = apr_table_elts(sconf->envvars);
978 if (arr) {
979 elts = (const apr_table_entry_t *)arr->elts;
980 for (i = 0; i < arr->nelts; ++i) {
981 item = (envvar_item *)apr_array_push(sconf->envvar_items);
982 if (!item)
983 return HTTP_INTERNAL_SERVER_ERROR;
984 item->name = elts[i].key;
985 envvar_def = apr_table_get(sconf->envvars_def, elts[i].key);
986 if (envvar_def && !strcmp("1", envvar_def) ) {
987 item->value = elts[i].val;
988 item->has_default = 1;
989 }
990 else {
991 item->value = "";
992 item->has_default = 0;
993 }
994 }
995 }
996 }
997 }
998 }
999 conf->was_initialized = JK_TRUE;
1000 if (init_jk(pconf, conf, s) == JK_FALSE)
1001 return HTTP_INTERNAL_SERVER_ERROR;
1002 }
1003 }
1004
1005 return OK;
1006}
1007
1008/** Use the internal mod_jk mappings to find if this is a request for
1009 * tomcat and what worker to use.
1010 */
1011static int jk_translate(request_rec * r)
1012{
1013 if (!r->proxyreq) {
1014 jk_server_conf_t *conf =
1015 (jk_server_conf_t *) ap_get_module_config(r->server->
1016 module_config,
1017 &jk_module);
1018
1019 if (conf) {
1020 const char *worker;
1021 if ((r->handler != NULL) && (!strcmp(r->handler, JK_HANDLER))) {
1022 /* Somebody already set the handler, probably manual config
1023 * or "native" configuration, no need for extra overhead
1024 */
1025 if (JK_IS_DEBUG_LEVEL(conf->log))
1026 jk_log(conf->log, JK_LOG_DEBUG,
1027 "Manually mapped, no need to call uri_to_worker");
1028 return DECLINED;
1029 }
1030
1031 if (apr_table_get(r->subprocess_env, "no-jk")) {
1032 if (JK_IS_DEBUG_LEVEL(conf->log))
1033 jk_log(conf->log, JK_LOG_DEBUG,
1034 "Into translate no-jk env var detected for uri=%s, declined",
1035 r->uri);
1036
1037 return DECLINED;
1038 }
1039
1040 /* Special case to make sure that apache can serve a directory
1041 listing if there are no matches for the DirectoryIndex and
1042 Tomcat webapps are mapped into apache using JkAutoAlias. */
1043 if (r->main != NULL && r->main->handler != NULL &&
1044 (conf->alias_dir != NULL) &&
1045 !strcmp(r->main->handler, DIR_MAGIC_TYPE)) {
1046
1047 /* Append the request uri to the JkAutoAlias directory and
1048 determine if the file exists. */
1049 char *clean_uri;
1050 apr_finfo_t finfo;
1051 finfo.filetype = APR_NOFILE;
1052 clean_uri = apr_pstrdup(r->pool, r->uri);
1053 ap_no2slash(clean_uri);
1054 /* Map uri to a context static file */
1055 if (strlen(clean_uri) > 1) {
1056 char *context_path = NULL;
1057
1058 context_path = apr_pstrcat(r->pool, conf->alias_dir,
1059 ap_os_escape_path(r->pool,
1060 clean_uri,
1061 1), NULL);
1062 if (context_path != NULL) {
1063 apr_stat(&finfo, context_path, APR_FINFO_TYPE,
1064 r->pool);
1065 }
1066 }
1067 if (finfo.filetype != APR_REG) {
1068 if (JK_IS_DEBUG_LEVEL(conf->log))
1069 jk_log(conf->log, JK_LOG_DEBUG,
1070 "JkAutoAlias, no DirectoryIndex file for URI %s",
1071 r->uri);
1072 return DECLINED;
1073 }
1074 }
1075 if (!conf->uw_map) {
1076 if (JK_IS_DEBUG_LEVEL(conf->log))
1077 jk_log(conf->log, JK_LOG_DEBUG,
1078 "missing uri map for %s:%s",
1079 conf->s->server_hostname ? conf->s->server_hostname : "_default_",
1080 r->uri);
1081 return DECLINED;
1082 }
1083 else
1084 worker = map_uri_to_worker(conf->uw_map, r->uri,
1085 NULL, conf->log);
1086
1087 if (worker) {
1088 r->handler = apr_pstrdup(r->pool, JK_HANDLER);
1089 apr_table_setn(r->notes, JK_NOTE_WORKER_NAME, worker);
1090
1091 /* This could be a sub-request, possibly from mod_dir */
1092 /* Also add the the HANDLER to the main request */
1093 if (r->main) {
1094 r->main->handler = apr_pstrdup(r->main->pool, JK_HANDLER);
1095 apr_table_setn(r->main->notes, JK_NOTE_WORKER_NAME, worker);
1096 }
1097
1098 return OK;
1099 }
1100 else if (conf->alias_dir != NULL) {
1101 char *clean_uri = apr_pstrdup(r->pool, r->uri);
1102 ap_no2slash(clean_uri);
1103 /* Automatically map uri to a context static file */
1104 if (JK_IS_DEBUG_LEVEL(conf->log))
1105 jk_log(conf->log, JK_LOG_DEBUG,
1106 "check alias_dir: %s",
1107 conf->alias_dir);
1108 if (strlen(clean_uri) > 1) {
1109 /* Get the context directory name */
1110 char *context_dir = NULL;
1111 char *context_path = NULL;
1112 char *child_dir = NULL;
1113 char *index = clean_uri;
1114 char *suffix = strchr(index + 1, '/');
1115 if (suffix != NULL) {
1116 int size = suffix - index;
1117 context_dir = apr_pstrndup(r->pool, index, size);
1118 /* Get the context child directory name */
1119 index = index + size + 1;
1120 suffix = strchr(index, '/');
1121 if (suffix != NULL) {
1122 size = suffix - index;
1123 child_dir = apr_pstrndup(r->pool, index, size);
1124 }
1125 else {
1126 child_dir = index;
1127 }
1128 /* Deny access to WEB-INF and META-INF directories */
1129 if (child_dir != NULL) {
1130 if (JK_IS_DEBUG_LEVEL(conf->log))
1131 jk_log(conf->log, JK_LOG_DEBUG,
1132 "AutoAlias child_dir: %s",
1133 child_dir);
1134 if (!strcasecmp(child_dir, "WEB-INF")
1135 || !strcasecmp(child_dir, "META-INF")) {
1136 if (JK_IS_DEBUG_LEVEL(conf->log))
1137 jk_log(conf->log, JK_LOG_DEBUG,
1138 "AutoAlias HTTP_NOT_FOUND for URI: %s",
1139 r->uri);
1140 return HTTP_NOT_FOUND;
1141 }
1142 }
1143 }
1144 else {
1145 context_dir = apr_pstrdup(r->pool, index);
1146 }
1147
1148 context_path = apr_pstrcat(r->pool, conf->alias_dir,
1149 ap_os_escape_path(r->pool,
1150 context_dir,
1151 1), NULL);
1152 if (context_path != NULL) {
1153 apr_finfo_t finfo;
1154 finfo.filetype = APR_NOFILE;
1155 apr_stat(&finfo, context_path, APR_FINFO_TYPE,
1156 r->pool);
1157 if (finfo.filetype == APR_DIR) {
1158 char *escurl =
1159 ap_os_escape_path(r->pool, clean_uri, 1);
1160 char *ret =
1161 apr_pstrcat(r->pool, conf->alias_dir, escurl,
1162 NULL);
1163 /* Add code to verify real path ap_os_canonical_name */
1164 if (ret != NULL) {
1165 if (JK_IS_DEBUG_LEVEL(conf->log))
1166 jk_log(conf->log, JK_LOG_DEBUG,
1167 "AutoAlias OK for file: %s",
1168 ret);
1169 r->filename = ret;
1170 return OK;
1171 }
1172 }
1173 else {
1174 /* Deny access to war files in web app directory */
1175 int size = strlen(context_dir);
1176 if (size > 4
1177 && !strcasecmp(context_dir + (size - 4),
1178 ".war")) {
1179 if (JK_IS_DEBUG_LEVEL(conf->log))
1180 jk_log(conf->log, JK_LOG_DEBUG,
1181 "AutoAlias HTTP_FORBIDDEN for URI: %s",
1182 r->uri);
1183 return HTTP_FORBIDDEN;
1184 }
1185 }
1186 }
1187 }
1188 }
1189 else {
1190 if (JK_IS_DEBUG_LEVEL(conf->log))
1191 jk_log(conf->log, JK_LOG_DEBUG,
1192 "no match for %s found",
1193 r->uri);
1194 }
1195 }
1196 }
1197
1198 return DECLINED;
1199}
1200
1201#if (MODULE_MAGIC_NUMBER_MAJOR > 20010808)
1202/* bypass the directory_walk and file_walk for non-file requests */
1203static int jk_map_to_storage(request_rec * r)
1204{
1205
1206 if (!r->proxyreq && !apr_table_get(r->notes, JK_NOTE_WORKER_NAME)) {
1207 jk_server_conf_t *conf =
1208 (jk_server_conf_t *) ap_get_module_config(r->server->
1209 module_config,
1210 &jk_module);
1211
1212 if (conf) {
1213 const char *worker;
1214 if ((r->handler != NULL) && (!strcmp(r->handler, JK_HANDLER))) {
1215 /* Somebody already set the handler, probably manual config
1216 * or "native" configuration, no need for extra overhead
1217 */
1218 if (JK_IS_DEBUG_LEVEL(conf->log))
1219 jk_log(conf->log, JK_LOG_DEBUG,
1220 "Manually mapped, no need to call uri_to_worker");
1221 return DECLINED;
1222 }
1223
1224 if (apr_table_get(r->subprocess_env, "no-jk")) {
1225 if (JK_IS_DEBUG_LEVEL(conf->log))
1226 jk_log(conf->log, JK_LOG_DEBUG,
1227 "Into map_to_storage no-jk env var detected for uri=%s, declined",
1228 r->uri);
1229
1230 return DECLINED;
1231 }
1232 if (!conf->uw_map) {
1233 if (JK_IS_DEBUG_LEVEL(conf->log))
1234 jk_log(conf->log, JK_LOG_DEBUG,
1235 "missing uri map for %s:%s",
1236 conf->s->server_hostname ? conf->s->server_hostname : "_default_",
1237 r->uri);
1238 return DECLINED;
1239 }
1240 else
1241 worker = map_uri_to_worker(conf->uw_map, r->uri,
1242 NULL, conf->log);
1243
1244 if (worker) {
1245 r->handler = apr_pstrdup(r->pool, JK_HANDLER);
1246 apr_table_setn(r->notes, JK_NOTE_WORKER_NAME, worker);
1247
1248 /* This could be a sub-request, possibly from mod_dir */
1249 if (r->main)
1250 apr_table_setn(r->main->notes, JK_NOTE_WORKER_NAME, worker);
1251
1252 }
1253 else {
1254 if (JK_IS_DEBUG_LEVEL(conf->log))
1255 jk_log(conf->log, JK_LOG_DEBUG,
1256 "no match for %s found",
1257 r->uri);
1258 if (conf->strip_session == JK_TRUE) {
1259 char *jsessionid;
1260 if (r->uri) {
1261 jsessionid = strstr(r->uri, JK_PATH_SESSION_IDENTIFIER);
1262 if (jsessionid) {
1263 if (JK_IS_DEBUG_LEVEL(conf->log))
1264 jk_log(conf->log, JK_LOG_DEBUG,
1265 "removing session identifier [%s] for non servlet url [%s]",
1266 jsessionid, r->uri);
1267 *jsessionid = '\0';
1268 }
1269 }
1270 if (r->filename) {
1271 jsessionid = strstr(r->filename, JK_PATH_SESSION_IDENTIFIER);
1272 if (jsessionid)
1273 *jsessionid = '\0';
1274 }
1275 return DECLINED;
1276 }
1277 }
1278 }
1279 }
1280
1281 if (apr_table_get(r->notes, JK_NOTE_WORKER_NAME)) {
1282
1283 /* First find just the name of the file, no directory */
1284 r->filename = (char *)apr_filepath_name_get(r->uri);
1285
1286 /* Only if sub-request for a directory, most likely from mod_dir */
1287 if (r->main && r->main->filename &&
1288 (!apr_filepath_name_get(r->main->filename) ||
1289 !strlen(apr_filepath_name_get(r->main->filename)))) {
1290
1291 /* The filename from the main request will be set to what should
1292 * be picked up, aliases included. Tomcat will need to know about
1293 * those aliases or things won't work for them. Normal files should
1294 * be fine. */
1295
1296 /* Need absolute path to stat */
1297 if (apr_filepath_merge(&r->filename,
1298 r->main->filename, r->filename,
1299 APR_FILEPATH_SECUREROOT |
1300 APR_FILEPATH_TRUENAME, r->pool)
1301 != APR_SUCCESS) {
1302 return DECLINED; /* We should never get here, very bad */
1303 }
1304
1305 /* Stat the file so that mod_dir knows it's there */
1306 apr_stat(&r->finfo, r->filename, APR_FINFO_TYPE, r->pool);
1307 }
1308
1309 return OK;
1310 }
1311 return DECLINED;
1312}
1313#endif
1314
1315static void jk_register_hooks(apr_pool_t * p)
1316{
1317 ap_hook_handler(jk_handler, NULL, NULL, APR_HOOK_MIDDLE);
1318 ap_hook_post_config(jk_post_config, NULL, NULL, APR_HOOK_MIDDLE);
1319 ap_hook_child_init(jk_child_init, NULL, NULL, APR_HOOK_MIDDLE);
1320 ap_hook_translate_name(jk_translate, NULL, NULL, APR_HOOK_MIDDLE);
1321#if (MODULE_MAGIC_NUMBER_MAJOR > 20010808)
1322 ap_hook_map_to_storage(jk_map_to_storage, NULL, NULL, APR_HOOK_MIDDLE);
1323#endif
1324}
1325
1326module AP_MODULE_DECLARE_DATA jk_module = {
1327 STANDARD20_MODULE_STUFF,
1328 NULL, /* dir config creater */
1329 NULL, /* dir merger --- default is to override */
1330 create_jk_config, /* server config */
1331 merge_jk_config, /* merge server config */
1332 jk_cmds, /* command ap_table_t */
1333 jk_register_hooks /* register hooks */
1334};