Changeset 510
- Timestamp:
- 08/08/2005 10:26:13 AM (3 years ago)
- Location:
- trunk
- Files:
-
- 10 modified
-
src/array.h (modified) (1 diff)
-
src/base.h (modified) (2 diffs)
-
src/configfile-glue.c (modified) (6 diffs)
-
src/configfile.c (modified) (1 diff)
-
src/connections.c (modified) (3 diffs)
-
src/mod_redirect.c (modified) (6 diffs)
-
src/mod_rewrite.c (modified) (3 diffs)
-
src/response.c (modified) (2 diffs)
-
tests/lighttpd.conf (modified) (3 diffs)
-
tests/mod-redirect.t (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/array.h
r336 r510 65 65 66 66 typedef enum { CONFIG_COND_UNSET, CONFIG_COND_EQ, CONFIG_COND_MATCH, CONFIG_COND_NE, CONFIG_COND_NOMATCH } config_cond_t; 67 typedef enum { COND_RESULT_FALSE, COND_RESULT_TRUE, COND_RESULT_UNSET } cond_result_t;68 67 69 68 #define PATCHES NULL, "SERVERsocket", "HTTPurl", "HTTPhost", "HTTPreferer", "HTTPuseragent", "HTTPcookie", "HTTPremoteip" -
trunk/src/base.h
r353 r510 280 280 } server_socket_array; 281 281 282 typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t; 283 typedef struct { 284 cond_result_t result; 285 int patterncount; 286 int matches[3 * 10]; 287 buffer *comp_value; /* just a pointer */ 288 } cond_cache_t; 289 282 290 typedef struct { 283 291 connection_state_t state; … … 346 354 347 355 specific_config conf; /* global connection specific config */ 348 cond_ result_t *cond_results_cache;356 cond_cache_t *cond_cache; 349 357 350 358 buffer *server_name; -
trunk/src/configfile-glue.c
r418 r510 157 157 } 158 158 159 static int config_check_cond_cached(server *srv, connection *con, data_config *dc);159 static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc); 160 160 161 161 static cond_result_t config_check_cond_nocache(server *srv, connection *con, data_config *dc) { … … 166 166 if (dc->parent && dc->parent->context_ndx) { 167 167 if (con->conf.log_condition_handling) { 168 log_error_write(srv, __FILE__, __LINE__, "sb", "go parent", dc->parent-> string);169 } 170 if ( !config_check_cond_cached(srv, con, dc->parent)) {168 log_error_write(srv, __FILE__, __LINE__, "sb", "go parent", dc->parent->key); 169 } 170 if (config_check_cond_cached(srv, con, dc->parent) == COND_RESULT_FALSE) { 171 171 return COND_RESULT_FALSE; 172 172 } … … 175 175 if (dc->prev) { 176 176 if (con->conf.log_condition_handling) { 177 log_error_write(srv, __FILE__, __LINE__, "sb", "go prev", dc->prev-> string);177 log_error_write(srv, __FILE__, __LINE__, "sb", "go prev", dc->prev->key); 178 178 } 179 179 /* make sure prev is checked first */ 180 180 config_check_cond_cached(srv, con, dc->prev); 181 181 /* one of prev set me to FALSE */ 182 if ( con->cond_results_cache[dc->context_ndx] == COND_RESULT_FALSE) {182 if (COND_RESULT_FALSE == con->cond_cache[dc->context_ndx].result) { 183 183 return COND_RESULT_FALSE; 184 184 } … … 359 359 case CONFIG_COND_MATCH: { 360 360 #ifdef HAVE_PCRE_H 361 #define N 10 362 int ovec[N * 3]; 361 cond_cache_t *cache = &con->cond_cache[dc->context_ndx]; 363 362 int n; 364 363 365 n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0, ovec, N * 3); 364 #ifndef elementsof 365 #define elementsof(x) (sizeof(x) / sizeof(x[0])) 366 #endif 367 n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0, 368 cache->matches, elementsof(cache->matches)); 366 369 367 370 if (n > 0) { 371 cache->patterncount = n; 372 cache->comp_value = l; 368 373 return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE; 369 374 } else { 375 /* cache is already cleared */ 370 376 return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_FALSE : COND_RESULT_TRUE; 371 377 } … … 382 388 } 383 389 384 static int config_check_cond_cached(server *srv, connection *con, data_config *dc) {385 cond_ result_t *cache = con->cond_results_cache;386 387 if ( cache[dc->context_ndx] == COND_RESULT_UNSET) {388 if (COND_RESULT_TRUE == (cache [dc->context_ndx]= config_check_cond_nocache(srv, con, dc))) {390 static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc) { 391 cond_cache_t *caches = con->cond_cache; 392 393 if (COND_RESULT_UNSET == caches[dc->context_ndx].result) { 394 if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) { 389 395 if (dc->next) { 390 396 data_config *c; 391 397 if (con->conf.log_condition_handling) { 392 log_error_write(srv, __FILE__, __LINE__, "s", "setting remains of chaining to FALSE"); 398 log_error_write(srv, __FILE__, __LINE__, "s", 399 "setting remains of chaining to false"); 393 400 } 394 401 for (c = dc->next; c; c = c->next) { 395 cache [c->context_ndx]= COND_RESULT_FALSE;402 caches[c->context_ndx].result = COND_RESULT_FALSE; 396 403 } 397 404 } 398 405 } 399 406 if (con->conf.log_condition_handling) { 400 log_error_write(srv, __FILE__, __LINE__, "dsd", dc->context_ndx, "(uncached) result:", cache[dc->context_ndx]); 407 log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx, 408 "(uncached) result:", 409 caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false"); 401 410 } 402 411 } else { 403 412 if (con->conf.log_condition_handling) { 404 log_error_write(srv, __FILE__, __LINE__, "dsd", dc->context_ndx, "(cached) result:", cache[dc->context_ndx]); 405 } 406 } 407 return cache[dc->context_ndx]; 413 log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx, 414 "(cached) result:", 415 caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false"); 416 } 417 } 418 return caches[dc->context_ndx].result; 408 419 } 409 420 … … 412 423 log_error_write(srv, __FILE__, __LINE__, "s", "=== start of condition block ==="); 413 424 } 414 return config_check_cond_cached(srv, con, dc); 415 } 425 return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE); 426 } 427 428 int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n) 429 { 430 cond_cache_t *cache = &con->cond_cache[dc->context_ndx]; 431 if (n > cache->patterncount) { 432 return 0; 433 } 434 435 n <<= 1; /* n *= 2 */ 436 buffer_append_string_len(buf, 437 cache->comp_value->ptr + cache->matches[n], 438 cache->matches[n + 1] - cache->matches[n]); 439 return 1; 440 } 441 -
trunk/src/configfile.c
r506 r510 188 188 int config_setup_connection(server *srv, connection *con) { 189 189 specific_config *s = srv->config_storage[0]; 190 int i;191 192 for (i = srv->config_context->used - 1; i >= 0; i --) {193 con->cond_results_cache[i] = COND_RESULT_UNSET;194 }195 190 196 191 PATCH(allow_http11); -
trunk/src/connections.c
r359 r510 468 468 con->plugin_ctx = calloc(srv->plugins.used + 1, sizeof(void *)); 469 469 470 con->cond_ results_cache = calloc(srv->config_context->used, sizeof(cond_result_t));470 con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t)); 471 471 con->dst_addr_buf = buffer_init(); 472 472 config_setup_connection(srv, con); … … 520 520 #undef CLEAN 521 521 free(con->plugin_ctx); 522 free(con->cond_ results_cache);522 free(con->cond_cache); 523 523 524 524 file_descr_free(con->fd); … … 618 618 con->plugin_ctx[0] = NULL; 619 619 } 620 621 #if COND_RESULT_UNSET 622 for (i = srv->config_context->used - 1; i >= 0; i --) { 623 con->cond_cache[i].result = COND_RESULT_UNSET; 624 con->cond_cache[i].patterncount = 0; 625 } 626 #else 627 memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used); 628 #endif 620 629 621 630 con->header_len = 0; -
trunk/src/mod_redirect.c
r415 r510 14 14 typedef struct { 15 15 pcre_keyvalue_buffer *redirect; 16 data_config *context; /* to which apply me */ 16 17 } plugin_config; 17 18 … … 153 154 if (0 == strcmp(du->key->ptr, "url.redirect")) { 154 155 p->conf.redirect = s->redirect; 156 p->conf.context = dc; 155 157 } 156 158 } … … 193 195 if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) { 194 196 if (n != PCRE_ERROR_NOMATCH) { 195 log_error_write(srv, __FILE__, __LINE__, "sd" 197 log_error_write(srv, __FILE__, __LINE__, "sd", 196 198 "execution error while matching: ", n); 197 199 return HANDLER_ERROR; … … 201 203 size_t start, end; 202 204 size_t k; 205 203 206 /* it matched */ 204 207 pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list); … … 210 213 start = 0; end = pattern_len; 211 214 for (k = 0; k < pattern_len; k++) { 212 if ( pattern[k] == '$'&&215 if ((pattern[k] == '$' || pattern[k] == '%') && 213 216 isdigit((unsigned char)pattern[k + 1])) { 214 217 /* got one */ … … 220 223 buffer_append_string_len(p->location, pattern + start, end - start); 221 224 222 /* n is always > 0 */ 223 if (num < (size_t)n) { 224 buffer_append_string(p->location, list[num]); 225 if (pattern[k] == '$') { 226 /* n is always > 0 */ 227 if (num < (size_t)n) { 228 buffer_append_string(p->location, list[num]); 229 } 230 } else { 231 config_append_cond_match_buffer(con, p->conf.context, p->location, num); 225 232 } 226 233 -
trunk/src/mod_rewrite.c
r419 r510 16 16 pcre_keyvalue_buffer *rewrite; 17 17 buffer *final; 18 data_config *context; /* to which apply me */ 18 19 } plugin_config; 19 20 … … 298 299 start = 0; end = pattern_len; 299 300 for (k = 0; k < pattern_len; k++) { 300 if ( pattern[k] == '$'&&301 if ((pattern[k] == '$' || pattern[k] == '%') && 301 302 isdigit((unsigned char)pattern[k + 1])) { 302 303 /* got one */ … … 308 309 buffer_append_string_len(con->request.uri, pattern + start, end - start); 309 310 310 /* n is always larger than 0 */ 311 if (num < (size_t)n) { 312 buffer_append_string(con->request.uri, list[num]); 311 if (pattern[k] == '$') { 312 /* n is always > 0 */ 313 if (num < (size_t)n) { 314 buffer_append_string(con->request.uri, list[num]); 315 } 316 } else { 317 config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num); 313 318 } 314 319 -
trunk/src/response.c
r335 r510 126 126 char *qstr; 127 127 128 if (con->conf.log_condition_handling) { 129 log_error_write(srv, __FILE__, __LINE__, "s", "run condition"); 130 } 128 131 config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */ 129 config_patch_connection(srv, con, COMP_HTTP_REMOTEIP); /* Client-IP */130 132 131 133 /** … … 156 158 157 159 config_patch_connection(srv, con, COMP_HTTP_HOST); /* Host: */ 160 config_patch_connection(srv, con, COMP_HTTP_REMOTEIP); /* Client-IP */ 158 161 config_patch_connection(srv, con, COMP_HTTP_REFERER); /* Referer: */ 159 162 config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent: */ -
trunk/tests/lighttpd.conf
r289 r510 1 1 2 2 debug.log-request-handling = "enable" 3 debug.log-condition-handling = "enable" 3 4 4 5 server.document-root = "/tmp/lighttpd/servers/www.example.org/pages/" … … 129 130 url.access-deny = ( "~", ".inc") 130 131 131 url.redirect = ( "^/redirect/$" => "http://localhost:2048/" )132 133 132 url.rewrite = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1", 134 133 "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" ) … … 163 162 } 164 163 164 $HTTP["host"] =~ "(vvv).example.org" { 165 url.redirect = ( "^/redirect/$" => "http://localhost:2048/" ) 166 } 167 168 $HTTP["host"] =~ "(zzz).example.org" { 169 url.redirect = ( "^/redirect/$" => "http://localhost:2048/%1" ) 170 } 171 172 $HTTP["host"] =~ "(remoteip).example.org" { 173 $HTTP["remoteip"] =~ "(127.0.0.1)" { 174 url.redirect = ( "^/redirect/$" => "http://localhost:2048/%1" ) 175 } 176 } 177 178 $HTTP["remoteip"] =~ "(127.0.0.1)" { 179 $HTTP["host"] =~ "(remoteip2).example.org" { 180 url.redirect = ( "^/redirect/$" => "http://localhost:2048/%1" ) 181 } 182 } -
trunk/tests/mod-redirect.t
r72 r510 3 3 use strict; 4 4 use IO::Socket; 5 use Test::More tests => 3;5 use Test::More tests => 6; 6 6 7 7 my $basedir = (defined $ENV{'top_builddir'} ? $ENV{'top_builddir'} : '..'); … … 191 191 @request = ( <<EOF 192 192 GET /redirect/ HTTP/1.0 193 Host: vvv.example.org 193 194 EOF 194 195 ); … … 196 197 ok(handle_http == 0, 'external redirect'); 197 198 199 @request = ( <<EOF 200 GET /redirect/ HTTP/1.0 201 Host: zzz.example.org 202 EOF 203 ); 204 @response = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:2048/zzz' } ); 205 ok(handle_http == 0, 'external redirect with cond regsub'); 206 207 @request = ( <<EOF 208 GET /redirect/ HTTP/1.0 209 Host: remoteip.example.org 210 EOF 211 ); 212 @response = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:2048/127.0.0.1' } ); 213 ok(handle_http == 0, 'external redirect with cond regsub on remoteip'); 214 215 @request = ( <<EOF 216 GET /redirect/ HTTP/1.0 217 Host: remoteip2.example.org 218 EOF 219 ); 220 @response = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:2048/remoteip2' } ); 221 ok(handle_http == 0, 'external redirect with cond regsub on remoteip2'); 198 222 199 223 ok(stop_proc == 0, "Stopping lighttpd");

