You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lighttpd2/src/main/http_headers_lua.c

245 lines
5.6 KiB
C

#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 = li_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 = li_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 = li_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 = li_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 = li_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 = li_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 = li_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;
}
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 li_lua_init_http_headers_mt(lua_State *L) {
if (luaL_newmetatable(L, LUA_HTTPHEADERS)) {
init_http_headers_mt(L);
}
lua_pop(L, 1);
}
liHttpHeaders* li_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 li_lua_push_http_headers(lua_State *L, liHttpHeaders *headers) {
liHttpHeaders **pheaders;
if (NULL == headers) {
lua_pushnil(L);
return 1;
}
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;
}