parent
897b27c692
commit
659ebfdd16
@ -0,0 +1,73 @@
|
||||
#ifndef _LIGHTTPD_CORE_LUA_H_
|
||||
#define _LIGHTTPD_CORE_LUA_H_
|
||||
|
||||
#include <lighttpd/base.h>
|
||||
#include <lua.h>
|
||||
|
||||
#define li_lua_lock(srv) g_mutex_lock((srv)->lualock);
|
||||
#define li_lua_unlock(srv) g_mutex_unlock((srv)->lualock);
|
||||
|
||||
LI_API void lua_init_chunk_mt(lua_State *L);
|
||||
LI_API liChunk* lua_get_chunk(lua_State *L, int ndx);
|
||||
LI_API int lua_push_chunk(lua_State *L, liChunk *c);
|
||||
LI_API liChunkQueue* lua_get_chunkqueue(lua_State *L, int ndx);
|
||||
LI_API int lua_push_chunkqueue(lua_State *L, liChunkQueue *cq);
|
||||
|
||||
LI_API void lua_init_connection_mt(lua_State *L);
|
||||
LI_API liConnection* lua_get_connection(lua_State *L, int ndx);
|
||||
LI_API int lua_push_connection(lua_State *L, liConnection *con);
|
||||
|
||||
LI_API void lua_init_environment_mt(lua_State *L);
|
||||
LI_API liEnvironment* lua_get_environment(lua_State *L, int ndx);
|
||||
LI_API int lua_push_environment(lua_State *L, liEnvironment *env);
|
||||
|
||||
LI_API void lua_init_http_headers_mt(lua_State *L);
|
||||
LI_API liHttpHeaders* lua_get_http_headers(lua_State *L, int ndx);
|
||||
LI_API int lua_push_http_headers(lua_State *L, liHttpHeaders *headers);
|
||||
|
||||
LI_API void lua_init_physical_mt(lua_State *L);
|
||||
LI_API liPhysical* lua_get_physical(lua_State *L, int ndx);
|
||||
LI_API int lua_push_physical(lua_State *L, liPhysical *phys);
|
||||
|
||||
LI_API void lua_init_request_mt(lua_State *L);
|
||||
LI_API liRequest* lua_get_request(lua_State *L, int ndx);
|
||||
LI_API int lua_push_request(lua_State *L, liRequest *req);
|
||||
|
||||
LI_API liRequestUri* lua_get_requesturi(lua_State *L, int ndx);
|
||||
LI_API int lua_push_requesturi(lua_State *L, liRequestUri *uri);
|
||||
|
||||
LI_API void lua_init_response_mt(lua_State *L);
|
||||
LI_API liResponse* lua_get_response(lua_State *L, int ndx);
|
||||
LI_API int lua_push_response(lua_State *L, liResponse *resp);
|
||||
|
||||
LI_API void lua_init_vrequest_mt(lua_State *L);
|
||||
LI_API liVRequest* lua_get_vrequest(lua_State *L, int ndx);
|
||||
LI_API int lua_push_vrequest(lua_State *L, liVRequest *vr);
|
||||
|
||||
|
||||
/* return 1 if value is found in mt (on top of the stack), 0 if it is not found (stack balance = 0)
|
||||
* table, key on stack at pos 0 and 1 (i.e. __index metho)
|
||||
*/
|
||||
LI_API int li_lua_metatable_index(lua_State *L);
|
||||
|
||||
LI_API void li_lua_init(liServer *srv, lua_State *L);
|
||||
|
||||
LI_API int li_lua_push_traceback(lua_State *L, int narg);
|
||||
|
||||
LI_API void li_lua_restore_globals(lua_State *L);
|
||||
LI_API void li_lua_new_globals(lua_State *L);
|
||||
|
||||
/* joinWith " " (map tostring parameter[from..to]) */
|
||||
LI_API GString* lua_print_get_string(lua_State *L, int from, int to);
|
||||
|
||||
/* pairs() for a GHashTable GString -> GString:
|
||||
* Don't modify the hastable while iterating:
|
||||
* - no new keys
|
||||
* - no delete
|
||||
* Modifying values is fine; g_hash_table_insert() as long as the key already exists too.
|
||||
* The returned "next" function has an internal state, it ignores the table/state and previous key parameter.
|
||||
* returns: <next>, nil, nil on the stack (and 3 as c function)
|
||||
*/
|
||||
LI_API int li_lua_ghashtable_gstring_pairs(lua_State *L, GHashTable *ht);
|
||||
|
||||
#endif
|
@ -0,0 +1,108 @@
|
||||
|
||||
#include <lighttpd/core_lua.h>
|
||||
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#define LUA_CHUNK "liChunk*"
|
||||
#define LUA_CHUNKQUEUE "liChunkQueue*"
|
||||
|
||||
static void init_chunk_mt(lua_State *L) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static int lua_chunkqueue_add(lua_State *L) {
|
||||
liChunkQueue *cq;
|
||||
const char *s;
|
||||
size_t len;
|
||||
|
||||
luaL_checkany(L, 2);
|
||||
cq = lua_get_chunkqueue(L, 1);
|
||||
if (cq == NULL) return 0;
|
||||
if (lua_isstring(L, 2)) {
|
||||
s = lua_tolstring(L, 2, &len);
|
||||
li_chunkqueue_append_mem(cq, s, len);
|
||||
} else {
|
||||
lua_pushliteral(L, "Wrong type for chunkqueue add");
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg chunkqueue_mt[] = {
|
||||
{ "add", lua_chunkqueue_add },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static void init_chunkqueue_mt(lua_State *L) {
|
||||
luaL_register(L, NULL, chunkqueue_mt);
|
||||
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -2, "__index");
|
||||
}
|
||||
|
||||
void lua_init_chunk_mt(lua_State *L) {
|
||||
if (luaL_newmetatable(L, LUA_CHUNK)) {
|
||||
init_chunk_mt(L);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (luaL_newmetatable(L, LUA_CHUNKQUEUE)) {
|
||||
init_chunkqueue_mt(L);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
liChunk* lua_get_chunk(lua_State *L, int ndx) {
|
||||
if (!lua_isuserdata(L, ndx)) return NULL;
|
||||
if (!lua_getmetatable(L, ndx)) return NULL;
|
||||
luaL_getmetatable(L, LUA_CHUNK);
|
||||
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 *(liChunk**) lua_touserdata(L, ndx);
|
||||
}
|
||||
|
||||
int lua_push_chunk(lua_State *L, liChunk *c) {
|
||||
liChunk **pc;
|
||||
|
||||
pc = (liChunk**) lua_newuserdata(L, sizeof(liChunk*));
|
||||
*pc = c;
|
||||
|
||||
if (luaL_newmetatable(L, LUA_CHUNK)) {
|
||||
init_chunk_mt(L);
|
||||
}
|
||||
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
liChunkQueue* lua_get_chunkqueue(lua_State *L, int ndx) {
|
||||
if (!lua_isuserdata(L, ndx)) return NULL;
|
||||
if (!lua_getmetatable(L, ndx)) return NULL;
|
||||
luaL_getmetatable(L, LUA_CHUNKQUEUE);
|
||||
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 *(liChunkQueue**) lua_touserdata(L, ndx);
|
||||
}
|
||||
|
||||
int lua_push_chunkqueue(lua_State *L, liChunkQueue *cq) {
|
||||
liChunkQueue **pcq;
|
||||
|
||||
pcq = (liChunkQueue**) lua_newuserdata(L, sizeof(liChunkQueue*));
|
||||
*pcq = cq;
|
||||
|
||||
if (luaL_newmetatable(L, LUA_CHUNKQUEUE)) {
|
||||
init_chunkqueue_mt(L);
|
||||
}
|
||||
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
|
||||
#include <lighttpd/core_lua.h>
|
||||
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#define LUA_CONNECTION "liConnection*"
|
||||
|
||||
static void init_con_mt(lua_State *L) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
void lua_init_connection_mt(lua_State *L) {
|
||||
if (luaL_newmetatable(L, LUA_CONNECTION)) {
|
||||
init_con_mt(L);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
liConnection* lua_get_connection(lua_State *L, int ndx) {
|
||||
if (!lua_isuserdata(L, ndx)) return NULL;
|
||||
if (!lua_getmetatable(L, ndx)) return NULL;
|
||||
luaL_getmetatable(L, LUA_CONNECTION);
|
||||
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 *(liConnection**) lua_touserdata(L, ndx);
|
||||
}
|
||||
|
||||
int lua_push_connection(lua_State *L, liConnection *con) {
|
||||
liConnection **pcon;
|
||||
|
||||
pcon = (liConnection**) lua_newuserdata(L, sizeof(liConnection*));
|
||||
*pcon = con;
|
||||
|
||||
if (luaL_newmetatable(L, LUA_CONNECTION)) {
|
||||
init_con_mt(L);
|
||||
}
|
||||
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
@ -0,0 +1,201 @@
|
||||
|
||||
#include <lighttpd/core_lua.h>
|
||||
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
static int traceback (lua_State *L) {
|
||||
if (!lua_isstring(L, 1)) /* 'message' not a string? */
|
||||
return 1; /* keep it intact */
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, "debug");
|
||||
if (!lua_istable(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
lua_getfield(L, -1, "traceback");
|
||||
if (!lua_isfunction(L, -1)) {
|
||||
lua_pop(L, 2);
|
||||
return 1;
|
||||
}
|
||||
lua_pushvalue(L, 1); /* pass error message */
|
||||
lua_pushinteger(L, 2); /* skip this function and traceback */
|
||||
lua_call(L, 2, 1); /* call debug.traceback */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int li_lua_push_traceback(lua_State *L, int narg) {
|
||||
int base = lua_gettop(L) - narg; /* function index */
|
||||
lua_pushcfunction(L, traceback);
|
||||
lua_insert(L, base);
|
||||
return base;
|
||||
}
|
||||
|
||||
int li_lua_metatable_index(lua_State *L) {
|
||||
/* search for entry in mt, i.e. functions */
|
||||
if (!lua_getmetatable(L, 1)) return 0; /* +1 */
|
||||
|
||||
lua_pushvalue(L, 2); /* +1 */
|
||||
lua_rawget(L, -2); /* */
|
||||
|
||||
if (!lua_isnil(L, -1)) return 1;
|
||||
|
||||
lua_pop(L, 2); /* -2 */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void li_lua_store_globals(lua_State *L) {
|
||||
/* backup global table reference */
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX); /* +1 */
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "li_globals"); /* -1 */
|
||||
}
|
||||
|
||||
GString* lua_print_get_string(lua_State *L, int from, int to) {
|
||||
int i, n = lua_gettop(L);
|
||||
GString *buf = g_string_sized_new(0);
|
||||
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, "tostring");
|
||||
for (i = from; i <= to; i++) {
|
||||
const char *s;
|
||||
size_t len;
|
||||
|
||||
lua_pushvalue(L, n+1);
|
||||
lua_pushvalue(L, i);
|
||||
lua_call(L, 1, 1);
|
||||
s = lua_tolstring(L, -1, &len);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (NULL == s) {
|
||||
g_string_free(buf, TRUE);
|
||||
lua_pushliteral(L, "lua_print_get_string: Couldn't convert parameter to string");
|
||||
lua_error(L);
|
||||
}
|
||||
if (0 == len) continue;
|
||||
if (buf->len > 0) {
|
||||
g_string_append_c(buf, ' ');
|
||||
g_string_append_len(buf, s, len);
|
||||
} else {
|
||||
g_string_append_len(buf, s, len);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int li_lua_error(lua_State *L) {
|
||||
liServer *srv = lua_touserdata(L, lua_upvalueindex(1));
|
||||
GString *buf = lua_print_get_string(L, 1, lua_gettop(L));
|
||||
|
||||
ERROR(srv, "(lua): %s", buf->str);
|
||||
|
||||
g_string_free(buf, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int li_lua_warning(lua_State *L) {
|
||||
liServer *srv = lua_touserdata(L, lua_upvalueindex(1));
|
||||
GString *buf = lua_print_get_string(L, 1, lua_gettop(L));
|
||||
|
||||
WARNING(srv, "(lua): %s", buf->str);
|
||||
|
||||
g_string_free(buf, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int li_lua_info(lua_State *L) {
|
||||
liServer *srv = lua_touserdata(L, lua_upvalueindex(1));
|
||||
GString *buf = lua_print_get_string(L, 1, lua_gettop(L));
|
||||
|
||||
INFO(srv, "(lua): %s", buf->str);
|
||||
|
||||
g_string_free(buf, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int li_lua_debug(lua_State *L) {
|
||||
liServer *srv = lua_touserdata(L, lua_upvalueindex(1));
|
||||
GString *buf = lua_print_get_string(L, 1, lua_gettop(L));
|
||||
|
||||
DEBUG(srv, "(lua): %s", buf->str);
|
||||
|
||||
g_string_free(buf, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void li_lua_init(liServer *srv, lua_State *L) {
|
||||
lua_init_chunk_mt(L);
|
||||
lua_init_connection_mt(L);
|
||||
lua_init_environment_mt(L);
|
||||
lua_init_physical_mt(L);
|
||||
lua_init_request_mt(L);
|
||||
lua_init_response_mt(L);
|
||||
lua_init_vrequest_mt(L);
|
||||
|
||||
/* prefer closure, but just in case */
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "lighty.srv");
|
||||
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_pushcclosure(L, li_lua_error, 1);
|
||||
lua_setfield(L, LUA_GLOBALSINDEX, "print");
|
||||
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_pushcclosure(L, li_lua_warning, 1);
|
||||
lua_setfield(L, LUA_GLOBALSINDEX, "warning");
|
||||
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_pushcclosure(L, li_lua_info, 1);
|
||||
lua_setfield(L, LUA_GLOBALSINDEX, "info");
|
||||
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_pushcclosure(L, li_lua_debug, 1);
|
||||
lua_setfield(L, LUA_GLOBALSINDEX, "debug");
|
||||
|
||||
li_lua_store_globals(L);
|
||||
}
|
||||
|
||||
void li_lua_restore_globals(lua_State *L) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "li_globals"); /* +1 */
|
||||
lua_replace(L, LUA_GLOBALSINDEX); /* -1 */
|
||||
}
|
||||
|
||||
void li_lua_new_globals(lua_State *L) {
|
||||
lua_newtable(L); /* +1 */
|
||||
|
||||
/* metatable for new global env, link old globals as readonly */
|
||||
lua_newtable(L); /* +1 */
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX); /* +1 */
|
||||
lua_setfield(L, -2, "__index"); /* -1 */
|
||||
lua_setmetatable(L, -2); /* -1 */
|
||||
|
||||
lua_replace(L, LUA_GLOBALSINDEX); /* -1 */
|
||||
}
|
||||
|
||||
|
||||
static int ghashtable_gstring_next(lua_State *L) {
|
||||
GHashTableIter *it = lua_touserdata(L, lua_upvalueindex(1));
|
||||
gpointer pkey = NULL, pvalue = NULL;
|
||||
|
||||
/* ignore arguments */
|
||||
if (g_hash_table_iter_next(it, &pkey, &pvalue)) {
|
||||
GString *key = pkey, *value = pvalue;
|
||||
lua_pushlstring(L, key->str, key->len);
|
||||
lua_pushlstring(L, value->str, value->len);
|
||||
return 2;
|
||||
}
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int li_lua_ghashtable_gstring_pairs(lua_State *L, GHashTable *ht) {
|
||||
GHashTableIter *it = lua_newuserdata(L, sizeof(GHashTableIter)); /* +1 */
|
||||
g_hash_table_iter_init(it, ht);
|
||||
lua_pushcclosure(L, ghashtable_gstring_next, 1); /* -1, +1 */
|
||||
lua_pushnil(L); lua_pushnil(L); /* +2 */
|
||||
return 3;
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
|
||||
#include <lighttpd/core_lua.h>
|
||||
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#define LUA_ENVIRONMENT "liEnvironment*"
|
||||
|
||||
static int lua_environment_get(lua_State *L) {
|
||||
liEnvironment *env;
|
||||
const char *ckey;
|
||||
size_t keylen;
|
||||
GString *val;
|
||||
|
||||
luaL_checkany(L, 2);
|
||||
if (NULL == (env = lua_get_environment(L, 1))) return 0;
|
||||
if (NULL == (ckey = lua_tolstring(L, 2, &keylen))) return 0;
|
||||
|
||||
val = li_environment_get(env, ckey, keylen);
|
||||
if (val) {
|
||||
lua_pushlstring(L, val->str, val->len);
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_environment_index(lua_State *L) {
|
||||
if (li_lua_metatable_index(L)) return 1;
|
||||
|
||||
return lua_environment_get(L);
|
||||
}
|
||||
|
||||
static int lua_environment_set(lua_State *L) {
|
||||
liEnvironment *env;
|
||||
const char *ckey, *cval;
|
||||
size_t keylen, vallen;
|
||||
|
||||
luaL_checkany(L, 3);
|
||||
if (NULL == (env = lua_get_environment(L, 1))) return 0;
|
||||
if (NULL == (ckey = lua_tolstring(L, 2, &keylen))) return 0;
|
||||
if (lua_isnil(L, 3)) {
|
||||
li_environment_remove(env, ckey, keylen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (NULL == (cval = lua_tolstring(L, 3, &vallen))) return 0;
|
||||
|
||||
li_environment_set(env, ckey, keylen, cval, vallen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_environment_unset(lua_State *L) {
|
||||
liEnvironment *env;
|
||||
const char *ckey;
|
||||
size_t keylen;
|
||||
|
||||
luaL_checkany(L, 2);
|
||||
if (NULL == (env = lua_get_environment(L, 1))) return 0;
|
||||
if (NULL == (ckey = lua_tolstring(L, 2, &keylen))) return 0;
|
||||
li_environment_remove(env, ckey, keylen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_environment_weak_set(lua_State *L) {
|
||||
liEnvironment *env;
|
||||
const char *ckey, *cval;
|
||||
size_t keylen, vallen;
|
||||
|
||||
luaL_checkany(L, 3);
|
||||
if (NULL == (env = lua_get_environment(L, 1))) return 0;
|
||||
if (NULL == (ckey = lua_tolstring(L, 2, &keylen))) return 0;
|
||||
if (NULL == (cval = lua_tolstring(L, 3, &vallen))) return 0;
|
||||
|
||||
li_environment_insert(env, ckey, keylen, cval, vallen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_environment_clear(lua_State *L) {
|
||||
liEnvironment *env;
|
||||
|
||||
luaL_checkany(L, 1);
|
||||
if (NULL == (env = lua_get_environment(L, 1))) return 0;
|
||||
|
||||
li_environment_reset(env);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_environment_pairs(lua_State *L) {
|
||||
liEnvironment *env;
|
||||
|
||||
luaL_checkany(L, 1);
|
||||
env = lua_get_environment(L, 1);
|
||||
|
||||
if (!env) return 0;
|
||||
return li_lua_ghashtable_gstring_pairs(L, env->table);
|
||||
}
|
||||
|
||||
static const luaL_Reg environment_mt[] = {
|
||||
{ "__index", lua_environment_index },
|
||||
{ "get", lua_environment_get },
|
||||
{ "__newindex", lua_environment_set },
|
||||
{ "set", lua_environment_set },
|
||||
{ "unset", lua_environment_unset },
|
||||
{ "weak_set", lua_environment_weak_set },
|
||||
{ "__pairs", lua_environment_pairs },
|
||||
{ "pairs", lua_environment_pairs },
|
||||
{ "clear", lua_environment_clear },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static void init_env_mt(lua_State *L) {
|
||||
luaL_register(L, NULL, environment_mt);
|
||||
}
|
||||
|
||||
void lua_init_environment_mt(lua_State *L) {
|
||||
if (luaL_newmetatable(L, LUA_ENVIRONMENT)) {
|
||||
init_env_mt(L);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
liEnvironment* lua_get_environment(lua_State *L, int ndx) {
|
||||
if (!lua_isuserdata(L, ndx)) return NULL;
|
||||
if (!lua_getmetatable(L, ndx)) return NULL;
|
||||
luaL_getmetatable(L, LUA_ENVIRONMENT);
|
||||
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 *(liEnvironment**) lua_touserdata(L, ndx);
|
||||
}
|
||||
|
||||
int lua_push_environment(lua_State *L, liEnvironment *env) {
|
||||
liEnvironment **penv;
|
||||
|
||||
penv = (liEnvironment**) lua_newuserdata(L, sizeof(liEnvironment*));
|
||||
*penv = env;
|
||||
|
||||
if (luaL_newmetatable(L, LUA_ENVIRONMENT)) {
|
||||
init_env_mt(L);
|
||||
}
|
||||
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
@ -0,0 +1,240 @@
|
||||
|
||||
#include <lighttpd/core_lua.h>
|
||||
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#define LUA_HTTPHEADERS "liHttpHeaders*"
|
||||
|
||||
static int lua_http_headers_get(lua_State *L) {
|
||||
liHttpHeaders *headers;
|
||||
const char *ckey;
|
||||
size_t keylen;
|
||||
GString *val;
|
||||
|
||||
luaL_checkany(L, 2);
|
||||
if (NULL == (headers = lua_get_http_headers(L, 1))) return 0;
|
||||
if (NULL == (ckey = lua_tolstring(L, 2, &keylen))) return 0;
|
||||
|
||||
val = g_string_sized_new(0);
|
||||
li_http_header_get_all(val, headers, ckey, keylen);
|
||||
lua_pushlstring(L, val->str, val->len);
|
||||
g_string_free(val, TRUE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_http_headers_index(lua_State *L) {
|
||||
if (li_lua_metatable_index(L)) return 1;
|
||||
|
||||
return lua_http_headers_get(L);
|
||||
}
|
||||
|
||||
static int lua_http_headers_set(lua_State *L) {
|
||||
liHttpHeaders *headers;
|
||||
const char *ckey, *cval;
|
||||
size_t keylen, vallen;
|
||||
|
||||
luaL_checkany(L, 3);
|
||||
if (NULL == (headers = lua_get_http_headers(L, 1))) return 0;
|
||||
if (NULL == (ckey = lua_tolstring(L, 2, &keylen))) return 0;
|
||||
if (lua_isnil(L, 3)) {
|
||||
li_http_header_remove(headers, ckey, keylen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (NULL == (cval = lua_tolstring(L, 3, &vallen))) return 0;
|
||||
|
||||
li_http_header_remove(headers, ckey, keylen);
|
||||
li_http_header_insert(headers, ckey, keylen, cval, vallen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_http_headers_append(lua_State *L) {
|
||||
liHttpHeaders *headers;
|
||||
const char *ckey, *cval;
|
||||
size_t keylen, vallen;
|
||||
|
||||
luaL_checkany(L, 3);
|
||||
if (NULL == (headers = lua_get_http_headers(L, 1))) return 0;
|
||||
if (NULL == (ckey = lua_tolstring(L, 2, &keylen))) return 0;
|
||||
if (lua_isnil(L, 3)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (NULL == (cval = lua_tolstring(L, 3, &vallen))) return 0;
|
||||
|
||||
li_http_header_append(headers, ckey, keylen, cval, vallen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_http_headers_insert(lua_State *L) {
|
||||
liHttpHeaders *headers;
|
||||
const char *ckey, *cval;
|
||||
size_t keylen, vallen;
|
||||
|
||||
luaL_checkany(L, 3);
|
||||
if (NULL == (headers = lua_get_http_headers(L, 1))) return 0;
|
||||
if (NULL == (ckey = lua_tolstring(L, 2, &keylen))) return 0;
|
||||
if (lua_isnil(L, 3)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (NULL == (cval = lua_tolstring(L, 3, &vallen))) return 0;
|
||||
|
||||
li_http_header_insert(headers, ckey, keylen, cval, vallen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_http_headers_unset(lua_State *L) {
|
||||
liHttpHeaders *headers;
|
||||
const char *ckey;
|
||||
size_t keylen;
|
||||
|
||||
luaL_checkany(L, 2);
|
||||
if (NULL == (headers = lua_get_http_headers(L, 1))) return 0;
|
||||
if (NULL == (ckey = lua_tolstring(L, 2, &keylen))) return 0;
|
||||
li_http_header_remove(headers, ckey, keylen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_http_headers_clear(lua_State *L) {
|
||||
liHttpHeaders *headers;
|
||||
|
||||
luaL_checkany(L, 1);
|
||||
if (NULL == (headers = lua_get_http_headers(L, 1))) return 0;
|
||||
li_http_headers_reset(headers);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_http_headers_next(lua_State *L) {
|
||||
liHttpHeader *h;
|
||||
liHttpHeaders *headers = lua_touserdata(L, lua_upvalueindex(1));
|
||||
GList *l = lua_touserdata(L, lua_upvalueindex(2));
|
||||
const char *ckey;
|
||||
size_t keylen;
|
||||
ckey = lua_tolstring(L, lua_upvalueindex(3), &keylen);
|
||||
|
||||
if (!headers && !l) goto endoflist;
|
||||
|
||||
if (headers) {
|
||||
lua_pushnil(L);
|
||||
lua_replace(L, lua_upvalueindex(1));
|
||||
if (ckey) {
|
||||
l = li_http_header_find_first(headers, ckey, keylen);
|
||||
} else {
|
||||
l = headers->entries.head;
|
||||
}
|
||||
} else {
|
||||
if (ckey) {
|
||||
l = li_http_header_find_next(l, ckey, keylen);
|
||||
} else {
|
||||
l = g_list_next(l);
|
||||
}
|
||||
}
|
||||
|
||||
if (!l) goto endoflist;
|
||||
|
||||
h = l->data;
|
||||
lua_pushlstring(L, h->data->str, h->keylen);
|
||||
if (h->data->len > h->keylen + 2) {
|
||||
lua_pushlstring(L, h->data->str + (h->keylen + 2), h->data->len - (h->keylen + 2));
|
||||
} else {
|
||||
lua_pushliteral(L, "");
|
||||
}
|
||||
|
||||
lua_pushlightuserdata(L, l);
|
||||
lua_replace(L, lua_upvalueindex(2));
|
||||
|
||||
return 2;
|
||||
|
||||
endoflist:
|
||||
lua_pushnil(L);
|
||||
lua_replace(L, lua_upvalueindex(1));
|
||||
lua_pushnil(L);
|
||||
lua_replace(L, lua_upvalueindex(2));
|
||||
lua_pushnil(L);
|
||||
lua_replace(L, lua_upvalueindex(3));
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_http_headers_pairs(lua_State *L) {
|
||||
liHttpHeaders *headers;
|
||||
gboolean haskey = FALSE;
|
||||
|
||||
luaL_checkany(L, 1);
|
||||
headers = lua_get_http_headers(L, 1);
|
||||
|
||||
if (lua_gettop(L) == 2) {
|
||||
luaL_checkstring(L, 2);
|
||||
haskey = TRUE;
|
||||
}
|
||||
|
||||
if (!headers) return 0;
|
||||
|
||||
lua_pushlightuserdata(L, headers);
|
||||
lua_pushlightuserdata(L, NULL);
|
||||
if (haskey) {
|
||||
lua_pushvalue(L, 2);
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
lua_pushcclosure(L, lua_http_headers_next, 3);
|
||||
|
||||
return 1;
|
||||
// return li_lua_ghashtable_gstring_pairs(L, env->table);
|
||||
}
|
||||
|
||||
static const luaL_Reg http_headers_mt[] = {
|
||||
{ "__index", lua_http_headers_index },
|
||||
{ "get", lua_http_headers_get },
|
||||
{ "__newindex", lua_http_headers_set },
|
||||
{ "set", lua_http_headers_set },
|
||||
{ "append", lua_http_headers_append },
|
||||
{ "insert", lua_http_headers_insert },
|
||||
{ "unset", lua_http_headers_unset },
|
||||
{ "__pairs", lua_http_headers_pairs },
|
||||
{ "pairs", lua_http_headers_pairs },
|
||||
{ "list", lua_http_headers_pairs },
|
||||
{ "clear", lua_http_headers_clear },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static void init_http_headers_mt(lua_State *L) {
|
||||
luaL_register(L, NULL, http_headers_mt);
|
||||
}
|
||||
|
||||
void lua_init_http_headers_mt(lua_State *L) {
|
||||
if (luaL_newmetatable(L, LUA_HTTPHEADERS)) {
|
||||
init_http_headers_mt(L);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
liHttpHeaders* lua_get_http_headers(lua_State *L, int ndx) {
|
||||
if (!lua_isuserdata(L, ndx)) return NULL;
|
||||
if (!lua_getmetatable(L, ndx)) return NULL;
|
||||
luaL_getmetatable(L, LUA_HTTPHEADERS);
|
||||
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 *(liHttpHeaders**) lua_touserdata(L, ndx);
|
||||
}
|
||||
|
||||
int lua_push_http_headers(lua_State *L, liHttpHeaders *headers) {
|
||||
liHttpHeaders **pheaders;
|
||||
|
||||
pheaders = (liHttpHeaders**) lua_newuserdata(L, sizeof(liHttpHeaders*));
|
||||
*pheaders = headers;
|
||||
|
||||
if (luaL_newmetatable(L, LUA_HTTPHEADERS)) {
|
||||
init_http_headers_mt(L);
|
||||
}
|
||||
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
|
||||
#include <lighttpd/core_lua.h>
|
||||
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#define LUA_PHYSICAL "liPhysical*"
|
||||
|
||||
typedef int (*lua_Physical_Attrib)(liPhysical *phys, lua_State *L);
|
||||
|
||||
#define DEF_LUA_MODIFY_GSTRING(attr) \
|
||||
static int lua_physical_attr_read_##attr(liPhysical *phys, lua_State *L) { \
|
||||
lua_pushlstring(L, phys->attr->str, phys->attr->len); \
|
||||
return 1; \
|
||||
} \
|
||||
\
|
||||
static int lua_physical_attr_write_##attr(liPhysical *phys, lua_State *L) { \
|
||||
const char *s; size_t len; \
|
||||
luaL_checkstring(L, 3); \
|
||||
s = lua_tolstring(L, 3, &len); \
|
||||
g_string_truncate(phys->attr, 0); \
|
||||
g_string_append_len(phys->attr, s, len); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
DEF_LUA_MODIFY_GSTRING(path)
|
||||
DEF_LUA_MODIFY_GSTRING(doc_root)
|
||||
DEF_LUA_MODIFY_GSTRING(pathinfo)
|
||||
|
||||
#undef DEF_LUA_MODIFY_GSTRING
|
||||
|
||||
#define AR(m) { #m, lua_physical_attr_read_##m, NULL }
|
||||
#define AW(m) { #m, NULL, lua_physical_attr_write_##m }
|
||||
#define ARW(m) { #m, lua_physical_attr_read_##m, lua_physical_attr_write_##m }
|
||||
|
||||
static const struct {
|
||||
const char* key;
|
||||
lua_Physical_Attrib read_attr, write_attr;
|
||||
} physical_attribs[] = {
|
||||
ARW(path),
|
||||
ARW(doc_root),
|
||||
ARW(pathinfo),
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
#undef AR
|
||||
#undef AW
|
||||
#undef ARW
|
||||
|
||||
|
||||
static int lua_physical_index(lua_State *L) {
|
||||
liPhysical *phys;
|
||||
const char *key;
|
||||
int i;
|
||||
|
||||
if (lua_gettop(L) != 2) {
|
||||
lua_pushstring(L, "incorrect number of arguments");
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
if (li_lua_metatable_index(L)) return 1;
|
||||
|
||||
phys = lua_get_physical(L, 1);
|
||||
if (!phys) return 0;
|
||||
|
||||
if (lua_isnumber(L, 2)) return 0;
|
||||
if (!lua_isstring(L, 2)) return 0;
|
||||
|
||||
key = lua_tostring(L, 2);
|
||||
for (i = 0; physical_attribs[i].key ; i++) {
|
||||
if (0 == strcmp(key, physical_attribs[i].key)) {
|
||||
if (physical_attribs[i].read_attr)
|
||||
return physical_attribs[i].read_attr(phys, L);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lua_pushstring(L, "cannot read attribute ");
|
||||
lua_pushstring(L, key);
|
||||
lua_pushstring(L, " in physical");
|
||||
lua_concat(L, 3);
|
||||
lua_error(L);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_physical_newindex(lua_State *L) {
|
||||
liPhysical *phys;
|
||||
const char *key;
|
||||
int i;
|
||||
|
||||
if (lua_gettop(L) != 3) {
|
||||
lua_pushstring(L, "incorrect number of arguments");
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
phys = lua_get_physical(L, 1);
|
||||
if (!phys) return 0;
|
||||
|
||||
if (lua_isnumber(L, 2)) return 0;
|
||||
if (!lua_isstring(L, 2)) return 0;
|
||||
|
||||
key = lua_tostring(L, 2);
|
||||
for (i = 0; physical_attribs[i].key ; i++) {
|
||||
if (0 == strcmp(key, physical_attribs[i].key)) {
|
||||
if (physical_attribs[i].write_attr)
|
||||
return physical_attribs[i].write_attr(phys, L);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lua_pushstring(L, "cannot write attribute ");
|
||||
lua_pushstring(L, key);
|
||||
lua_pushstring(L, "in physical");
|
||||
lua_concat(L, 3);
|
||||
lua_error(L);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg physical_mt[] = {
|
||||
{ "__index", lua_physical_index },
|
||||
{ "__newindex", lua_physical_newindex },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static void init_physical_mt(lua_State *L) {
|
||||
luaL_register(L, NULL, physical_mt);
|
||||
}
|
||||
|
||||
void lua_init_physical_mt(lua_State *L) {
|
||||
if (luaL_newmetatable(L, LUA_PHYSICAL)) {
|
||||
init_physical_mt(L);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
liPhysical* lua_get_physical(lua_State *L, int ndx) {
|
||||
if (!lua_isuserdata(L, ndx)) return NULL;
|
||||
if (!lua_getmetatable(L, ndx)) return NULL;
|
||||
luaL_getmetatable(L, LUA_PHYSICAL);
|
||||
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 *(liPhysical**) lua_touserdata(L, ndx);
|
||||
}
|
||||
|
||||
int lua_push_physical(lua_State *L, liPhysical *phys) {
|
||||
liPhysical **pphys;
|
||||
|
||||
pphys = (liPhysical**) lua_newuserdata(L, sizeof(liPhysical*));
|
||||
*pphys = phys;
|
||||
|
||||
if (luaL_newmetatable(L, LUA_PHYSICAL)) {
|
||||
init_physical_mt(L);
|
||||
}
|
||||
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
@ -0,0 +1,348 @@
|
||||
|
||||
#include <lighttpd/core_lua.h>
|
||||
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#define LUA_REQUEST "liRequest*"
|
||||
#define LUA_REQUESTURI "liRequestUri*"
|
||||
|
||||
typedef int (*lua_Request_Attrib)(liRequest *req, lua_State *L);
|
||||
|
||||
static int lua_request_attr_read_headers(liRequest *req, lua_State *L) {
|
||||
lua_push_http_headers(L, req->headers);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_request_attr_read_http_method(liRequest *req, lua_State *L) {
|
||||
lua_pushlstring(L, req->http_method_str->str, req->http_method_str->len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_request_attr_read_http_version(liRequest *req, lua_State *L) {
|
||||
switch (req->http_version) {
|
||||
case LI_HTTP_VERSION_1_0:
|
||||
lua_pushliteral(L, "HTTP/1.0");
|
||||
break;
|
||||
case LI_HTTP_VERSION_1_1:
|
||||
lua_pushliteral(L, "HTTP/1.1");
|
||||
break;
|
||||
case LI_HTTP_VERSION_UNSET:
|
||||
default:
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_request_attr_read_content_length(liRequest *req, lua_State *L) {
|
||||
lua_pushinteger(L, req->content_length);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_request_attr_read_uri(liRequest *req, lua_State *L) {
|
||||
lua_push_requesturi(L, &req->uri);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define AR(m) { #m, lua_request_attr_read_##m, NULL }
|
||||
#define AW(m) { #m, NULL, lua_request_attr_write_##m }
|
||||
#define ARW(m) { #m, lua_request_attr_read_##m, lua_request_attr_write_##m }
|
||||
|
||||
static const struct {
|
||||
const char* key;
|
||||
lua_Request_Attrib read_attr, write_attr;
|
||||
} request_attribs[] = {
|
||||
AR(headers),
|
||||
AR(http_method),
|
||||
AR(http_version),
|
||||
AR(content_length),
|
||||
AR(uri),
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
#undef AR
|
||||
#undef AW
|
||||
#undef ARW
|
||||
|
||||
|
||||
static int lua_request_index(lua_State *L) {
|
||||
liRequest *req;
|
||||
const char *key;
|
||||
int i;
|
||||
|
||||
if (lua_gettop(L) != 2) {
|
||||
lua_pushstring(L, "incorrect number of arguments");
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
if (li_lua_metatable_index(L)) return 1;
|
||||
|
||||
req = lua_get_request(L, 1);
|
||||
if (!req) return 0;
|
||||
|
||||
if (lua_isnumber(L, 2)) return 0;
|
||||
if (!lua_isstring(L, 2)) return 0;
|
||||
|
||||
key = lua_tostring(L, 2);
|
||||
for (i = 0; request_attribs[i].key ; i++) {
|
||||
if (0 == strcmp(key, request_attribs[i].key)) {
|
||||
if (request_attribs[i].read_attr)
|
||||
return request_attribs[i].read_attr(req, L);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lua_pushstring(L, "cannot read attribute ");
|
||||
lua_pushstring(L, key);
|
||||
lua_pushstring(L, " in request");
|
||||
lua_concat(L, 3);
|
||||
lua_error(L);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_request_newindex(lua_State *L) {
|
||||
liRequest *req;
|
||||
const char *key;
|
||||
int i;
|
||||
|
||||
if (lua_gettop(L) != 3) {
|
||||
lua_pushstring(L, "incorrect number of arguments");
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
req = lua_get_request(L, 1);
|
||||
if (!req) return 0;
|
||||
|
||||
if (lua_isnumber(L, 2)) return 0;
|
||||
if (!lua_isstring(L, 2)) return 0;
|
||||
|
||||
key = lua_tostring(L, 2);
|
||||
for (i = 0; request_attribs[i].key ; i++) {
|
||||
if (0 == strcmp(key, request_attribs[i].key)) {
|
||||
if (request_attribs[i].write_attr)
|
||||
return request_attribs[i].write_attr(req, L);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lua_pushstring(L, "cannot write attribute ");
|
||||
lua_pushstring(L, key);
|
||||
lua_pushstring(L, "in request");
|
||||
lua_concat(L, 3);
|
||||
lua_error(L);
|
||||