New condition structure, some code for lua condition support

personal/stbuehler/wip
Stefan Bühler 14 years ago
parent 0ec2404647
commit c342be6424
  1. 4
      src/actions.h
  2. 175
      src/condition.c
  3. 116
      src/condition.h
  4. 201
      src/condition_lua.c
  5. 2
      src/condition_lua.h
  6. 6
      src/config_lua.c
  7. 8
      src/config_lua.h
  8. 1
      src/lighttpd.c
  9. 6
      src/plugin_core.c

@ -92,6 +92,6 @@ LI_API action *action_new_setting(server *srv, const gchar *name, option *value)
LI_API action *action_new_function(ActionFunc func, ActionFree free, gpointer param);
LI_API action *action_new_list();
LI_API action *action_new_condition(condition *cond, action_list *al);
LI_API action *action_new_condition_string(comp_key_t comp, comp_operator_t op, GString *str);
LI_API action *action_new_condition_int(comp_key_t comp, comp_operator_t op, guint64 i);
/*LI_API action *action_new_condition_string(comp_key_t comp, comp_operator_t op, GString *str);
LI_API action *action_new_condition_int(comp_key_t comp, comp_operator_t op, guint64 i);*/
#endif

@ -1,46 +1,49 @@
#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(comp_operator_t op, comp_key_t comp);
static condition* cond_new_string(comp_operator_t op, comp_key_t comp, GString *str);
static condition* cond_new_socket(comp_operator_t op, comp_key_t comp, GString *str);
static condition* condition_new_from_string(comp_operator_t op, comp_key_t comp, GString *str);
static condition* condition_new(comp_operator_t op, condition_lvalue *lvalue);
static condition* cond_new_string(comp_operator_t op, condition_lvalue *lvalue, GString *str);
static condition* cond_new_socket(comp_operator_t op, condition_lvalue *lvalue, GString *str);
static condition* condition_new_from_string(comp_operator_t op, condition_lvalue *lvalue, GString *str);
static void condition_free(condition *c);
static gboolean condition_check_eval(server *srv, connection *con, condition *cond);
static condition* condition_find_cached(server *srv, GString *key) {
UNUSED(srv);
UNUSED(key);
return NULL;
condition_lvalue* condition_lvalue_new(cond_lvalue_t type, GString *key) {
condition_lvalue *lvalue = g_slice_new0(condition_lvalue);
lvalue->type = type;
lvalue->key = key;
lvalue->refcount = 1;
return lvalue;
}
static void condition_cache_insert(server *srv, GString *key, condition *c) {
UNUSED(srv);
UNUSED(c);
void condition_lvalue_acquire(condition_lvalue *lvalue) {
assert(lvalue->refcount > 0);
lvalue->refcount++;
}
g_string_free(key, TRUE);
void condition_lvalue_release(condition_lvalue *lvalue) {
assert(lvalue->refcount > 0);
if (!(--lvalue->refcount)) {
if (lvalue->key) g_string_free(lvalue->key, TRUE);
g_slice_free(condition_lvalue, lvalue);
}
}
static condition* condition_new(comp_operator_t op, comp_key_t comp) {
static condition* condition_new(comp_operator_t op, condition_lvalue *lvalue) {
condition *c = g_slice_new0(condition);
c->refcount = 1;
c->cache_index = -1;
c->op = op;
c->comp = comp;
c->lvalue = lvalue;
return c;
}
static condition* cond_new_string(comp_operator_t op, comp_key_t comp, GString *str) {
condition *c = condition_new(op, comp);
static condition* cond_new_string(comp_operator_t op, condition_lvalue *lvalue, GString *str) {
condition *c = condition_new(op, lvalue);
switch (op) {
case CONFIG_COND_EQ: /** == */
case CONFIG_COND_NE: /** != */
c->value.string = str;
c->rvalue.string = str;
break;
case CONFIG_COND_MATCH: /** =~ */
case CONFIG_COND_NOMATCH: /** !~ */
@ -60,31 +63,29 @@ static condition* cond_new_string(comp_operator_t op, comp_key_t comp, GString *
condition_free(c);
return NULL;
}
c->value_type = COND_VALUE_STRING;
c->rvalue.type = COND_VALUE_STRING;
return c;
}
static condition* cond_new_socket(comp_operator_t op, comp_key_t comp, GString *str) {
return cond_new_string(op, comp, str);
static condition* cond_new_socket(comp_operator_t op, condition_lvalue *lvalue, GString *str) {
return cond_new_string(op, lvalue, str);
/* TODO: parse str as socket addr */
}
static condition* condition_new_from_string(comp_operator_t op, comp_key_t comp, GString *str) {
switch (comp) {
case COMP_SERVER_SOCKET:
case COMP_REQUEST_REMOTE_IP:
return cond_new_socket(op, comp, str);
static condition* condition_new_from_string(comp_operator_t op, condition_lvalue *lvalue, GString *str) {
switch (lvalue->type) {
case COMP_REQUEST_LOCALIP:
case COMP_REQUEST_REMOTEIP:
return cond_new_socket(op, lvalue, str);
case COMP_REQUEST_PATH:
case COMP_REQUEST_HOST:
case COMP_REQUEST_REFERER:
case COMP_REQUEST_USER_AGENT:
case COMP_REQUEST_COOKIE:
case COMP_REQUEST_SCHEME:
case COMP_REQUEST_QUERY_STRING:
case COMP_REQUEST_METHOD:
case COMP_PHYSICAL_PATH:
case COMP_PHYSICAL_PATH_EXISTS:
return cond_new_string(op, comp, str);
case COMP_REQUEST_HEADER:
return cond_new_string(op, lvalue, str);
case COMP_PHYSICAL_SIZE:
case COMP_REQUEST_CONTENT_LENGTH:
// TODO: die with error
@ -94,41 +95,21 @@ static condition* condition_new_from_string(comp_operator_t op, comp_key_t comp,
return NULL;
}
condition* condition_new_string(server *srv, comp_operator_t op, comp_key_t comp, GString *str) {
condition* condition_new_string(server *srv, comp_operator_t op, condition_lvalue *lvalue, GString *str) {
condition *c;
GString *key = g_string_sized_new(0);
g_string_sprintf(key, "%i:%i:%s", (int) op, (int) comp, str->str);
if (NULL != (c = condition_find_cached(srv, key))) {
g_string_free(key, TRUE);
return c;
}
if (NULL == (c = condition_new_from_string(op, comp, str))) {
g_string_free(key, TRUE);
if (NULL == (c = condition_new_from_string(op, lvalue, str))) {
ERROR(srv, "Condition creation failed: %s %s '%s' (perhaps you compiled without pcre?)",
comp_key_to_string(comp), comp_op_to_string(op),
cond_lvalue_to_string(lvalue->type), comp_op_to_string(op),
str->str);
return NULL;
}
condition_cache_insert(srv, key, c);
return c;
}
condition* condition_new_string_uncached(server *srv, comp_operator_t op, comp_key_t comp, GString *str) {
condition *c;
GString *key = g_string_sized_new(0);
g_string_sprintf(key, "%i:%i:%s", (int) op, (int) comp, str->str);
c = condition_find_cached(srv, key);
g_string_free(key, TRUE);
if (NULL != c) return c;
return condition_new_from_string(op, comp, str);
return c;
}
static void condition_free(condition *c) {
switch (c->value_type) {
switch (c->rvalue.type) {
case COND_VALUE_INT:
case COND_VALUE_SOCKET_IPV4:
case COND_VALUE_SOCKET_IPV6:
@ -137,27 +118,17 @@ static void condition_free(condition *c) {
case COND_VALUE_STRING:
if (c->op == CONFIG_COND_MATCH || c->op == 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);
if (c->rvalue.regex) pcre_free(c->rvalue.regex);
if (c->rvalue.regex_study) pcre_free(c->rvalue.regex_study);
#endif
} else {
g_string_free(c->value.string, TRUE);
g_string_free(c->rvalue.string, TRUE);
}
break;
}
g_slice_free(condition, c);
}
condition* condition_from_option(server *srv, option *opt) {
if (opt->type == OPTION_CONDITION) {
assert(srv == opt->value.opt_cond.srv);
condition_acquire(opt->value.opt_cond.cond);
return opt->value.opt_cond.cond;
}
/* TODO: convert triple into condition */
return NULL;
}
void condition_acquire(condition *c) {
assert(c->refcount > 0);
c->refcount++;
@ -186,11 +157,23 @@ const char* comp_op_to_string(comp_operator_t op) {
return "<unkown>";
}
const char* comp_key_to_string(comp_key_t comp) {
UNUSED(comp);
const char* cond_lvalue_to_string(cond_lvalue_t t) {
switch (t) {
case COMP_REQUEST_LOCALIP: return "request.localip";
case COMP_REQUEST_REMOTEIP: return "request.remoteip";
case COMP_REQUEST_PATH: return "request.path";
case COMP_REQUEST_HOST: return "request.host";
case COMP_REQUEST_SCHEME: return "request.scheme";
case COMP_REQUEST_QUERY_STRING: return "request.querystring";
case COMP_REQUEST_METHOD: return "request.method";
case COMP_REQUEST_CONTENT_LENGTH: return "request.length";
case COMP_PHYSICAL_PATH: return "physical.path";
case COMP_PHYSICAL_PATH_EXISTS: return "physical.pathexist";
case COMP_PHYSICAL_SIZE: return "physical.size";
case COMP_REQUEST_HEADER: return "request.header";
}
/* TODO */
return "";
return "<unknown>";
}
gboolean condition_check(server *srv, connection *con, condition *cond) {
@ -205,9 +188,12 @@ static gboolean condition_check_eval_string(server *srv, connection *con, condit
UNUSED(srv);
UNUSED(con);
switch (cond->comp) {
switch (cond->lvalue->type) {
/* TODO: get values */
case COMP_SERVER_SOCKET:
case COMP_REQUEST_LOCALIP:
break;
case COMP_REQUEST_REMOTEIP:
value = con->dst_addr_str->str;
break;
case COMP_REQUEST_PATH:
value = con->request.uri.path->str;
@ -215,19 +201,10 @@ static gboolean condition_check_eval_string(server *srv, connection *con, condit
case COMP_REQUEST_HOST:
value = con->request.host->str;
break;
case COMP_REQUEST_REFERER:
break;
case COMP_REQUEST_USER_AGENT:
break;
case COMP_REQUEST_COOKIE:
break;
case COMP_REQUEST_SCHEME:
/* TODO: check for ssl */
value = "http"; /* ssl ? "https" : "http" */
break;
case COMP_REQUEST_REMOTE_IP:
value = con->dst_addr_str->str;
break;
case COMP_REQUEST_QUERY_STRING:
value = con->request.uri.query->str;
break;
@ -236,6 +213,10 @@ static gboolean condition_check_eval_string(server *srv, connection *con, condit
break;
case COMP_PHYSICAL_PATH:
case COMP_PHYSICAL_PATH_EXISTS:
/* TODO */
break;
case COMP_REQUEST_HEADER:
/* TODO */
break;
case COMP_PHYSICAL_SIZE:
case COMP_REQUEST_CONTENT_LENGTH:
@ -246,10 +227,10 @@ static gboolean condition_check_eval_string(server *srv, connection *con, condit
if (value) switch (cond->op) {
case CONFIG_COND_EQ: /** == */
result = 0 == strcmp(value, cond->value.string->str);
result = 0 == strcmp(value, cond->rvalue.string->str);
break;
case CONFIG_COND_NE: /** != */
result = 0 != strcmp(value, cond->value.string->str);
result = 0 != strcmp(value, cond->rvalue.string->str);
break;
case CONFIG_COND_MATCH: /** =~ */
case CONFIG_COND_NOMATCH: /** !~ */
@ -273,7 +254,7 @@ static gboolean condition_check_eval_int(server *srv, connection *con, condition
UNUSED(con);
gint64 value;
switch (cond->comp) {
switch (cond->lvalue->type) {
case COMP_REQUEST_CONTENT_LENGTH:
value = con->request.content_length;
case COMP_PHYSICAL_SIZE:
@ -285,17 +266,17 @@ static gboolean condition_check_eval_int(server *srv, connection *con, condition
if (value > 0) switch (cond->op) {
case CONFIG_COND_EQ: /** == */
return (value == cond->value.i);
return (value == cond->rvalue.i);
case CONFIG_COND_NE: /** != */
return (value != cond->value.i);
return (value != cond->rvalue.i);
case CONFIG_COND_LT: /** < */
return (value < cond->value.i);
return (value < cond->rvalue.i);
case CONFIG_COND_LE: /** <= */
return (value <= cond->value.i);
return (value <= cond->rvalue.i);
case CONFIG_COND_GT: /** > */
return (value > cond->value.i);
return (value > cond->rvalue.i);
case CONFIG_COND_GE: /** >= */
return (value >= cond->value.i);
return (value >= cond->rvalue.i);
case CONFIG_COND_MATCH:
case CONFIG_COND_NOMATCH:
// TODO: die with error
@ -328,7 +309,7 @@ static gboolean ipv6_in_ipv4_net(const unsigned char *target, guint32 match, gui
#endif
static gboolean condition_check_eval(server *srv, connection *con, condition *cond) {
switch (cond->value_type) {
switch (cond->rvalue.type) {
case COND_VALUE_STRING:
return condition_check_eval_string(srv, con, cond);
case COND_VALUE_INT:

@ -1,6 +1,17 @@
#ifndef _LIGHTTPD_CONDITION_H_
#define _LIGHTTPD_CONDITION_H_
#include "settings.h"
struct condition_rvalue;
typedef struct condition_rvalue condition_rvalue;
struct condition_lvalue;
typedef struct condition_lvalue condition_lvalue;
struct condition;
typedef struct condition condition;
/**
* possible compare ops in the configfile parser
*/
@ -24,31 +35,67 @@ typedef enum {
* possible fields to match against
*/
typedef enum {
COMP_SERVER_SOCKET,
COMP_REQUEST_LOCALIP,
COMP_REQUEST_REMOTEIP,
COMP_REQUEST_PATH,
COMP_REQUEST_HOST,
COMP_REQUEST_REFERER,
COMP_REQUEST_USER_AGENT,
COMP_REQUEST_COOKIE,
COMP_REQUEST_SCHEME,
COMP_REQUEST_REMOTE_IP,
COMP_REQUEST_QUERY_STRING,
COMP_REQUEST_METHOD,
COMP_REQUEST_CONTENT_LENGTH,
COMP_PHYSICAL_PATH,
COMP_PHYSICAL_PATH_EXISTS,
COMP_PHYSICAL_SIZE
} comp_key_t;
COMP_PHYSICAL_SIZE,
/* needs a key */
COMP_REQUEST_HEADER
} cond_lvalue_t;
#define COND_LVALUE_FIRST_WITH_KEY COMP_REQUEST_HEADER
#define COND_LVALUE_END (1+COMP_REQUEST_HEADER)
struct condition_lvalue {
int refcount;
cond_lvalue_t type;
GString *key;
};
typedef enum {
COND_VALUE_INT,
COND_VALUE_STRING,
COND_VALUE_SOCKET_IPV4, /** only match ip/netmask */
COND_VALUE_SOCKET_IPV6 /** only match ip/netmask */
} cond_value_t;
#ifdef HAVE_PCRE_H
COND_VALUE_REGEXP,
#endif
COND_VALUE_SOCKET_IPV4 /** only match ip/netmask */
#ifdef HAVE_IPV6
,COND_VALUE_SOCKET_IPV6 /** only match ip/netmask */
#endif
} cond_rvalue_t;
struct condition;
typedef struct condition condition;
struct condition_rvalue {
cond_rvalue_t type;
GString *string;
#ifdef HAVE_PCRE_H
struct {
pcre *regex;
pcre_extra *regex_study;
};
#endif
gint64 i;
struct {
guint32 addr;
guint32 networkmask;
} ipv4;
#ifdef HAVE_IPV6
struct {
guint8 addr[16];
guint network;
} ipv6;
#endif
sock_addr addr;
};
#include "base.h"
@ -56,50 +103,25 @@ struct condition {
int refcount;
comp_operator_t op;
comp_key_t comp;
/* index into connection conditional caching table, -1 if uncached */
int cache_index;
cond_value_t value_type;
union {
GString *string;
#ifdef HAVE_PCRE_H
struct {
pcre *regex;
pcre_extra *regex_study;
};
#endif
gint64 i;
struct {
guint32 addr;
guint32 networkmask;
} ipv4;
#ifdef HAVE_IPV6
struct {
guint8 addr[16];
guint network;
} ipv6;
#endif
sock_addr addr;
} value;
condition_lvalue *lvalue;
condition_rvalue rvalue;
};
LI_API condition* condition_new_string(server *srv, comp_operator_t op, comp_key_t comp, GString *str);
LI_API condition* condition_new_int(server *srv, comp_operator_t op, comp_key_t comp, gint i);
/* lvalue */
LI_API condition_lvalue* condition_lvalue_new(cond_lvalue_t type, GString *key);
LI_API void condition_lvalue_acquire(condition_lvalue *lvalue);
LI_API void condition_lvalue_release(condition_lvalue *lvalue);
LI_API condition* condition_new_string_uncached(server *srv, comp_operator_t op, comp_key_t comp, GString *str);
LI_API condition* condition_new_int_uncached(server *srv, comp_operator_t op, comp_key_t comp, gint i);
struct option;
LI_API condition* condition_from_option(server *srv, struct option *opt);
LI_API condition* condition_new_string(server *srv, comp_operator_t op, condition_lvalue *lvalue, GString *str);
LI_API condition* condition_new_int(server *srv, comp_operator_t op, condition_lvalue *lvalue, gint i);
LI_API void condition_acquire(condition *c);
LI_API void condition_release(server *srv, condition* c);
LI_API const char* comp_op_to_string(comp_operator_t op);
LI_API const char* comp_key_to_string(comp_key_t comp);
LI_API const char* cond_lvalue_to_string(cond_lvalue_t t);
LI_API gboolean condition_check(server *srv, connection *con, condition *cond);

@ -1,10 +1,51 @@
#include "condition_lua.h"
#include "options_lua.h"
#include <lualib.h>
#include <lauxlib.h>
#define LUA_CONDITION "condition*"
#define LUA_COND_LVALUE "cond_lvalue*"
#define LUA_COND_LVALUE_T "cond_lvalue_t"
/* helper */
#define lua_mt_register_srv(srv, L, name, func) do {\
lua_pushlightuserdata(L, srv); \
lua_pushcclosure(L, func, 1); \
lua_setfield(L, -2, name); \
} while(0)
#define lua_mt_register(L, name, func) do {\
lua_pushcclosure(L, func, 0); \
lua_setfield(L, -2, name); \
} while(0)
static void lua_settop_in_dicts(lua_State *L, const gchar *path) {
int ndx, curtable;
gchar** segments;
size_t i;
ndx = lua_gettop(L);
segments = g_strsplit(path, ".", 10);
assert(segments[0]);
for (i = 0, curtable = LUA_GLOBALSINDEX; segments[i+1]; i++) {
lua_getfield(L, curtable, segments[i]);
if (lua_isnil(L, -1) || !lua_istable(L, -1)) {
lua_pop(L, 1); /* pop nil */
lua_newtable(L);
lua_pushvalue(L, -1); /* save table in field */
lua_setfield(L, curtable, segments[i]);
}
curtable = lua_gettop(L);
}
lua_pushvalue(L, ndx);
lua_setfield(L, curtable, segments[i]);
lua_pop(L, lua_gettop(L) - ndx + 1);
g_strfreev(segments);
}
/* Get objects from lua */
condition* lua_get_condition(lua_State *L, int ndx) {
if (!lua_isuserdata(L, ndx)) return NULL;
@ -18,6 +59,32 @@ condition* lua_get_condition(lua_State *L, int ndx) {
return *(condition**) lua_touserdata(L, ndx);
}
condition_lvalue* lua_get_condition_lvalue(lua_State *L, int ndx) {
if (!lua_isuserdata(L, ndx)) return NULL;
if (!lua_getmetatable(L, ndx)) return NULL;
luaL_getmetatable(L, LUA_COND_LVALUE);
if (lua_isnil(L, -1) || lua_isnil(L, -2) || !lua_equal(L, -1, -2)) {
lua_pop(L, 2);
return NULL;
}
lua_pop(L, 2);
return *(condition_lvalue**) lua_touserdata(L, ndx);
}
cond_lvalue_t lua_get_cond_lvalue_t(lua_State *L, int ndx) {
if (!lua_isuserdata(L, ndx)) return -1;
if (!lua_getmetatable(L, ndx)) return -1;
luaL_getmetatable(L, LUA_COND_LVALUE_T);
if (lua_isnil(L, -1) || lua_isnil(L, -2) || !lua_equal(L, -1, -2)) {
lua_pop(L, 2);
return -1;
}
lua_pop(L, 2);
return *(cond_lvalue_t*) lua_touserdata(L, ndx);
}
/* Garbage collection */
static int lua_condition_gc(lua_State *L) {
server *srv;
condition **c = (condition**) luaL_checkudata(L, 1, LUA_CONDITION);
@ -28,19 +95,143 @@ static int lua_condition_gc(lua_State *L) {
return 0;
}
static int lua_cond_lvalue_gc(lua_State *L) {
condition_lvalue **lvalue = (condition_lvalue**) luaL_checkudata(L, 1, LUA_COND_LVALUE);
if (!lvalue || !*lvalue) return 0;
condition_lvalue_release(*lvalue);
return 0;
}
/* new metatables and push */
static void lua_push_condition_metatable(server *srv, lua_State *L) {
if (luaL_newmetatable(L, LUA_CONDITION)) {
lua_mt_register_srv(srv, L, "__gc", lua_condition_gc);
}
}
int lua_push_condition(server *srv, lua_State *L, condition *c) {
condition **pc;
pc = (condition**) lua_newuserdata(L, sizeof(condition*));
condition_acquire(c);
*pc = c;
if (luaL_newmetatable(L, LUA_CONDITION)) {
lua_pushlightuserdata(L, srv);
lua_pushcclosure(L, lua_condition_gc, 1);
lua_setfield(L, -2, "__gc");
lua_push_condition_metatable(srv, L);
lua_setmetatable(L, -2);
return 1;
}
/* cond_lvalue metatable (except __gc) */
static int lua_cond_lvalue_tostring(lua_State *L) {
condition_lvalue *lvalue = lua_get_condition_lvalue(L, 1);
if (!lvalue) return 0;
lua_pushstring(L, cond_lvalue_to_string(lvalue->type));
if (lvalue->key) {
lua_pushstring(L, "['");
lua_pushstring(L, lvalue->key->str);
lua_pushstring(L, "']");
lua_concat(L, 4);
}
return 1;
}
static int lua_cond_lvalue_eq(lua_State *L) {
server *srv;
GString *sval;
condition *c;
condition_lvalue *lvalue = lua_get_condition_lvalue(L, 1);
srv = (server*) lua_touserdata(L, lua_upvalueindex(1));
if (NULL == (sval = lua_togstring(L, 2))) return 0;
c = condition_new_string(srv, CONFIG_COND_EQ, lvalue, sval);
if (c) {
condition_lvalue_acquire(lvalue);
lua_push_condition(srv, L, c);
return 1;
}
return 0;
}
static void lua_push_cond_lvalue_metatable(server *srv, lua_State *L) {
if (luaL_newmetatable(L, LUA_COND_LVALUE)) {
lua_mt_register(L, "__gc", lua_cond_lvalue_gc);
lua_mt_register(L, "__tostring", lua_cond_lvalue_tostring);
lua_mt_register_srv(srv, L, "eq", lua_cond_lvalue_eq);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
}
}
int lua_push_cond_lvalue(server *srv, lua_State *L, condition_lvalue *lvalue) {
condition_lvalue **pv;
pv = (condition_lvalue**) lua_newuserdata(L, sizeof(condition_lvalue*));
*pv = lvalue;
lua_push_cond_lvalue_metatable(srv, L);
lua_setmetatable(L, -2);
return 1;
}
/* cond_lvalue_t metatable */
static int lua_cond_lvalue_t_tostring(lua_State *L) {
cond_lvalue_t t = lua_get_cond_lvalue_t(L, 1);
lua_pushstring(L, cond_lvalue_to_string(t));
return 1;
}
static int lua_cond_lvalue_t_index(lua_State *L) {
server *srv;
GString *key;
cond_lvalue_t t = lua_get_cond_lvalue_t(L, 1);
srv = (server*) lua_touserdata(L, lua_upvalueindex(1));
if (t < COND_LVALUE_FIRST_WITH_KEY || t >= COND_LVALUE_END) return 0;
if (NULL == (key = lua_togstring(L, 2))) return 0;
lua_push_cond_lvalue(srv, L, condition_lvalue_new(t, key));
return 1;
}
static void lua_push_cond_lvalue_t_metatable(server *srv, lua_State *L) {
if (luaL_newmetatable(L, LUA_COND_LVALUE_T)) {
lua_mt_register(L, "__tostring", lua_cond_lvalue_t_tostring);
lua_mt_register_srv(srv, L, "__index", lua_cond_lvalue_t_index);
}
}
/* cond_lvalue_t */
int lua_push_cond_lvalue_t(server *srv, lua_State *L, cond_lvalue_t t) {
cond_lvalue_t *pt;
pt = (cond_lvalue_t*) lua_newuserdata(L, sizeof(cond_lvalue_t));
*pt = t;
lua_push_cond_lvalue_t_metatable(srv, L);
lua_setmetatable(L, -2);
return 1;
}
void lua_push_lvalues_dict(server *srv, lua_State *L) {
size_t i;
for (i = 0; i < COND_LVALUE_FIRST_WITH_KEY; i++) {
lua_push_cond_lvalue(srv, L, condition_lvalue_new(i, NULL));
lua_settop_in_dicts(L, cond_lvalue_to_string(i));
}
for ( ; i < COND_LVALUE_END; i++) {
lua_push_cond_lvalue_t(srv, L, i);
lua_settop_in_dicts(L, cond_lvalue_to_string(i));
}
}

@ -7,4 +7,6 @@
condition* lua_get_condition(lua_State *L, int ndx);
int lua_push_condition(server *srv, lua_State *L, condition *c);
void lua_push_lvalues_dict(server *srv, lua_State *L);
#endif

@ -1,5 +1,6 @@
#include "base.h"
#include "config_lua.h"
#include "condition_lua.h"
#include "options_lua.h"
#include "actions_lua.h"
@ -8,7 +9,7 @@
typedef int (*LuaWrapper)(server *srv, lua_State *L, gpointer data);
option* lua_params_to_option(server *srv, lua_State *L) {
static option* lua_params_to_option(server *srv, lua_State *L) {
option *opt, *subopt;
switch (lua_gettop(L)) {
case 0:
@ -201,6 +202,7 @@ gboolean config_lua_load(server *srv, const gchar *filename) {
lua_pushcclosure(L, handle_option, 1);
lua_setfield(L, LUA_GLOBALSINDEX, "option");
lua_push_lvalues_dict(srv, L);
if (lua_pcall(L, 0, 1, 0)) {
ERROR(srv, "lua_pcall(): %s", lua_tostring(L, -1));

@ -0,0 +1,8 @@
#ifndef _LIGHTTPD_CONFIG_LUA_H_
#define _LIGHTTPD_CONFIG_LUA_H_
#include "base.h"
LI_API gboolean config_lua_load(server *srv, const gchar *filename);
#endif

@ -2,6 +2,7 @@
#include "base.h"
#include "log.h"
#include "config_parser.h"
#include "config_lua.h"
void plugin_core_init(server *srv, plugin *p);

@ -29,9 +29,9 @@ static action* core_list(server *srv, plugin* p, option *opt) {
static action* core_when(server *srv, plugin* p, option *opt) {
option *opt_cond, *opt_act;
condition *c;
action *a;
UNUSED(p);
if (opt->type != OPTION_LIST) {
ERROR(srv, "expected list, got %s", option_type_string(opt->type));
return NULL;
@ -46,11 +46,11 @@ static action* core_when(server *srv, plugin* p, option *opt) {
ERROR(srv, "expected action as second parameter, got %s", option_type_string(opt->type));
return NULL;
}
if (NULL == (c = condition_from_option(srv, opt_cond))) {
if (opt_cond->type != OPTION_CONDITION) {
ERROR(srv, "expected condition as first parameter, got %s", option_type_string(opt->type));
return NULL;
}
a = action_new_condition(c, action_list_from_action(opt_act->value.opt_action.action));
a = action_new_condition(opt_cond->value.opt_cond.cond, action_list_from_action(opt_act->value.opt_action.action));
option_free(opt);
return a;
}

Loading…
Cancel
Save