From c16f668a72dd066f78409466ee79070520ec173c Mon Sep 17 00:00:00 2001 From: Michael Koloberdin Date: Mon, 11 May 2009 23:33:19 +0100 Subject: [PATCH] mod_redirect: Added url.redirect-simple (simple non-RE redirection). --- src/mod_redirect.c | 153 +++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 117 insertions(+), 36 deletions(-) diff --git a/src/mod_redirect.c b/src/mod_redirect.c index ed09f8d..4963d6c 100644 --- a/src/mod_redirect.c +++ b/src/mod_redirect.c @@ -15,6 +15,9 @@ typedef struct { pcre_keyvalue_buffer *redirect; +#ifdef HAVE_GLIB_H + GHashTable *redirect_simple; +#endif data_config *context; /* to which apply me */ unsigned short redirect_code; @@ -43,6 +46,17 @@ INIT_FUNC(mod_redirect_init) { return p; } +#ifdef HAVE_GLIB_H +static gboolean mod_redirect_simple_free_hrfunc(gpointer k, gpointer v, gpointer user_data) { + buffer_free((buffer *)k); + buffer_free((buffer *)v); + + UNUSED(user_data); + + return TRUE; +} +#endif + FREE_FUNC(mod_redirect_free) { plugin_data *p = p_d; @@ -54,6 +68,10 @@ FREE_FUNC(mod_redirect_free) { plugin_config *s = p->config_storage[i]; pcre_keyvalue_buffer_free(s->redirect); +#ifdef HAVE_GLIB_H + g_hash_table_foreach_remove(s->redirect_simple, mod_redirect_simple_free_hrfunc, NULL); + g_hash_table_destroy(s->redirect_simple); +#endif free(s); } @@ -76,7 +94,8 @@ SETDEFAULTS_FUNC(mod_redirect_set_defaults) { config_values_t cv[] = { { "url.redirect", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ - { "url.redirect-code", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ + { "url.redirect-simple", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ + { "url.redirect-code", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; @@ -93,9 +112,11 @@ SETDEFAULTS_FUNC(mod_redirect_set_defaults) { s = calloc(1, sizeof(plugin_config)); s->redirect = pcre_keyvalue_buffer_init(); + s->redirect_simple = g_hash_table_new(buffer_key_hash, buffer_key_equal); cv[0].destination = s->redirect; - cv[1].destination = &(s->redirect_code); + cv[1].destination = s->redirect_simple; + cv[2].destination = &(s->redirect_code); p->config_storage[i] = s; ca = ((data_config *)srv->config_context->data[i])->value; @@ -104,48 +125,82 @@ SETDEFAULTS_FUNC(mod_redirect_set_defaults) { return HANDLER_ERROR; } - if (NULL == (du = array_get_element(ca, CONST_STR_LEN("url.redirect")))) { - /* no url.redirect defined */ - continue; - } + if (NULL != (du = array_get_element(ca, CONST_STR_LEN("url.redirect")))) { + /* url.redirect defined */ + if (du->type != TYPE_ARRAY) { + log_error_write(srv, __FILE__, __LINE__, "sss", + "unexpected type for key: ", "url.redirect", "array of strings"); + + return HANDLER_ERROR; + } - if (du->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "sss", - "unexpected type for key: ", "url.redirect", "array of strings"); + da = (data_array *)du; - return HANDLER_ERROR; - } + for (j = 0; j < da->value->used; j++) { + if (da->value->data[j]->type != TYPE_STRING) { + log_error_write(srv, __FILE__, __LINE__, "sssbs", + "unexpected type for key: ", + "url.redirect", + "[", da->value->data[j]->key, "](string)"); - da = (data_array *)du; + return HANDLER_ERROR; + } - for (j = 0; j < da->value->used; j++) { - if (da->value->data[j]->type != TYPE_STRING) { - log_error_write(srv, __FILE__, __LINE__, "sssbs", - "unexpected type for key: ", - "url.redirect", - "[", da->value->data[j]->key, "](string)"); + if (0 != pcre_keyvalue_buffer_append(s->redirect, + ((data_string *)(da->value->data[j]))->key->ptr, + ((data_string *)(da->value->data[j]))->value->ptr)) { - return HANDLER_ERROR; + log_error_write(srv, __FILE__, __LINE__, "sb", + "pcre-compile failed for", da->value->data[j]->key); + } } + } + if (NULL != (du = array_get_element(ca, CONST_STR_LEN("url.redirect-simple")))) { + /* url.redirect-simple defined */ + if (du->type != TYPE_ARRAY) { + log_error_write(srv, __FILE__, __LINE__, "sss", + "unexpected type for key: ", "url.redirect-simple", "array of strings"); - if (0 != pcre_keyvalue_buffer_append(s->redirect, - ((data_string *)(da->value->data[j]))->key->ptr, - ((data_string *)(da->value->data[j]))->value->ptr)) { + return HANDLER_ERROR; + } - log_error_write(srv, __FILE__, __LINE__, "sb", - "pcre-compile failed for", da->value->data[j]->key); + da = (data_array *)du; + + for (j = 0; j < da->value->used; j++) { + if (da->value->data[j]->type != TYPE_STRING) { + log_error_write(srv, __FILE__, __LINE__, "sssbs", + "unexpected type for key: ", + "url.redirect-simple", + "[", da->value->data[j]->key, "](string)"); + + return HANDLER_ERROR; + } + + g_hash_table_insert(s->redirect_simple, + buffer_init_string( + ((data_string *)(da->value->data[j]))->key->ptr + ), + buffer_init_string( + ((data_string *)(da->value->data[j]))->value->ptr + ) + ); } } } return HANDLER_GO_ON; } -#ifdef HAVE_PCRE_H +#if defined (HAVE_PCRE_H) || defined (HAVE_GLIB_H) static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; +#ifdef HAVE_PCRE_H PATCH_OPTION(redirect); +#endif +#ifdef HAVE_GLIB_H + PATCH_OPTION(redirect_simple); +#endif PATCH_OPTION(redirect_code); /* skip the first, the global context */ @@ -160,10 +215,20 @@ static int mod_redirect_patch_connection(server *srv, connection *con, plugin_da for (j = 0; j < dc->value->used; j++) { data_unset *du = dc->value->data[j]; - if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.redirect"))) { + if +#ifdef HAVE_PCRE_H + (buffer_is_equal_string(du->key, CONST_STR_LEN("url.redirect"))) { PATCH_OPTION(redirect); p->conf.context = dc; - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.redirect-code"))) { + } else if +#endif +#ifdef HAVE_GLIB_H + (buffer_is_equal_string(du->key, CONST_STR_LEN("url.redirect-simple"))) { + PATCH_OPTION(redirect_simple); + p->conf.context = dc; + } else if +#endif + (buffer_is_equal_string(du->key, CONST_STR_LEN("url.redirect-code"))) { PATCH_OPTION(redirect_code); } } @@ -173,9 +238,10 @@ static int mod_redirect_patch_connection(server *srv, connection *con, plugin_da } #endif static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) { -#ifdef HAVE_PCRE_H +#if defined (HAVE_PCRE_H) || defined (HAVE_GLIB_H) plugin_data *p = p_data; int i; + buffer *dest; /* * REWRITE URL @@ -187,20 +253,35 @@ static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_ mod_redirect_patch_connection(srv, con, p); buffer_copy_string_buffer(p->match_buf, con->request.uri); - i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location); - - if (i >= 0) { - response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location)); +#ifdef HAVE_GLIB_H + dest = g_hash_table_lookup(p->conf.redirect_simple, p->match_buf); + if (dest != NULL) { + response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(dest)); + i = -1; + } else { +#endif +#ifdef HAVE_PCRE_H + i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location); + if (i >= 0) { + response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location)); + } + else if (i != PCRE_ERROR_NOMATCH) { + log_error_write(srv, __FILE__, __LINE__, "s", + "execution error while matching", i); + } +#endif +#ifdef HAVE_GLIB_H + } +#else + dest = NULL; +#endif + if (dest != NULL || i >= 0) { con->http_status = p->conf.redirect_code > 99 && p->conf.redirect_code < 1000 ? p->conf.redirect_code : 301; con->send->is_closed = 1; return HANDLER_FINISHED; } - else if (i != PCRE_ERROR_NOMATCH) { - log_error_write(srv, __FILE__, __LINE__, "s", - "execution error while matching", i); - } #undef N #else -- 1.6.2.5