merge from lp
commit
1d624ff022
|
@ -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
|
||||
|
|
177
src/condition.c
177
src/condition.c
|
@ -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);
|
||||
|
||||
g_string_free(key, TRUE);
|
||||
void condition_lvalue_acquire(condition_lvalue *lvalue) {
|
||||
assert(lvalue->refcount > 0);
|
||||
lvalue->refcount++;
|
||||
}
|
||||
|
||||
static condition* condition_new(comp_operator_t op, comp_key_t comp) {
|
||||
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, 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);
|
||||
}
|
||||
|
||||
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:
|
||||
|
|
116
src/condition.h
116
src/condition.h
|
@ -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;
|
||||
|
@ -41,16 +41,16 @@ static action* core_when(server *srv, plugin* p, option *opt) {
|
|||
return NULL;
|
||||
}
|
||||
opt_cond = g_array_index(opt->value.opt_list, option*, 0);
|
||||
opt_act = g_array_index(opt->value.opt_list, option*, 0);
|
||||
opt_act = g_array_index(opt->value.opt_list, option*, 1);
|
||||
if (opt_act->type != OPTION_ACTION) {
|
||||
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…
Reference in New Issue