From 2941105e2825904087fda72adeae42740ca47084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Thu, 7 Oct 2010 15:58:46 +0200 Subject: [PATCH] [pattern] Fix vr->wrk->tmp_str usage, remove pattern.h from base.h, add pattern support to header.add* actions --- include/lighttpd/base.h | 1 - include/lighttpd/condition.h | 7 +- include/lighttpd/pattern.h | 1 + src/main/condition.c | 32 ++++---- src/main/pattern.c | 12 ++- src/main/plugin_core.c | 145 +++++++++++++---------------------- src/modules/mod_memcached.c | 29 +++---- src/modules/mod_redirect.c | 1 + src/modules/mod_rewrite.c | 1 + 9 files changed, 94 insertions(+), 135 deletions(-) diff --git a/include/lighttpd/base.h b/include/lighttpd/base.h index b614ffb..a49246e 100644 --- a/include/lighttpd/base.h +++ b/include/lighttpd/base.h @@ -59,7 +59,6 @@ #include #include #include -#include #include #include diff --git a/include/lighttpd/condition.h b/include/lighttpd/condition.h index 56bb48c..2a39848 100644 --- a/include/lighttpd/condition.h +++ b/include/lighttpd/condition.h @@ -151,9 +151,8 @@ typedef struct { } data; } liConditionValue; -/* uses wrk->tmp_str for temporary (and returned) strings */ -LI_API liHandlerResult li_condition_get_value(liVRequest *vr, liConditionLValue *lvalue, liConditionValue *res, liConditionValueType prefer); -/* uses wrk->tmp_str for temporary (and returned) strings, no conflict with the tmp string from li_condition_get_value */ -LI_API gchar const* li_condition_value_to_string(liVRequest *vr, liConditionValue *value); +LI_API liHandlerResult li_condition_get_value(GString *tmpstr, liVRequest *vr, liConditionLValue *lvalue, liConditionValue *res, liConditionValueType prefer); +/* tmpstr can be the same as for li_condition_get_value */ +LI_API gchar const* li_condition_value_to_string(GString *tmpstr, liConditionValue *value); #endif diff --git a/include/lighttpd/pattern.h b/include/lighttpd/pattern.h index eaa2239..34810ed 100644 --- a/include/lighttpd/pattern.h +++ b/include/lighttpd/pattern.h @@ -15,6 +15,7 @@ typedef void (*liPatternCB) (GString *pattern_result, guint from, guint to, gpoi LI_API liPattern *li_pattern_new(liServer *srv, const gchar* str); LI_API void li_pattern_free(liPattern *pattern); +/* you can use vr->wrk->tmp_str as dest! */ LI_API void li_pattern_eval(liVRequest *vr, GString *dest, liPattern *pattern, liPatternCB nth_callback, gpointer nth_data, liPatternCB nth_prev_callback, gpointer nth_prev_data); /* default array callback, expects a GArray* containing GString* elements */ diff --git a/src/main/condition.c b/src/main/condition.c index 87f94ad..85d016e 100644 --- a/src/main/condition.c +++ b/src/main/condition.c @@ -30,8 +30,8 @@ static const liConditionValueType cond_value_hints[] = { }; #endif -/* uses wrk->tmp_str for temporary (and returned) strings */ -liHandlerResult li_condition_get_value(liVRequest *vr, liConditionLValue *lvalue, liConditionValue *res, liConditionValueType prefer) { +/* uses tmpstr for temporary (and returned) strings */ +liHandlerResult li_condition_get_value(GString *tmpstr, liVRequest *vr, liConditionLValue *lvalue, liConditionValue *res, liConditionValueType prefer) { liConInfo *coninfo = vr->coninfo; liHandlerResult r; struct stat st; @@ -174,14 +174,14 @@ liHandlerResult li_condition_get_value(liVRequest *vr, liConditionLValue *lvalue break; case LI_COMP_REQUEST_HEADER: res->match_type = LI_COND_VALUE_HINT_STRING; - li_http_header_get_all(vr->wrk->tmp_str, vr->request.headers, GSTR_LEN(lvalue->key)); - res->data.str = vr->wrk->tmp_str->str; + li_http_header_get_all(tmpstr, vr->request.headers, GSTR_LEN(lvalue->key)); + res->data.str = tmpstr->str; break; case LI_COMP_RESPONSE_HEADER: VREQUEST_WAIT_FOR_RESPONSE_HEADERS(vr); res->match_type = LI_COND_VALUE_HINT_STRING; - li_http_header_get_all(vr->wrk->tmp_str, vr->response.headers, GSTR_LEN(lvalue->key)); - res->data.str = vr->wrk->tmp_str->str; + li_http_header_get_all(tmpstr, vr->response.headers, GSTR_LEN(lvalue->key)); + res->data.str = tmpstr->str; break; case LI_COMP_ENVIRONMENT: res->match_type = LI_COND_VALUE_HINT_STRING; @@ -198,7 +198,7 @@ liHandlerResult li_condition_get_value(liVRequest *vr, liConditionLValue *lvalue return LI_HANDLER_GO_ON; } -gchar const* li_condition_value_to_string(liVRequest *vr, liConditionValue *value) { +gchar const* li_condition_value_to_string(GString *tmpstr, liConditionValue *value) { switch (value->match_type) { case LI_COND_VALUE_HINT_ANY: case LI_COND_VALUE_HINT_STRING: @@ -206,11 +206,11 @@ gchar const* li_condition_value_to_string(liVRequest *vr, liConditionValue *valu case LI_COND_VALUE_HINT_BOOL: return value->data.bool ? "TRUE" : "FALSE"; case LI_COND_VALUE_HINT_NUMBER: - g_string_printf(vr->wrk->tmp_str, "%"L_GOFFSET_FORMAT, value->data.number); - return vr->wrk->tmp_str->str; + g_string_printf(tmpstr, "%"L_GOFFSET_FORMAT, value->data.number); + return tmpstr->str; case LI_COND_VALUE_HINT_SOCKADDR: - li_sockaddr_to_string(value->data.addr, vr->wrk->tmp_str, TRUE); - return vr->wrk->tmp_str->str; + li_sockaddr_to_string(value->data.addr, tmpstr, TRUE); + return tmpstr->str; } return ""; } @@ -579,7 +579,7 @@ static liHandlerResult li_condition_check_eval_bool(liVRequest *vr, liCondition liHandlerResult r; *res = FALSE; - r = li_condition_get_value(vr, cond->lvalue, &match_val, LI_COND_VALUE_HINT_BOOL); + r = li_condition_get_value(vr->wrk->tmp_str, vr, cond->lvalue, &match_val, LI_COND_VALUE_HINT_BOOL); if (r != LI_HANDLER_GO_ON) return r; switch (match_val.match_type) { @@ -613,10 +613,10 @@ static liHandlerResult li_condition_check_eval_string(liVRequest *vr, liConditio const char *val = ""; *res = FALSE; - r = li_condition_get_value(vr, cond->lvalue, &match_val, LI_COND_VALUE_HINT_STRING); + r = li_condition_get_value(vr->wrk->tmp_str, vr, cond->lvalue, &match_val, LI_COND_VALUE_HINT_STRING); if (r != LI_HANDLER_GO_ON) return r; - val = li_condition_value_to_string(vr, &match_val); + val = li_condition_value_to_string(vr->wrk->tmp_str, &match_val); switch (cond->op) { case LI_CONFIG_COND_EQ: @@ -679,7 +679,7 @@ static liHandlerResult li_condition_check_eval_int(liVRequest *vr, liCondition * liHandlerResult r; *res = FALSE; - r = li_condition_get_value(vr, cond->lvalue, &match_val, LI_COND_VALUE_HINT_NUMBER); + r = li_condition_get_value(vr->wrk->tmp_str, vr, cond->lvalue, &match_val, LI_COND_VALUE_HINT_NUMBER); if (r != LI_HANDLER_GO_ON) return r; switch (match_val.match_type) { @@ -756,7 +756,7 @@ static liHandlerResult li_condition_check_eval_ip(liVRequest *vr, liCondition *c liHandlerResult r; liConditionRValue ipval; - r = li_condition_get_value(vr, cond->lvalue, &match_val, LI_COND_VALUE_HINT_SOCKADDR); + r = li_condition_get_value(vr->wrk->tmp_str, vr, cond->lvalue, &match_val, LI_COND_VALUE_HINT_SOCKADDR); if (r != LI_HANDLER_GO_ON) return r; *res = (cond->op == LI_CONFIG_COND_NOTIP); diff --git a/src/main/pattern.c b/src/main/pattern.c index a9f285f..94c0e2e 100644 --- a/src/main/pattern.c +++ b/src/main/pattern.c @@ -1,5 +1,6 @@ #include #include +#include typedef struct { enum { @@ -254,6 +255,7 @@ void li_pattern_eval(liVRequest *vr, GString *dest, liPattern *pattern, liPatter liHandlerResult res; liConditionValue cond_val; GArray *arr = (GArray*) pattern; + GString *tmpstr = NULL; for (i = 0; i < arr->len; i++) { liPatternPart *part = &g_array_index(arr, liPatternPart, i); @@ -279,18 +281,22 @@ void li_pattern_eval(liVRequest *vr, GString *dest, liPattern *pattern, liPatter case PATTERN_VAR: if (vr == NULL) continue; - res = li_condition_get_value(vr, part->data.lvalue, &cond_val, LI_COND_VALUE_HINT_STRING); + if (NULL == tmpstr) tmpstr = g_string_sized_new(127); + + res = li_condition_get_value(tmpstr, vr, part->data.lvalue, &cond_val, LI_COND_VALUE_HINT_STRING); if (res == LI_HANDLER_GO_ON) { if (encoded) { - li_string_encode_append(li_condition_value_to_string(vr, &cond_val), dest, LI_ENCODING_URI); + li_string_encode_append(li_condition_value_to_string(tmpstr, &cond_val), dest, LI_ENCODING_URI); } else { - g_string_append(dest, li_condition_value_to_string(vr, &cond_val)); + g_string_append(dest, li_condition_value_to_string(tmpstr, &cond_val)); } } break; } } + + if (NULL != tmpstr) g_string_free(tmpstr, TRUE); } void li_pattern_array_cb(GString *pattern_result, guint from, guint to, gpointer data) { diff --git a/src/main/plugin_core.c b/src/main/plugin_core.c index 848d693..d1ead19 100644 --- a/src/main/plugin_core.c +++ b/src/main/plugin_core.c @@ -1,5 +1,7 @@ #include +#include + #include #include @@ -873,7 +875,6 @@ static void core_log_write_free(liServer *srv, gpointer param) { static liHandlerResult core_handle_log_write(liVRequest *vr, gpointer param, gpointer *context) { liPattern *pattern = param; - GString *str = g_string_sized_new(127); GMatchInfo *match_info = NULL; if (vr->action_stack.regex_stack->len) { @@ -884,10 +885,9 @@ static liHandlerResult core_handle_log_write(liVRequest *vr, gpointer param, gpo UNUSED(context); /* eval pattern, ignore $n */ - li_pattern_eval(vr, str, pattern, NULL, NULL, li_pattern_regex_cb, match_info); + li_pattern_eval(vr, vr->wrk->tmp_str, pattern, NULL, NULL, li_pattern_regex_cb, match_info); - VR_INFO(vr, "%s", str->str); - g_string_free(str, TRUE); + VR_INFO(vr, "%s", vr->wrk->tmp_str->str); return LI_HANDLER_GO_ON; } @@ -1458,119 +1458,78 @@ static gboolean core_option_etag_use_parse(liServer *srv, liWorker *wrk, liPlugi return TRUE; } -static liHandlerResult core_handle_header_add(liVRequest *vr, gpointer param, gpointer *context) { - GArray *l = (GArray*)param; - GString *k = g_array_index(l, liValue*, 0)->data.string; - GString *v = g_array_index(l, liValue*, 1)->data.string; - UNUSED(param); - UNUSED(context); +typedef void (*header_cb)(liHttpHeaders *headers, const gchar *key, size_t keylen, const gchar *val, size_t valuelen); - li_http_header_insert(vr->response.headers, GSTR_LEN(k), GSTR_LEN(v)); - - return LI_HANDLER_GO_ON; -} +typedef struct header_ctx header_ctx; +struct header_ctx { + GString *key; + liPattern *value; + header_cb cb; +}; static void core_header_free(liServer *srv, gpointer param) { + header_ctx *ctx = param; + UNUSED(srv); - li_value_list_free(param); + + g_string_free(ctx->key, TRUE); + li_pattern_free(ctx->value); + g_slice_free(header_ctx, ctx); +} + +static liHandlerResult core_handle_header(liVRequest *vr, gpointer param, gpointer *context) { + header_ctx *ctx = param; + GMatchInfo *match_info = NULL; + + UNUSED(context); + + if (vr->action_stack.regex_stack->len) { + GArray *rs = vr->action_stack.regex_stack; + match_info = g_array_index(rs, liActionRegexStackElement, rs->len - 1).match_info; + } + + g_string_truncate(vr->wrk->tmp_str, 0); + li_pattern_eval(vr, vr->wrk->tmp_str, ctx->value, NULL, NULL, li_pattern_regex_cb, match_info); + + ctx->cb(vr->response.headers, GSTR_LEN(ctx->key), GSTR_LEN(vr->wrk->tmp_str)); + + return LI_HANDLER_GO_ON; } static liAction* core_header_add(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { GArray *l; - UNUSED(wrk); UNUSED(p); UNUSED(userdata); + liPattern *pat; + header_ctx *ctx; + UNUSED(wrk); UNUSED(p); if (val->type != LI_VALUE_LIST) { - ERROR(srv, "'header.add' action expects a string tuple as parameter, %s given", li_value_type_string(val->type)); + ERROR(srv, "'header.add/append/overwrite' action expects a string tuple as parameter, %s given", li_value_type_string(val->type)); return NULL; } l = val->data.list; if (l->len != 2) { - ERROR(srv, "'header.add' action expects a string tuple as parameter, list has %u entries", l->len); + ERROR(srv, "'header.add/append/overwrite' action expects a string tuple as parameter, list has %u entries", l->len); return NULL; } if (g_array_index(l, liValue*, 0)->type != LI_VALUE_STRING || g_array_index(l, liValue*, 0)->type != LI_VALUE_STRING) { - ERROR(srv, "%s", "'header.add' action expects a string tuple as parameter"); + ERROR(srv, "%s", "'header.add/append/overwrite' action expects a string tuple as parameter"); return NULL; } - return li_action_new_function(core_handle_header_add, NULL, core_header_free, li_value_extract_list(val)); -} - - -static liHandlerResult core_handle_header_append(liVRequest *vr, gpointer param, gpointer *context) { - GArray *l = (GArray*)param; - GString *k = g_array_index(l, liValue*, 0)->data.string; - GString *v = g_array_index(l, liValue*, 1)->data.string; - UNUSED(param); - UNUSED(context); - - li_http_header_append(vr->response.headers, GSTR_LEN(k), GSTR_LEN(v)); - - return LI_HANDLER_GO_ON; -} - -static liAction* core_header_append(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { - GArray *l; - UNUSED(wrk); UNUSED(p); UNUSED(userdata); - - if (val->type != LI_VALUE_LIST) { - ERROR(srv, "'header.append' action expects a string tuple as parameter, %s given", li_value_type_string(val->type)); + if (NULL == (pat = li_pattern_new(srv, g_array_index(l, liValue*, 1)->data.string->str))) { + ERROR(srv, "%s", "'header.add/append/overwrite': parsing value pattern failed"); return NULL; } - l = val->data.list; + ctx = g_slice_new(header_ctx); + ctx->key = li_value_extract_string(g_array_index(l, liValue*, 0)); + ctx->value = pat; + ctx->cb = (header_cb)(intptr_t)userdata; - if (l->len != 2) { - ERROR(srv, "'header.append' action expects a string tuple as parameter, list has %u entries", l->len); - return NULL; - } - - if (g_array_index(l, liValue*, 0)->type != LI_VALUE_STRING || g_array_index(l, liValue*, 0)->type != LI_VALUE_STRING) { - ERROR(srv, "%s", "'header.append' action expects a string tuple as parameter"); - return NULL; - } - - return li_action_new_function(core_handle_header_append, NULL, core_header_free, li_value_extract_list(val)); -} - - -static liHandlerResult core_handle_header_overwrite(liVRequest *vr, gpointer param, gpointer *context) { - GArray *l = (GArray*)param; - GString *k = g_array_index(l, liValue*, 0)->data.string; - GString *v = g_array_index(l, liValue*, 1)->data.string; - UNUSED(param); - UNUSED(context); - - li_http_header_overwrite(vr->response.headers, GSTR_LEN(k), GSTR_LEN(v)); - - return LI_HANDLER_GO_ON; -} - -static liAction* core_header_overwrite(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { - GArray *l; - UNUSED(wrk); UNUSED(p); UNUSED(userdata); - - if (val->type != LI_VALUE_LIST) { - ERROR(srv, "'header.overwrite' action expects a string tuple as parameter, %s given", li_value_type_string(val->type)); - return NULL; - } - - l = val->data.list; - - if (l->len != 2) { - ERROR(srv, "'header.overwrite' action expects a string tuple as parameter, list has %u entries", l->len); - return NULL; - } - - if (g_array_index(l, liValue*, 0)->type != LI_VALUE_STRING || g_array_index(l, liValue*, 0)->type != LI_VALUE_STRING) { - ERROR(srv, "%s", "'header.overwrite' action expects a string tuple as parameter"); - return NULL; - } - - return li_action_new_function(core_handle_header_overwrite, NULL, core_header_free, li_value_extract_list(val)); + return li_action_new_function(core_handle_header, NULL, core_header_free, ctx); } static void core_header_remove_free(liServer *srv, gpointer param) { @@ -1919,9 +1878,9 @@ static const liPluginAction actions[] = { { "env.remove", core_env_remove, NULL }, { "env.clear", core_env_clear, NULL }, - { "header.add", core_header_add, NULL }, - { "header.append", core_header_append, NULL }, - { "header.overwrite", core_header_overwrite, NULL }, + { "header.add", core_header_add, (void*)(intptr_t)li_http_header_insert }, + { "header.append", core_header_add, (void*)(intptr_t)li_http_header_append }, + { "header.overwrite", core_header_add, (void*)(intptr_t)li_http_header_overwrite }, { "header.remove", core_header_remove, NULL }, { "io.buffer_out", core_buffer_out, NULL }, diff --git a/src/modules/mod_memcached.c b/src/modules/mod_memcached.c index 0ea8f85..1a2f054 100644 --- a/src/modules/mod_memcached.c +++ b/src/modules/mod_memcached.c @@ -37,6 +37,7 @@ */ #include +#include #include #include @@ -235,22 +236,18 @@ option_failed: return NULL; } -static GString* mc_ctx_build_key(memcached_ctx *ctx, liVRequest *vr) { +static void mc_ctx_build_key(GString *dest, memcached_ctx *ctx, liVRequest *vr) { GMatchInfo *match_info = NULL; - GString *key = g_string_sized_new(255); - - g_string_truncate(key, 0); if (vr->action_stack.regex_stack->len) { GArray *rs = vr->action_stack.regex_stack; match_info = g_array_index(rs, liActionRegexStackElement, rs->len - 1).match_info; } - li_pattern_eval(vr, key, ctx->pattern, NULL, NULL, li_pattern_regex_cb, match_info); + g_string_truncate(dest, 0); + li_pattern_eval(vr, dest, ctx->pattern, NULL, NULL, li_pattern_regex_cb, match_info); - li_memcached_mutate_key(key); - - return key; + li_memcached_mutate_key(dest); } static liMemcachedCon* mc_ctx_prepare(memcached_ctx *ctx, liWorker *wrk) { @@ -356,7 +353,6 @@ static liHandlerResult mc_handle_lookup(liVRequest *vr, gpointer param, gpointer return LI_HANDLER_GO_ON; } else { liMemcachedCon *con; - GString *key; GError *err = NULL; if (li_vrequest_is_handled(vr)) { @@ -367,15 +363,14 @@ static liHandlerResult mc_handle_lookup(liVRequest *vr, gpointer param, gpointer } con = mc_ctx_prepare(ctx, vr->wrk); - key = mc_ctx_build_key(ctx, vr); + mc_ctx_build_key(vr->wrk->tmp_str, ctx, vr); if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) { - VR_DEBUG(vr, "memcached.lookup: looking up key '%s'", key->str); + VR_DEBUG(vr, "memcached.lookup: looking up key '%s'", vr->wrk->tmp_str->str); } req = g_slice_new0(memcache_request); - req->req = li_memcached_get(con, key, memcache_callback, req, &err); - g_string_free(key, TRUE); + req->req = li_memcached_get(con, vr->wrk->tmp_str, memcache_callback, req, &err); if (NULL == req->req) { if (NULL != err) { @@ -481,7 +476,6 @@ static liHandlerResult memcache_store_filter(liVRequest *vr, liFilter *f) { /* finally: store response in memcached */ liMemcachedCon *con; - GString *key; GError *err = NULL; liMemcachedRequest *req; memcached_ctx *ctx = mf->ctx; @@ -489,14 +483,13 @@ static liHandlerResult memcache_store_filter(liVRequest *vr, liFilter *f) { f->out->is_closed = TRUE; con = mc_ctx_prepare(ctx, vr->wrk); - key = mc_ctx_build_key(ctx, vr); + mc_ctx_build_key(vr->wrk->tmp_str, ctx, vr); if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) { - VR_DEBUG(vr, "memcached.store: storing response for key '%s'", key->str); + VR_DEBUG(vr, "memcached.store: storing response for key '%s'", vr->wrk->tmp_str->str); } - req = li_memcached_set(con, key, ctx->flags, ctx->ttl, mf->buf, NULL, NULL, &err); - g_string_free(key, TRUE); + req = li_memcached_set(con, vr->wrk->tmp_str, ctx->flags, ctx->ttl, mf->buf, NULL, NULL, &err); li_buffer_release(mf->buf); mf->buf = NULL; diff --git a/src/modules/mod_redirect.c b/src/modules/mod_redirect.c index fa5d539..0449c22 100644 --- a/src/modules/mod_redirect.c +++ b/src/modules/mod_redirect.c @@ -54,6 +54,7 @@ #include #include +#include LI_API gboolean mod_redirect_init(liModules *mods, liModule *mod); LI_API gboolean mod_redirect_free(liModules *mods, liModule *mod); diff --git a/src/modules/mod_rewrite.c b/src/modules/mod_rewrite.c index 3f4c297..66d7978 100644 --- a/src/modules/mod_rewrite.c +++ b/src/modules/mod_rewrite.c @@ -59,6 +59,7 @@ #include #include +#include LI_API gboolean mod_rewrite_init(liModules *mods, liModule *mod); LI_API gboolean mod_rewrite_free(liModules *mods, liModule *mod);