2
* Copyright 1999-2004 The Apache Software Foundation
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
/***************************************************************************
18
* Description: URI to worker map object. *
20
* Author: Gal Shachor <shachor@il.ibm.com> *
21
* Author: Mladen Turk <mturk@apache.org> *
22
* Version: $Revision: 1.56 $ *
23
***************************************************************************/
29
#include "jk_uri_worker_map.h"
32
#define JK_STRCMP strcasecmp
33
#define JK_STRNCMP strnicmp
35
#define JK_STRCMP strcmp
36
#define JK_STRNCMP strncmp
39
static int worker_compare(const void *elem1, const void *elem2)
41
uri_worker_record_t *e1 = *(uri_worker_record_t **)elem1;
42
uri_worker_record_t *e2 = *(uri_worker_record_t **)elem2;
43
return ((int)e2->context_len - (int)e1->context_len);
46
static void worker_qsort(jk_uri_worker_map_t *uw_map)
49
/* Sort remaining args using Quicksort algorithm: */
50
qsort((void *)uw_map->maps, uw_map->size,
51
sizeof(uri_worker_record_t *), worker_compare );
55
/* Match = 0, NoMatch = 1, Abort = -1
56
* Based loosely on sections of wildmat.c by Rich Salz
58
static int wildchar_match(const char *str, const char *exp, int icase)
62
for (x = 0, y = 0; exp[y]; ++y, ++x) {
63
if (!str[x] && exp[y] != '*')
66
while (exp[++y] == '*');
71
if ((ret = wildchar_match(&str[x++], &exp[y], icase)) != 1)
76
else if (exp[y] != '?') {
77
if (icase && (tolower(str[x]) != tolower(exp[y])))
79
else if (!icase && str[x] != exp[y])
83
return (str[x] != '\0');
86
int uri_worker_map_alloc(jk_uri_worker_map_t **uw_map,
87
jk_map_t *init_data, jk_logger_t *l)
93
*uw_map = (jk_uri_worker_map_t *)calloc(1, sizeof(jk_uri_worker_map_t));
95
JK_INIT_CS(&((*uw_map)->cs), rc);
97
jk_log(l, JK_LOG_ERROR,
98
"creating thread lock errno=%d",
104
rc = uri_worker_map_open(*uw_map, init_data, l);
109
JK_LOG_NULL_PARAMS(l);
115
static int uri_worker_map_close(jk_uri_worker_map_t *uw_map, jk_logger_t *l)
121
JK_DELETE_CS(&(uw_map->cs), i);
122
jk_close_pool(&uw_map->p);
127
JK_LOG_NULL_PARAMS(l);
132
int uri_worker_map_free(jk_uri_worker_map_t **uw_map, jk_logger_t *l)
136
if (uw_map && *uw_map) {
137
uri_worker_map_close(*uw_map, l);
144
JK_LOG_NULL_PARAMS(l);
151
* Ensure there will be memory in context info to store Context Bases
154
#define UW_INC_SIZE 4 /* 4 URI->WORKER STEP */
156
static int uri_worker_map_realloc(jk_uri_worker_map_t *uw_map)
158
if (uw_map->size == uw_map->capacity) {
159
uri_worker_record_t **uwr;
160
int capacity = uw_map->capacity + UW_INC_SIZE;
163
(uri_worker_record_t **) jk_pool_alloc(&uw_map->p,
164
sizeof(uri_worker_record_t
170
if (uw_map->capacity && uw_map->maps)
171
memcpy(uwr, uw_map->maps,
172
sizeof(uri_worker_record_t *) * uw_map->capacity);
175
uw_map->capacity = capacity;
182
int uri_worker_map_add(jk_uri_worker_map_t *uw_map,
183
const char *puri, const char *worker, jk_logger_t *l)
185
uri_worker_record_t *uwr = NULL;
187
unsigned int match_type = 0;
194
* This way you can disable already mounted
197
match_type = MATCH_TYPE_DISABLED;
201
match_type |= MATCH_TYPE_NO_MATCH;
205
/* Find if duplicate entry */
206
for (i = 0; i < uw_map->size; i++) {
207
uwr = uw_map->maps[i];
208
if (strcmp(uwr->uri, puri) == 0) {
209
/* Update disabled flag */
210
if (match_type & MATCH_TYPE_DISABLED)
211
uwr->match_type |= MATCH_TYPE_DISABLED;
213
uwr->match_type &= ~MATCH_TYPE_DISABLED;
214
if (strcmp(uwr->worker_name, worker) == 0) {
215
jk_log(l, JK_LOG_DEBUG,
216
"map rule %s=%s already exists",
222
jk_log(l, JK_LOG_DEBUG,
223
"changing map rule %s=%s ",
225
uwr->worker_name = jk_pool_strdup(&uw_map->p, worker);
231
if (uri_worker_map_realloc(uw_map) == JK_FALSE) {
235
uwr = (uri_worker_record_t *)jk_pool_alloc(&uw_map->p,
236
sizeof(uri_worker_record_t));
238
jk_log(l, JK_LOG_ERROR,
239
"can't alloc map entry");
244
uri = jk_pool_strdup(&uw_map->p, puri);
245
if (!uri || !worker) {
246
jk_log(l, JK_LOG_ERROR,
247
"can't alloc uri/worker strings");
253
if (strchr(uri, '*') ||
256
* /context/ * /user/ *
259
match_type |= MATCH_TYPE_WILDCHAR_PATH;
260
jk_log(l, JK_LOG_DEBUG,
261
"wildchar rule %s=%s was added",
266
/* Something like: JkMount /login/j_security_check ajp13 */
267
match_type |= MATCH_TYPE_EXACT;
268
jk_log(l, JK_LOG_DEBUG,
269
"exact rule %s=%s was added",
274
uwr->worker_name = jk_pool_strdup(&uw_map->p, worker);
275
uwr->context_len = strlen(uwr->context);
279
* JFC: please check...
280
* Not sure what to do, but I try to prevent problems.
281
* I have fixed jk_mount_context() in apaches/mod_jk.c so we should
282
* not arrive here when using Apache.
284
jk_log(l, JK_LOG_ERROR,
285
"invalid context %s",
290
uwr->match_type = match_type;
291
uw_map->maps[uw_map->size] = uwr;
293
if (match_type & MATCH_TYPE_NO_MATCH) {
294
/* If we split the mappings this one will be calculated */
297
worker_qsort(uw_map);
302
int uri_worker_map_open(jk_uri_worker_map_t *uw_map,
303
jk_map_t *init_data, jk_logger_t *l)
310
uw_map->capacity = 0;
316
jk_open_pool(&uw_map->p,
317
uw_map->buf, sizeof(jk_pool_atom_t) * SMALL_POOL_SIZE);
321
sz = jk_map_size(init_data);
323
jk_log(l, JK_LOG_DEBUG,
324
"rule map size is %d",
329
for (i = 0; i < sz; i++) {
330
if (uri_worker_map_add
331
(uw_map, jk_map_name_at(init_data, i),
332
jk_map_value_at(init_data, i), l) == JK_FALSE) {
339
if (JK_IS_DEBUG_LEVEL(l))
340
jk_log(l, JK_LOG_DEBUG,
341
"there are %d rules",
345
jk_log(l, JK_LOG_ERROR,
351
if (rc == JK_FALSE) {
352
jk_log(l, JK_LOG_ERROR,
353
"there was an error, freing buf");
354
jk_close_pool(&uw_map->p);
362
static int is_nomap_match(jk_uri_worker_map_t *uw_map,
363
const char *uri, const char* worker,
370
for (i = 0; i < uw_map->size; i++) {
371
uri_worker_record_t *uwr = uw_map->maps[i];
373
/* Check only nomatch mappings */
374
if (!(uwr->match_type & MATCH_TYPE_NO_MATCH) ||
375
(uwr->match_type & MATCH_TYPE_DISABLED))
377
/* Check only mathing workers */
378
if (strcmp(uwr->worker_name, worker))
380
if (uwr->match_type & MATCH_TYPE_WILDCHAR_PATH) {
381
/* Map is already sorted by context_len */
382
if (wildchar_match(uri, uwr->context,
389
jk_log(l, JK_LOG_DEBUG,
390
"Found a no match %s -> %s",
391
uwr->worker_name, uwr->context);
396
else if (JK_STRNCMP(uwr->context, uri, uwr->context_len) == 0) {
397
if (strlen(uri) == uwr->context_len) {
398
if (JK_IS_DEBUG_LEVEL(l))
399
jk_log(l, JK_LOG_DEBUG,
400
"Found an exact no match %s -> %s",
401
uwr->worker_name, uwr->context);
413
const char *map_uri_to_worker(jk_uri_worker_map_t *uw_map,
414
const char *uri, jk_logger_t *l)
418
const char *rv = NULL;
419
const char *url = uri;
420
char buf[JK_MAX_URI_LEN+1];
423
if (!uw_map || !uri) {
424
JK_LOG_NULL_PARAMS(l);
429
jk_log(l, JK_LOG_WARNING,
430
"Uri %s is invalid. Uri must start with /", uri);
434
url_rewrite = strstr(uri, JK_PATH_SESSION_IDENTIFIER);
436
size_t len = url_rewrite - uri;
437
if (len > JK_MAX_URI_LEN)
438
len = JK_MAX_URI_LEN;
439
strncpy(buf, uri, len);
442
if (JK_IS_DEBUG_LEVEL(l))
443
jk_log(l, JK_LOG_DEBUG, "Removing Session path '%s' URI '%s'",
447
uri_worker_map_update(uw_map, l);
448
if (JK_IS_DEBUG_LEVEL(l))
449
jk_log(l, JK_LOG_DEBUG, "Attempting to map URI '%s' from %d maps",
452
for (i = 0; i < uw_map->size; i++) {
453
uri_worker_record_t *uwr = uw_map->maps[i];
455
/* Check for match types */
456
if ((uwr->match_type & MATCH_TYPE_DISABLED) ||
457
(uwr->match_type & MATCH_TYPE_NO_MATCH))
460
if (JK_IS_DEBUG_LEVEL(l))
461
jk_log(l, JK_LOG_DEBUG, "Attempting to map context URI '%s'", uwr->uri);
463
if (uwr->match_type & MATCH_TYPE_WILDCHAR_PATH) {
465
/* Map is already sorted by context_len */
466
if (wildchar_match(url, uwr->context,
473
wname = uwr->worker_name;
474
if (JK_IS_DEBUG_LEVEL(l))
475
jk_log(l, JK_LOG_DEBUG,
476
"Found a wildchar match %s -> %s",
477
uwr->worker_name, uwr->context);
483
else if (JK_STRNCMP(uwr->context, url, uwr->context_len) == 0) {
484
if (strlen(url) == uwr->context_len) {
485
if (JK_IS_DEBUG_LEVEL(l))
486
jk_log(l, JK_LOG_DEBUG,
487
"Found an exact match %s -> %s",
488
uwr->worker_name, uwr->context);
490
rv = uwr->worker_name;
495
/* No matches found */
499
if (rv && uw_map->nosize) {
500
if (is_nomap_match(uw_map, url, rv, l)) {
501
if (JK_IS_DEBUG_LEVEL(l))
502
jk_log(l, JK_LOG_DEBUG,
503
"Denying matching for worker %s by nomatch rule",
511
int uri_worker_map_load(jk_uri_worker_map_t *uw_map,
518
if (jk_map_read_properties(map, uw_map->fname,
519
&uw_map->modified)) {
521
for (i = 0; i < jk_map_size(map); i++) {
522
const char *u = jk_map_name_at(map, i);
523
const char *w = jk_map_value_at(map, i);
524
/* Multiple mappings like :
525
* /servlets-examples|/ *
526
* will create two mappings:
529
* /servlets-examples/ *
531
if (strchr(u, '|')) {
532
char *s, *r = strdup(u);
535
/* Add first mapping */
536
if (!uri_worker_map_add(uw_map, r, w, l)) {
537
jk_log(l, JK_LOG_ERROR,
538
"invalid mapping rule %s->%s", r, w);
543
/* add second mapping */
544
if (!uri_worker_map_add(uw_map, r, w, l)) {
545
jk_log(l, JK_LOG_ERROR,
546
"invalid mapping rule %s->%s", r, w);
550
else if (!uri_worker_map_add(uw_map, u, w, l)) {
551
jk_log(l, JK_LOG_ERROR,
552
"invalid mapping rule %s->%s",
556
uw_map->checked = time(NULL);
563
int uri_worker_map_update(jk_uri_worker_map_t *uw_map,
567
time_t now = time(NULL);
569
if ((now - uw_map->checked) > JK_URIMAP_RELOAD) {
571
uw_map->checked = now;
572
if ((rc = stat(uw_map->fname, &statbuf)) == -1)
574
if (statbuf.st_mtime == uw_map->modified)
576
JK_ENTER_CS(&(uw_map->cs), rc);
577
/* Check if some other thread updated status */
578
if (statbuf.st_mtime == uw_map->modified) {
579
JK_LEAVE_CS(&(uw_map->cs), rc);
582
rc = uri_worker_map_load(uw_map, l);
583
JK_LEAVE_CS(&(uw_map->cs), rc);
584
jk_log(l, JK_LOG_INFO,
585
"Reloaded urimaps from %s", uw_map->fname);