Changeset 510

Show
Ignore:
Timestamp:
08/08/2005 10:26:13 AM (3 years ago)
Author:
moo
Message:

mod_redirect/mod_rewrite substitute %n with condition substring

Location:
trunk
Files:
10 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/array.h

    r336 r510  
    6565 
    6666typedef 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; 
    6867 
    6968#define PATCHES NULL, "SERVERsocket", "HTTPurl", "HTTPhost", "HTTPreferer", "HTTPuseragent", "HTTPcookie", "HTTPremoteip" 
  • trunk/src/base.h

    r353 r510  
    280280} server_socket_array; 
    281281 
     282typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t; 
     283typedef 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 
    282290typedef struct { 
    283291        connection_state_t state; 
     
    346354         
    347355        specific_config conf;        /* global connection specific config */ 
    348         cond_result_t *cond_results_cache; 
     356        cond_cache_t *cond_cache; 
    349357         
    350358        buffer *server_name; 
  • trunk/src/configfile-glue.c

    r418 r510  
    157157} 
    158158 
    159 static int config_check_cond_cached(server *srv, connection *con, data_config *dc); 
     159static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc); 
    160160 
    161161static cond_result_t config_check_cond_nocache(server *srv, connection *con, data_config *dc) { 
     
    166166        if (dc->parent && dc->parent->context_ndx) { 
    167167                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) { 
    171171                        return COND_RESULT_FALSE; 
    172172                } 
     
    175175        if (dc->prev) { 
    176176                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); 
    178178                } 
    179179                /* make sure prev is checked first */ 
    180180                config_check_cond_cached(srv, con, dc->prev); 
    181181                /* 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) { 
    183183                        return COND_RESULT_FALSE; 
    184184                } 
     
    359359        case CONFIG_COND_MATCH: { 
    360360#ifdef HAVE_PCRE_H 
    361 #define N 10 
    362                 int ovec[N * 3]; 
     361                cond_cache_t *cache = &con->cond_cache[dc->context_ndx]; 
    363362                int n; 
    364363                 
    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)); 
    366369                 
    367370                if (n > 0) { 
     371                        cache->patterncount = n; 
     372                        cache->comp_value = l; 
    368373                        return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE; 
    369374                } else { 
     375                        /* cache is already cleared */ 
    370376                        return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_FALSE : COND_RESULT_TRUE; 
    371377                } 
     
    382388} 
    383389 
    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))) { 
     390static 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))) { 
    389395                        if (dc->next) { 
    390396                                data_config *c; 
    391397                                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"); 
    393400                                } 
    394401                                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; 
    396403                                } 
    397404                        } 
    398405                } 
    399406                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"); 
    401410                } 
    402411        } else { 
    403412                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; 
    408419} 
    409420 
     
    412423                log_error_write(srv, __FILE__, __LINE__,  "s",  "=== start of condition block ==="); 
    413424        } 
    414         return config_check_cond_cached(srv, con, dc); 
    415 } 
     425        return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE); 
     426} 
     427 
     428int 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  
    188188int config_setup_connection(server *srv, connection *con) { 
    189189        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         } 
    195190         
    196191        PATCH(allow_http11); 
  • trunk/src/connections.c

    r359 r510  
    468468        con->plugin_ctx = calloc(srv->plugins.used + 1, sizeof(void *)); 
    469469         
    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)); 
    471471        con->dst_addr_buf = buffer_init(); 
    472472        config_setup_connection(srv, con); 
     
    520520#undef CLEAN 
    521521                free(con->plugin_ctx); 
    522                 free(con->cond_results_cache); 
     522                free(con->cond_cache); 
    523523 
    524524                file_descr_free(con->fd); 
     
    618618                con->plugin_ctx[0] = NULL; 
    619619        } 
     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 
    620629         
    621630        con->header_len = 0; 
  • trunk/src/mod_redirect.c

    r415 r510  
    1414typedef struct { 
    1515        pcre_keyvalue_buffer *redirect; 
     16        data_config *context; /* to which apply me */ 
    1617} plugin_config; 
    1718 
     
    153154                        if (0 == strcmp(du->key->ptr, "url.redirect")) { 
    154155                                p->conf.redirect = s->redirect; 
     156                                p->conf.context = dc; 
    155157                        } 
    156158                } 
     
    193195                if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) { 
    194196                        if (n != PCRE_ERROR_NOMATCH) { 
    195                                 log_error_write(srv, __FILE__, __LINE__, "sd" 
     197                                log_error_write(srv, __FILE__, __LINE__, "sd", 
    196198                                                "execution error while matching: ", n); 
    197199                                return HANDLER_ERROR; 
     
    201203                        size_t start, end; 
    202204                        size_t k; 
     205                         
    203206                        /* it matched */ 
    204207                        pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list); 
     
    210213                        start = 0; end = pattern_len; 
    211214                        for (k = 0; k < pattern_len; k++) { 
    212                                 if (pattern[k] == '$' && 
     215                                if ((pattern[k] == '$' || pattern[k] == '%') && 
    213216                                    isdigit((unsigned char)pattern[k + 1])) { 
    214217                                        /* got one */ 
     
    220223                                        buffer_append_string_len(p->location, pattern + start, end - start); 
    221224                                         
    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); 
    225232                                        } 
    226233                                         
  • trunk/src/mod_rewrite.c

    r419 r510  
    1616        pcre_keyvalue_buffer *rewrite; 
    1717        buffer *final; 
     18        data_config *context; /* to which apply me */ 
    1819} plugin_config; 
    1920 
     
    298299                        start = 0; end = pattern_len; 
    299300                        for (k = 0; k < pattern_len; k++) { 
    300                                 if (pattern[k] == '$' && 
     301                                if ((pattern[k] == '$' || pattern[k] == '%') && 
    301302                                    isdigit((unsigned char)pattern[k + 1])) { 
    302303                                        /* got one */ 
     
    308309                                        buffer_append_string_len(con->request.uri, pattern + start, end - start); 
    309310                                         
    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); 
    313318                                        } 
    314319                                         
  • trunk/src/response.c

    r335 r510  
    126126                char *qstr; 
    127127                 
     128                if (con->conf.log_condition_handling) { 
     129                        log_error_write(srv, __FILE__, __LINE__,  "s",  "run condition"); 
     130                } 
    128131                config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */ 
    129                 config_patch_connection(srv, con, COMP_HTTP_REMOTEIP); /* Client-IP */ 
    130132                 
    131133                /** 
     
    156158                 
    157159                config_patch_connection(srv, con, COMP_HTTP_HOST);      /* Host:        */ 
     160                config_patch_connection(srv, con, COMP_HTTP_REMOTEIP);  /* Client-IP */ 
    158161                config_patch_connection(srv, con, COMP_HTTP_REFERER);   /* Referer:     */ 
    159162                config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent:  */ 
  • trunk/tests/lighttpd.conf

    r289 r510  
    11 
    22debug.log-request-handling = "enable" 
     3debug.log-condition-handling = "enable" 
    34 
    45server.document-root         = "/tmp/lighttpd/servers/www.example.org/pages/" 
     
    129130url.access-deny             = ( "~", ".inc") 
    130131 
    131 url.redirect                = ( "^/redirect/$" => "http://localhost:2048/" ) 
    132  
    133132url.rewrite                 = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1", 
    134133                                "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" ) 
     
    163162} 
    164163 
     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  
    33use strict; 
    44use IO::Socket; 
    5 use Test::More tests => 3; 
     5use Test::More tests => 6; 
    66 
    77my $basedir = (defined $ENV{'top_builddir'} ? $ENV{'top_builddir'} : '..'); 
     
    191191@request  = ( <<EOF 
    192192GET /redirect/ HTTP/1.0 
     193Host: vvv.example.org 
    193194EOF 
    194195 ); 
     
    196197ok(handle_http == 0, 'external redirect'); 
    197198 
     199@request  = ( <<EOF 
     200GET /redirect/ HTTP/1.0 
     201Host: zzz.example.org 
     202EOF 
     203 ); 
     204@response = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:2048/zzz' } ); 
     205ok(handle_http == 0, 'external redirect with cond regsub'); 
     206 
     207@request  = ( <<EOF 
     208GET /redirect/ HTTP/1.0 
     209Host: remoteip.example.org 
     210EOF 
     211 ); 
     212@response = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:2048/127.0.0.1' } ); 
     213ok(handle_http == 0, 'external redirect with cond regsub on remoteip'); 
     214 
     215@request  = ( <<EOF 
     216GET /redirect/ HTTP/1.0 
     217Host: remoteip2.example.org 
     218EOF 
     219 ); 
     220@response = ( { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:2048/remoteip2' } ); 
     221ok(handle_http == 0, 'external redirect with cond regsub on remoteip2'); 
    198222 
    199223ok(stop_proc == 0, "Stopping lighttpd");