2
0
Fork 0

Condition

This commit is contained in:
Stefan Bühler 2008-06-29 17:48:28 +02:00
parent 5c24ec2c97
commit 777232ab5d
5 changed files with 296 additions and 44 deletions

View File

@ -9,82 +9,63 @@ typedef enum { ACTION_SETTING, ACTION_FUNCTION, ACTION_CONDITION } action_type;
struct action;
typedef struct action action;
// condition operator
typedef enum
{
CONDITION_EQUAL, CONDITION_UNEQUAL,
CONDITION_LESS, CONDITION_LESS_EQUAL,
CONDITION_GREATER, CONDITION_GREATER_EQUAL,
CONDITION_REGEX_MATCH, CONDITION_REGEX_NOMATCH
} condition_op;
// condition type
typedef enum { CONDITION_BOOL, CONDITION_INT, CONDITION_STRING, CONDITION_IP } condition_type;
struct condition;
typedef struct condition condition;
struct action_list
{
GArray* actions;
guint refcount;
}
struct action_list;
typedef struct action_list action_list;
struct action_stack
{
GArray* stack;
guint index;
}
struct action_stack;
typedef struct action_stack action_stack;
struct action_stack_elem
{
struct action_list {
GArray* actions;
guint refcount;
};
struct action_stack {
GArray* stack;
guint index;
};
struct action_stack_elem {
action_list* al;
guint index;
}
};
typedef struct action_stack_elem action_stack_elem;
struct action
{
struct action {
action_type type;
union
{
struct
{
union {
struct {
option_mark opt;
option newvalue;
} setting;
condition cond;
struct
{
struct {
action_func* func;
gpointer param;
} actionfunc;
} value;
};
struct condition
{
struct condition {
condition_type type;
condition_op op;
action_list* target; // action target to jump to if condition is fulfilled
// left value of condition
union
{
union {
guint val_int;
gboolean val_bool;
GString* val_string;
} lvalue;
// right value of condition
union
{
union {
guint val_int;
gboolean val_bool;
GString* val_string;

189
src/condition.c Normal file
View File

@ -0,0 +1,189 @@
#include "condition.h"
#include "log.h"
static condition* condition_find_cached(server *srv, GString *key);
static void condition_cache_insert(server *srv, GString *key, condition *c);
static condition* condition_new(config_cond_t cond, comp_key_t comp);
static condition* condition_new_with_string(config_cond_t cond, comp_key_t comp, GString *str);
static condition* condition_new_with_int(config_cond_t cond, comp_key_t comp, gint i);
static void condition_free(condition *c);
static condition* condition_find_cached(server *srv, GString *key) {
UNUSED(srv);
UNUSED(key);
return NULL;
}
static void condition_cache_insert(server *srv, GString *key, condition *c) {
UNUSED(srv);
UNUSED(c);
g_string_free(key, TRUE);
}
static condition* condition_new(config_cond_t cond, comp_key_t comp) {
condition *c = g_slice_new0(condition);
c->refcount = 1;
c->cache_index = -1;
c->cond = cond;
c->comp = comp;
return c;
}
static condition* condition_new_with_string(config_cond_t cond, comp_key_t comp, GString *str) {
condition *c = condition_new(cond, comp);
switch (c->cond) {
case CONFIG_COND_EQ: /** == */
case CONFIG_COND_NE: /** != */
c->value.string = str;
break;
case CONFIG_COND_MATCH: /** =~ */
case CONFIG_COND_NOMATCH: /** !~ */
#ifdef HAVE_PCRE_H
/* TODO */
ERROR("Regular expressions not supported for now in condition: %s %s '%s'",
config_cond_to_string(cond), comp_key_to_string(comp),
str);
condition_free(c);
return NULL;
break;
#else
ERROR("Regular expressions not supported in condition: %s %s '%s'",
config_cond_to_string(cond), comp_key_to_string(comp),
str->str);
condition_free(c);
return NULL;
#endif
case CONFIG_COND_GT: /** > */
case CONFIG_COND_GE: /** >= */
case CONFIG_COND_LT: /** < */
case CONFIG_COND_LE: /** <= */
ERROR("Cannot compare with strings in condition: %s %s '%s'",
config_cond_to_string(cond), comp_key_to_string(comp),
str->str);
condition_free(c);
return NULL;
}
return c;
}
static condition* condition_new_with_int(config_cond_t cond, comp_key_t comp, gint i) {
condition *c = condition_new(cond, comp);
switch (c->cond) {
case CONFIG_COND_EQ: /** == */
case CONFIG_COND_NE: /** != */
case CONFIG_COND_MATCH: /** =~ */
case CONFIG_COND_NOMATCH: /** !~ */
ERROR("Cannot compare with integer in condition: %s %s %i",
config_cond_to_string(cond), comp_key_to_string(comp),
i);
condition_free(c);
return NULL;
case CONFIG_COND_GT: /** > */
case CONFIG_COND_GE: /** >= */
case CONFIG_COND_LT: /** < */
case CONFIG_COND_LE: /** <= */
c->value.i = i;
break;
}
return c;
}
condition* condition_new_string(server *srv, config_cond_t cond, comp_key_t comp, GString *str) {
condition *c;
GString *key = g_string_sized_new(0);
g_string_sprintf(key, "%i:%i:%s", (int) cond, (int) comp, str->str);
if (NULL != (c = condition_find_cached(srv, key))) {
g_string_free(key, TRUE);
return c;
}
c = condition_new_with_string(cond, comp, str);
condition_cache_insert(srv, key, c);
return c;
}
condition* condition_new_int(server *srv, config_cond_t cond, comp_key_t comp, gint i) {
condition *c;
GString *key = g_string_sized_new(0);
g_string_sprintf(key, "%i:%i#%i", (int) cond, (int) comp, i);
if (NULL != (c = condition_find_cached(srv, key))) {
g_string_free(key, TRUE);
return c;
}
c = condition_new_with_int(cond, comp, i);
condition_cache_insert(srv, key, c);
return c;
}
condition* condition_new_string_uncached(server *srv, config_cond_t cond, comp_key_t comp, GString *str) {
condition *c;
GString *key = g_string_sized_new(0);
g_string_sprintf(key, "%i:%i:%s", (int) cond, (int) comp, str->str);
c = condition_find_cached(srv, key);
g_string_free(key, TRUE);
if (NULL != c) return c;
return condition_new_with_string(cond, comp, str);
}
condition* condition_new_int_uncached(server *srv, config_cond_t cond, comp_key_t comp, gint i) {
condition *c;
GString *key = g_string_sized_new(0);
g_string_sprintf(key, "%i:%i#%i", (int) cond, (int) comp, i);
c = condition_find_cached(srv, key);
g_string_free(key, TRUE);
if (NULL != c) return c;
return condition_new_with_int(cond, comp, i);
}
static void condition_free(condition *c) {
switch (c->cond) {
case CONFIG_COND_EQ: /** == */
case CONFIG_COND_NE: /** != */
g_string_free(c->value.string, TRUE);
break;
case CONFIG_COND_MATCH: /** =~ */
case CONFIG_COND_NOMATCH: /** !~ */
#ifdef HAVE_PCRE_H
if (c->value.regex) pcre_free(c->value.regex);
if (c->value.regex_study) pcre_free(c->value.regex_study);
#endif
break;
case CONFIG_COND_GT: /** > */
case CONFIG_COND_GE: /** >= */
case CONFIG_COND_LT: /** < */
case CONFIG_COND_LE: /** <= */
break;
}
g_slice_free(condition, c);
}
void condition_release(condition* c) {
/* assert(c->recount > 0); */
if (!(--c->refcount)) {
condition_free(c);
}
}
const char* config_cond_to_string(config_cond_t cond) {
UNUSED(cond);
/* TODO */
return "";
}
const char* comp_key_to_string(comp_key_t comp) {
UNUSED(comp);
/* TODO */
return "";
}

76
src/condition.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef _LIGHTTPD_CONDITION_H_
#define _LIGHTTPD_CONDITION_H_
/**
* possible compare ops in the configfile parser
*/
typedef enum {
CONFIG_COND_EQ, /** == */
CONFIG_COND_MATCH, /** =~ */
CONFIG_COND_NE, /** != */
CONFIG_COND_NOMATCH, /** !~ */
CONFIG_COND_GT, /** > */
CONFIG_COND_GE, /** >= */
CONFIG_COND_LT, /** < */
CONFIG_COND_LE /** <= */
} config_cond_t;
/**
* possible fields to match against
*/
typedef enum {
COMP_UNSET,
COMP_SERVER_SOCKET,
COMP_HTTP_PATH,
COMP_HTTP_HOST,
COMP_HTTP_REFERER,
COMP_HTTP_USER_AGENT,
COMP_HTTP_COOKIE,
COMP_HTTP_SCHEME,
COMP_HTTP_REMOTE_IP,
COMP_HTTP_QUERY_STRING,
COMP_HTTP_REQUEST_METHOD,
COMP_PHYSICAL_PATH,
COMP_PHYSICAL_PATH_EXISTS,
COMP_LAST_ELEMENT
} comp_key_t;
struct condition;
typedef struct condition condition;
#include "base.h"
struct condition {
int refcount;
config_cond_t cond;
comp_key_t comp;
/* index into connection conditional caching table, -1 if uncached */
int cache_index;
union {
GString *string;
#ifdef HAVE_PCRE_H
struct {
pcre *regex;
pcre_extra *regex_study;
};
#endif
gint i;
} value;
};
LI_API condition* condition_new_string(server *srv, config_cond_t cond, comp_key_t comp, GString *str);
LI_API condition* condition_new_int(server *srv, config_cond_t cond, comp_key_t comp, gint i);
LI_API condition* condition_new_string_uncached(server *srv, config_cond_t cond, comp_key_t comp, GString *str);
LI_API condition* condition_new_int_uncached(server *srv, config_cond_t cond, comp_key_t comp, gint i);
LI_API void condition_release(condition* c);
LI_API const char* config_cond_to_string(config_cond_t cond);
LI_API const char* comp_key_to_string(comp_key_t comp);
#endif

View File

@ -173,6 +173,8 @@ typedef enum { HANDLER_UNSET,
# define UNUSED_PARAM(x) x
#endif
#define UNUSED(x) ( (void)(x) )
#if __GNUC__
#define INLINE static inline
// # define INLINE extern inline

View File

@ -9,13 +9,17 @@ common_uselib = 'glib '
common_source='''
base.c
chunks.c
condition.c
log.c
options.c
options_lua.c
sys-files.c
sys-socket.c
'''
common_source_lua='''
options_lua.c
'''
main_source = '''
server.c
'''