From 7409b2ef63818f82edb6e265eead9bbe597bac2f Mon Sep 17 00:00:00 2001 From: Thomas Porzelt Date: Mon, 7 Jun 2010 00:02:43 +0200 Subject: [PATCH] [plugin_core] Enable 'docroot' action to use patterns and even traverse a list of these --- src/main/plugin_core.c | 115 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 106 insertions(+), 9 deletions(-) diff --git a/src/main/plugin_core.c b/src/main/plugin_core.c index a89b29d..1fafab5 100644 --- a/src/main/plugin_core.c +++ b/src/main/plugin_core.c @@ -151,14 +151,79 @@ static gboolean core_setup_set(liServer *srv, liPlugin* p, liValue *val, gpointe return li_plugin_set_default_option(srv, val_name->data.string->str, val_val); } +static void core_docroot_nth_cb(GString *pattern_result, guint8 nth_ndx, gpointer data) { + /* $n means n-th part of hostname from end divided by dots */ + gchar *c, *end; + guint i = 0; + GString *str = data; + + if (nth_ndx == 0) { + g_string_append_len(pattern_result, GSTR_LEN(str)); + return; + } + + end = str->str + str->len - 1; + + for (c = end; c > str->str; c--) { + if (*c == '.') { + i++; + + if (i == nth_ndx) { + g_string_append_len(pattern_result, c+1, end - c); + return; + } + + end = c-1; + } + } +} + static liHandlerResult core_handle_docroot(liVRequest *vr, gpointer param, gpointer *context) { - UNUSED(context); + guint i; + GMatchInfo *match_info = NULL; + GArray *arr = param; g_string_truncate(vr->physical.doc_root, 0); - g_string_append_len(vr->physical.doc_root, GSTR_LEN((GString*) param)); - if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) { - VR_DEBUG(vr, "docroot: %s", vr->physical.doc_root->str); + 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; + } + + /* resume from last stat check */ + if (*context) { + i = GPOINTER_TO_INT(*context); + } else { + i = 0; + } + + /* loop over all the patterns until we find an existing path */ + for (; i < arr->len; i++) { + struct stat st; + gint err; + + + g_string_truncate(vr->physical.doc_root, 0); + li_pattern_eval(vr, vr->physical.doc_root, g_array_index(arr, liPattern*, i), core_docroot_nth_cb, vr->request.uri.host, li_pattern_regex_cb, match_info); + + /* check if path exists */ + switch (li_stat_cache_get(vr, vr->physical.doc_root, &st, &err, NULL)) { + case LI_HANDLER_GO_ON: break; + case LI_HANDLER_WAIT_FOR_EVENT: + *context = GINT_TO_POINTER(i); + if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) { + VR_DEBUG(vr, "docroot: waiting for async: \"%s\"", vr->physical.doc_root->str); + } + return LI_HANDLER_WAIT_FOR_EVENT; + default: + /* not found, try next pattern */ + if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) { + VR_DEBUG(vr, "docroot: not found: \"%s\", trying next", vr->physical.doc_root->str); + } + continue; + } + + *context = NULL; } /* build physical path: docroot + uri.path */ @@ -169,25 +234,57 @@ static liHandlerResult core_handle_docroot(liVRequest *vr, gpointer param, gpoin g_string_append_len(vr->physical.path, GSTR_LEN(vr->request.uri.path)); if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) { - VR_DEBUG(vr, "physical path: %s", vr->physical.path->str); + VR_DEBUG(vr, "docroot: \"%s\"", vr->physical.doc_root->str); + VR_DEBUG(vr, "physical path: \"%s\"", vr->physical.path->str); } return LI_HANDLER_GO_ON; } static void core_docroot_free(liServer *srv, gpointer param) { + guint i; + GArray *arr = param; + UNUSED(srv); - g_string_free(param, TRUE); + + for (i = 0; i < arr->len; i++) { + li_pattern_free(g_array_index(arr, liPattern*, i)); + } } static liAction* core_docroot(liServer *srv, liWorker *wrk, liPlugin* p, liValue *val, gpointer userdata) { + GArray *arr; + guint i; + liValue *v; + liPattern *pattern; + UNUSED(wrk); UNUSED(p); UNUSED(userdata); - if (!val || val->type != LI_VALUE_STRING) { - ERROR(srv, "%s", "docroot action expects a string parameter"); + + if (!val || (val->type != LI_VALUE_STRING && val->type != LI_VALUE_LIST)) { + ERROR(srv, "%s", "docroot action expects a string or list of strings as parameter"); return NULL; } - return li_action_new_function(core_handle_docroot, NULL, core_docroot_free, li_value_extract_string(val)); + arr = g_array_new(FALSE, TRUE, sizeof(liPattern*)); + + if (val->type == LI_VALUE_STRING) { + pattern = li_pattern_new(val->data.string->str); + g_array_append_val(arr, pattern); + } else { + for (i = 0; i < val->data.list->len; i++) { + v = g_array_index(val->data.list, liValue*, i); + + if (v->type != LI_VALUE_STRING) { + core_docroot_free(srv, arr); + return NULL; + } + + pattern = li_pattern_new(v->data.string->str); + g_array_append_val(arr, pattern); + } + } + + return li_action_new_function(core_handle_docroot, NULL, core_docroot_free, arr); } typedef struct {