summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kneschke <jan@kneschke.de>2005-08-08 17:25:55 +0000
committerJan Kneschke <jan@kneschke.de>2005-08-08 17:25:55 +0000
commit360aba360f5bb6c8db7f98717d67c08448b7a111 (patch)
treea1b3ccf8ee9658351357ca54a62997aff71aca09
parent8b07d57d66b28931a99ae6358a1644ab171cd7f1 (diff)
downloadlighttpd-git-360aba360f5bb6c8db7f98717d67c08448b7a111.tar.gz
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-c4023f1b3aa9
-rw-r--r--src/configfile-glue.c21
-rw-r--r--src/configfile.c16
-rw-r--r--src/configparser.y112
-rw-r--r--src/connections.c1
-rw-r--r--src/mod_rewrite.c2
-rw-r--r--src/network.c2
-rw-r--r--src/plugin.h2
-rw-r--r--src/response.c13
-rwxr-xr-xtests/core-var-include.t8
-rw-r--r--tests/var-include-sub.conf4
10 files changed, 111 insertions, 70 deletions
diff --git a/src/configfile-glue.c b/src/configfile-glue.c
index 067ac05c..00e28ea8 100644
--- a/src/configfile-glue.c
+++ b/src/configfile-glue.c
@@ -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;
diff --git a/src/configfile.c b/src/configfile.c
index 4c53cfbf..0597eb3a 100644
--- a/src/configfile.c
+++ b/src/configfile.c
@@ -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);
}
diff --git a/src/configparser.y b/src/configparser.y
index ad00f233..23e19140 100644
--- a/src/configparser.y
+++ b/src/configparser.y
@@ -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;
+
+ 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;
- result = NULL;
#if 0
- fprintf(stderr, "get var %s\n", key->ptr);
+ fprintf(stderr, "get var %s\n", key->ptr);
#endif
- for (dc = ctx->current; dc && !result; dc = dc->parent) {
+ 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);
+ 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 != (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;
}
- 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("!="));
+ op = buffer_init_string("!=");
break;
case CONFIG_COND_EQ:
- buffer_append_string_len(b, CONST_STR_LEN("=="));
+ op = buffer_init_string("==");
break;
case CONFIG_COND_NOMATCH:
- buffer_append_string_len(b, CONST_STR_LEN("!~"));
+ op = buffer_init_string("!~");
break;
case CONFIG_COND_MATCH:
- buffer_append_string_len(b, CONST_STR_LEN("=~"));
+ op = buffer_init_string("=~");
break;
default:
- buffer_append_string_len(b, CONST_STR_LEN("??"));
+ 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);
+ 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);
diff --git a/src/connections.c b/src/connections.c
index 96083485..1842f3c6 100644
--- a/src/connections.c
+++ b/src/connections.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);
}
diff --git a/src/mod_rewrite.c b/src/mod_rewrite.c
index bf1b8446..345f6f6c 100644
--- a/src/mod_rewrite.c
+++ b/src/mod_rewrite.c
@@ -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;
diff --git a/src/network.c b/src/network.c
index 2d475afa..c40077d4 100644
--- a/src/network.c
+++ b/src/network.c
@@ -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\"].");
diff --git a/src/plugin.h b/src/plugin.h
index 8a141770..dad01424 100644
--- a/src/plugin.h
+++ b/src/plugin.h
@@ -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
diff --git a/src/response.c b/src/response.c
index aee79e55..f15bf769 100644
--- a/src/response.c
+++ b/src/response.c
@@ -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:
diff --git a/tests/core-var-include.t b/tests/core-var-include.t
index 2de8a8cb..538338fd 100755
--- a/tests/core-var-include.t
+++ b/tests/core-var-include.t
@@ -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");
+
diff --git a/tests/var-include-sub.conf b/tests/var-include-sub.conf
index 4ec85d35..152e6de1 100644
--- a/tests/var-include-sub.conf
+++ b/tests/var-include-sub.conf
@@ -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"