Condition
This commit is contained in:
parent
5c24ec2c97
commit
777232ab5d
|
@ -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;
|
||||
|
|
|
@ -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 "";
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
'''
|
||||
|
|
Loading…
Reference in New Issue