allow _ in env. and var. and optimized matching of conditions
git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-merge-1.4.x@529 152afb58-edef-0310-8abb-c4023f1b3aa9svn/tags/lighttpd-1.4.2
parent
8b07d57d66
commit
360aba360f
|
@ -174,18 +174,11 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* OPTIMIZE
|
||||
*
|
||||
* - replace all is_equal be simple == to an enum
|
||||
*
|
||||
*/
|
||||
|
||||
/* pass the rules */
|
||||
|
||||
l = srv->empty_string;
|
||||
|
||||
if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPhost"))) {
|
||||
if (COMP_HTTP_HOST == dc->comp) {
|
||||
l = con->uri.authority;
|
||||
#if 0
|
||||
/* FIXME: get this working again */
|
||||
|
@ -215,7 +208,7 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat
|
|||
break;
|
||||
}
|
||||
}
|
||||
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPremoteip"))) {
|
||||
} else if (COMP_HTTP_REMOTEIP == dc->comp) {
|
||||
char *nm_slash;
|
||||
/* handle remoteip limitations
|
||||
*
|
||||
|
@ -290,22 +283,22 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat
|
|||
buffer_copy_string(srv->cond_check_buf, s);
|
||||
}
|
||||
#endif
|
||||
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPurl"))) {
|
||||
} else if (COMP_HTTP_URL == dc->comp) {
|
||||
l = con->uri.path;
|
||||
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("SERVERsocket"))) {
|
||||
} else if (COMP_SERVER_SOCKET == dc->comp) {
|
||||
l = srv_sock->srv_token;
|
||||
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPreferer"))) {
|
||||
} else if (COMP_HTTP_REFERER == dc->comp) {
|
||||
data_string *ds;
|
||||
|
||||
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
|
||||
l = ds->value;
|
||||
}
|
||||
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPcookie"))) {
|
||||
} else if (COMP_HTTP_COOKIE == dc->comp) {
|
||||
data_string *ds;
|
||||
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
|
||||
l = ds->value;
|
||||
}
|
||||
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPuseragent"))) {
|
||||
} else if (COMP_HTTP_USERAGENT == dc->comp) {
|
||||
data_string *ds;
|
||||
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "User-Agent"))) {
|
||||
l = ds->value;
|
||||
|
|
|
@ -266,7 +266,7 @@ int config_setup_connection(server *srv, connection *con) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int config_patch_connection(server *srv, connection *con, const char *stage, size_t stage_len) {
|
||||
int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
|
||||
size_t i, j;
|
||||
|
||||
/* skip the first, the global context */
|
||||
|
@ -275,7 +275,7 @@ int config_patch_connection(server *srv, connection *con, const char *stage, siz
|
|||
specific_config *s = srv->config_storage[i];
|
||||
|
||||
/* not our stage */
|
||||
if (!buffer_is_equal_string(dc->comp_key, stage, stage_len)) continue;
|
||||
if (comp != dc->comp) continue;
|
||||
|
||||
/* condition didn't match */
|
||||
if (!config_check_cond(srv, con, dc)) continue;
|
||||
|
@ -739,6 +739,7 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|||
for (i = 0; t->input[t->offset + i] &&
|
||||
(isalnum((unsigned char)t->input[t->offset + i]) ||
|
||||
t->input[t->offset + i] == '.' ||
|
||||
t->input[t->offset + i] == '_' || /* for env.* */
|
||||
t->input[t->offset + i] == '-'
|
||||
); i++);
|
||||
|
||||
|
@ -838,19 +839,12 @@ static void context_init(server *srv, config_t *context) {
|
|||
context->srv = srv;
|
||||
context->ok = 1;
|
||||
context->configs_stack = array_init();
|
||||
context->configs_stack->is_weakref = 1;
|
||||
context->basedir = buffer_init();
|
||||
}
|
||||
|
||||
static void context_free(config_t *context) {
|
||||
size_t i;
|
||||
array *a = context->configs_stack;
|
||||
|
||||
/* don't free elements */
|
||||
for (i = 0; i < a->size; i++) {
|
||||
a->data[i] = NULL;
|
||||
}
|
||||
array_free(a);
|
||||
|
||||
array_free(context->configs_stack);
|
||||
buffer_free(context->basedir);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ static void configparser_push(config_t *ctx, data_config *dc, int isnew) {
|
|||
assert(dc->context_ndx > ctx->current->context_ndx);
|
||||
array_insert_unique(ctx->all_configs, (data_unset *)dc);
|
||||
dc->parent = ctx->current;
|
||||
array_insert_unique(dc->parent->childs, (data_unset *)dc);
|
||||
}
|
||||
array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
|
||||
ctx->current = dc;
|
||||
|
@ -28,30 +29,42 @@ static data_config *configparser_pop(config_t *ctx) {
|
|||
return old;
|
||||
}
|
||||
|
||||
static const data_unset *configparser_get_variable(config_t *ctx, buffer *key) {
|
||||
data_unset *ds, *result;
|
||||
data_config *dc;
|
||||
/* return a copied variable */
|
||||
static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
|
||||
if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
|
||||
char *env;
|
||||
|
||||
result = NULL;
|
||||
#if 0
|
||||
fprintf(stderr, "get var %s\n", key->ptr);
|
||||
#endif
|
||||
for (dc = ctx->current; dc && !result; dc = dc->parent) {
|
||||
#if 0
|
||||
fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
|
||||
array_print(dc->value, 0);
|
||||
#endif
|
||||
ds = array_get_element(dc->value, key->ptr);
|
||||
if (NULL != ds) {
|
||||
result = ds;
|
||||
break;
|
||||
if (NULL != (env = getenv(key->ptr + 4))) {
|
||||
data_string *ds;
|
||||
ds = data_string_init();
|
||||
buffer_append_string(ds->value, env);
|
||||
return (data_unset *)ds;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
|
||||
ctx->ok = 0;
|
||||
|
||||
return NULL;
|
||||
} else {
|
||||
data_unset *du;
|
||||
data_config *dc;
|
||||
|
||||
#if 0
|
||||
fprintf(stderr, "get var %s\n", key->ptr);
|
||||
#endif
|
||||
for (dc = ctx->current; dc; dc = dc->parent) {
|
||||
#if 0
|
||||
fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
|
||||
array_print(dc->value, 0);
|
||||
#endif
|
||||
if (NULL != (du = array_get_element(dc->value, key->ptr))) {
|
||||
return du->copy(du);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NULL == result) {
|
||||
fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
|
||||
ctx->ok = 0;
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* op1 is to be eat/return by this function, op1->key is not cared
|
||||
|
@ -161,7 +174,6 @@ varline ::= key(A) ASSIGN expression(B). {
|
|||
|
||||
varline ::= key(A) APPEND expression(B). {
|
||||
array *vars = ctx->current->value;
|
||||
const data_unset *var;
|
||||
data_unset *du;
|
||||
|
||||
if (NULL != (du = array_get_element(vars, A->ptr))) {
|
||||
|
@ -169,9 +181,8 @@ varline ::= key(A) APPEND expression(B). {
|
|||
du = configparser_merge_data(ctx, du, B);
|
||||
buffer_copy_string_buffer(du->key, A);
|
||||
array_replace(vars, du);
|
||||
} else if (NULL != (var = configparser_get_variable(ctx, A))) {
|
||||
du = var->copy(var);
|
||||
du = configparser_merge_data(ctx, du->copy(du), B);
|
||||
} else if (NULL != (du = configparser_get_variable(ctx, A))) {
|
||||
du = configparser_merge_data(ctx, du, B);
|
||||
buffer_copy_string_buffer(du->key, A);
|
||||
array_insert_unique(ctx->current->value, du);
|
||||
} else {
|
||||
|
@ -210,11 +221,8 @@ expression(A) ::= value(B). {
|
|||
}
|
||||
|
||||
value(A) ::= key(B). {
|
||||
const data_unset *var = configparser_get_variable(ctx, B);
|
||||
if (var) {
|
||||
A = var->copy(var);
|
||||
}
|
||||
else {
|
||||
A = configparser_get_variable(ctx, B);
|
||||
if (!A) {
|
||||
/* make a dummy so it won't crash */
|
||||
A = (data_unset *)data_string_init();
|
||||
}
|
||||
|
@ -317,48 +325,81 @@ condline(A) ::= context LCURLY metalines RCURLY. {
|
|||
|
||||
context ::= DOLLAR SRVVARNAME(B) LBRACKET STRING(C) RBRACKET cond(E) expression(D). {
|
||||
data_config *dc;
|
||||
buffer *b, *rvalue;
|
||||
buffer *b, *rvalue, *op;
|
||||
|
||||
if (ctx->ok && D->type != TYPE_STRING) {
|
||||
fprintf(stderr, "rvalue must be string");
|
||||
ctx->ok = 0;
|
||||
}
|
||||
|
||||
switch(E) {
|
||||
case CONFIG_COND_NE:
|
||||
op = buffer_init_string("!=");
|
||||
break;
|
||||
case CONFIG_COND_EQ:
|
||||
op = buffer_init_string("==");
|
||||
break;
|
||||
case CONFIG_COND_NOMATCH:
|
||||
op = buffer_init_string("!~");
|
||||
break;
|
||||
case CONFIG_COND_MATCH:
|
||||
op = buffer_init_string("=~");
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
b = buffer_init();
|
||||
buffer_copy_string_buffer(b, ctx->current->key);
|
||||
buffer_append_string(b, "/");
|
||||
buffer_append_string_buffer(b, B);
|
||||
buffer_append_string_buffer(b, C);
|
||||
switch(E) {
|
||||
case CONFIG_COND_NE:
|
||||
buffer_append_string_len(b, CONST_STR_LEN("!="));
|
||||
break;
|
||||
case CONFIG_COND_EQ:
|
||||
buffer_append_string_len(b, CONST_STR_LEN("=="));
|
||||
break;
|
||||
case CONFIG_COND_NOMATCH:
|
||||
buffer_append_string_len(b, CONST_STR_LEN("!~"));
|
||||
break;
|
||||
case CONFIG_COND_MATCH:
|
||||
buffer_append_string_len(b, CONST_STR_LEN("=~"));
|
||||
break;
|
||||
default:
|
||||
buffer_append_string_len(b, CONST_STR_LEN("??"));
|
||||
break;
|
||||
}
|
||||
buffer_append_string_buffer(b, op);
|
||||
rvalue = ((data_string*)D)->value;
|
||||
buffer_append_string_buffer(b, rvalue);
|
||||
|
||||
if (NULL != (dc = (data_config *)array_get_element(ctx->all_configs, b->ptr))) {
|
||||
configparser_push(ctx, dc, 0);
|
||||
} else {
|
||||
struct {
|
||||
comp_key_t comp;
|
||||
char *comp_key;
|
||||
size_t len;
|
||||
} comps[] = {
|
||||
{ COMP_SERVER_SOCKET, CONST_STR_LEN("SERVER[\"socket\"]" ) },
|
||||
{ COMP_HTTP_URL, CONST_STR_LEN("HTTP[\"url\"]" ) },
|
||||
{ COMP_HTTP_HOST, CONST_STR_LEN("HTTP[\"host\"]" ) },
|
||||
{ COMP_HTTP_REFERER, CONST_STR_LEN("HTTP[\"referer\"]" ) },
|
||||
{ COMP_HTTP_USERAGENT, CONST_STR_LEN("HTTP[\"useragent\"]" ) },
|
||||
{ COMP_HTTP_COOKIE, CONST_STR_LEN("HTTP[\"cookie\"]" ) },
|
||||
{ COMP_HTTP_REMOTEIP, CONST_STR_LEN("HTTP[\"remoteip\"]" ) },
|
||||
{ COMP_UNSET, NULL, 0 },
|
||||
};
|
||||
size_t i;
|
||||
|
||||
dc = data_config_init();
|
||||
|
||||
buffer_copy_string_buffer(dc->key, b);
|
||||
buffer_copy_string_buffer(dc->op, op);
|
||||
buffer_copy_string_buffer(dc->comp_key, B);
|
||||
buffer_append_string_len(dc->comp_key, CONST_STR_LEN("[\""));
|
||||
buffer_append_string_buffer(dc->comp_key, C);
|
||||
buffer_append_string_len(dc->comp_key, CONST_STR_LEN("\"]"));
|
||||
dc->cond = E;
|
||||
|
||||
for (i = 0; comps[i].comp_key; i ++) {
|
||||
if (buffer_is_equal_string(
|
||||
dc->comp_key, comps[i].comp_key, comps[i].len)) {
|
||||
dc->comp = comps[i].comp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (COMP_UNSET == dc->comp) {
|
||||
fprintf(stderr, "error comp_key %s", dc->comp_key->ptr);
|
||||
ctx->ok = 0;
|
||||
}
|
||||
|
||||
switch(E) {
|
||||
case CONFIG_COND_NE:
|
||||
case CONFIG_COND_EQ:
|
||||
|
@ -408,6 +449,7 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET STRING(C) RBRACKET cond(E) expression(
|
|||
}
|
||||
|
||||
buffer_free(b);
|
||||
buffer_free(op);
|
||||
buffer_free(B);
|
||||
B = NULL;
|
||||
buffer_free(C);
|
||||
|
|
|
@ -653,6 +653,7 @@ void connections_free(server *srv) {
|
|||
CLEAN(error_handler);
|
||||
#undef CLEAN
|
||||
free(con->plugin_ctx);
|
||||
free(con->cond_results_cache);
|
||||
|
||||
free(con);
|
||||
}
|
||||
|
|
|
@ -276,7 +276,7 @@ static int mod_rewrite_patch_connection(server *srv, connection *con, plugin_dat
|
|||
data_config *dc = (data_config *)srv->config_context->data[i];
|
||||
s = p->config_storage[i];
|
||||
|
||||
if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPurl"))) continue;
|
||||
if (COMP_HTTP_URL == dc->comp) continue;
|
||||
|
||||
/* condition didn't match */
|
||||
if (!config_check_cond(srv, con, dc)) continue;
|
||||
|
|
|
@ -386,7 +386,7 @@ int network_init(server *srv) {
|
|||
specific_config *s = srv->config_storage[i];
|
||||
|
||||
/* not our stage */
|
||||
if (!buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("SERVERsocket"))) continue;
|
||||
if (COMP_SERVER_SOCKET != dc->comp) continue;
|
||||
|
||||
if (dc->cond != CONFIG_COND_EQ) {
|
||||
log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"].");
|
||||
|
|
|
@ -87,7 +87,7 @@ handler_t plugins_call_cleanup(server *srv);
|
|||
int config_insert_values_global(server *srv, array *ca, const config_values_t *cv);
|
||||
int config_insert_values_internal(server *srv, array *ca, const config_values_t *cv);
|
||||
int config_setup_connection(server *srv, connection *con);
|
||||
int config_patch_connection(server *srv, connection *con, const char *stage, size_t stage_len);
|
||||
int config_patch_connection(server *srv, connection *con, comp_key_t comp);
|
||||
int config_check_cond(server *srv, connection *con, data_config *dc);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -974,7 +974,8 @@ handler_t http_response_prepare(server *srv, connection *con) {
|
|||
if (con->mode == DIRECT && con->physical.path->used == 0) {
|
||||
char *qstr;
|
||||
|
||||
config_patch_connection(srv, con, CONST_STR_LEN("SERVERsocket")); /* SERVERsocket */
|
||||
config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */
|
||||
config_patch_connection(srv, con, COMP_HTTP_REMOTEIP); /* Client-IP */
|
||||
|
||||
/**
|
||||
* prepare strings
|
||||
|
@ -1001,10 +1002,10 @@ handler_t http_response_prepare(server *srv, connection *con) {
|
|||
buffer_copy_string(con->uri.scheme, con->conf.is_ssl ? "https" : "http");
|
||||
buffer_copy_string_buffer(con->uri.authority, con->request.http_host);
|
||||
|
||||
config_patch_connection(srv, con, CONST_STR_LEN("HTTPhost")); /* Host: */
|
||||
config_patch_connection(srv, con, CONST_STR_LEN("HTTPreferer")); /* Referer: */
|
||||
config_patch_connection(srv, con, CONST_STR_LEN("HTTPuseragent")); /* User-Agent: */
|
||||
config_patch_connection(srv, con, CONST_STR_LEN("HTTPcookie")); /* Cookie: */
|
||||
config_patch_connection(srv, con, COMP_HTTP_HOST); /* Host: */
|
||||
config_patch_connection(srv, con, COMP_HTTP_REFERER); /* Referer: */
|
||||
config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent: */
|
||||
config_patch_connection(srv, con, COMP_HTTP_COOKIE); /* Cookie: */
|
||||
|
||||
/** extract query string from request.uri */
|
||||
if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) {
|
||||
|
@ -1077,7 +1078,7 @@ handler_t http_response_prepare(server *srv, connection *con) {
|
|||
*
|
||||
*/
|
||||
|
||||
config_patch_connection(srv, con, CONST_STR_LEN("HTTPurl")); /* HTTPurl */
|
||||
config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
|
||||
|
||||
switch(r = plugins_call_handle_uri_clean(srv, con)) {
|
||||
case HANDLER_GO_ON:
|
||||
|
|
|
@ -8,12 +8,14 @@ BEGIN {
|
|||
|
||||
use strict;
|
||||
use IO::Socket;
|
||||
use Test::More tests => 15;
|
||||
use Test::More tests => 16;
|
||||
use LightyTest;
|
||||
|
||||
my $tf = LightyTest->new();
|
||||
my $t;
|
||||
|
||||
$ENV{"env_test"} = "good_env";
|
||||
|
||||
$tf->{CONFIGFILE} = 'var-include.conf';
|
||||
|
||||
ok($tf->start_proc == 0, "Starting lighttpd") or die();
|
||||
|
@ -34,12 +36,15 @@ my $tests = {
|
|||
"servername3" => "/good_" . $server_name . "/",
|
||||
"var.myvar" => "/good_var_myvar" . $myvar,
|
||||
"myvar" => "/good_myvar" . $myvar,
|
||||
"env" => "/" . $ENV{"env_test"},
|
||||
|
||||
"number1" => "/good_number" . "1",
|
||||
"number2" => "1" . "/good_number",
|
||||
"array_append" => "/good_array_append",
|
||||
"string_append" => "/good_" . $mystr,
|
||||
"number_append" => "/good_" . "2"
|
||||
};
|
||||
|
||||
foreach my $test (keys %{ $tests }) {
|
||||
my $expect = $tests->{$test};
|
||||
$t->{REQUEST} = ( <<EOF
|
||||
|
@ -52,3 +57,4 @@ EOF
|
|||
}
|
||||
|
||||
ok($tf->stop_proc == 0, "Stopping lighttpd");
|
||||
|
||||
|
|
|
@ -10,7 +10,11 @@ $HTTP["host"] =~ "^" + server.name + "$" {
|
|||
"^/myvar$" => "/good_myvar" + myvar,
|
||||
"^/number1$" => "/good_number" + one,
|
||||
"^/number2$" => one + "/good_number",
|
||||
"^/env$" => "/" + env.env_test,
|
||||
)
|
||||
num = 1
|
||||
num2 = 2
|
||||
num2 += 1
|
||||
# without var prefix
|
||||
mystr = "string"
|
||||
mystr += "_append"
|
||||
|
|
Loading…
Reference in New Issue