|
|
|
@ -2,6 +2,7 @@
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <setjmp.h>
|
|
|
|
|
|
|
|
|
|
#include "base.h"
|
|
|
|
|
#include "log.h"
|
|
|
|
@ -24,6 +25,8 @@
|
|
|
|
|
|
|
|
|
|
/* plugin config for all request/connections */
|
|
|
|
|
|
|
|
|
|
static jmp_buf exceptionjmp;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
buffer *url_raw;
|
|
|
|
|
buffer *physical_path;
|
|
|
|
@ -169,6 +172,21 @@ static int magnet_print(lua_State *L) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int magnet_atpanic(lua_State *L) {
|
|
|
|
|
const char *s = luaL_checkstring(L, 1);
|
|
|
|
|
server *srv;
|
|
|
|
|
|
|
|
|
|
lua_pushstring(L, "lighty.srv");
|
|
|
|
|
lua_gettable(L, LUA_REGISTRYINDEX);
|
|
|
|
|
srv = lua_touserdata(L, -1);
|
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ss",
|
|
|
|
|
"(lua-atpanic)", s);
|
|
|
|
|
|
|
|
|
|
longjmp(exceptionjmp, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int magnet_reqhdr_get(lua_State *L) {
|
|
|
|
|
server *srv;
|
|
|
|
|
connection *con;
|
|
|
|
@ -414,98 +432,95 @@ static int magnet_copy_response_header(server *srv, connection *con, plugin_data
|
|
|
|
|
*
|
|
|
|
|
* return 200
|
|
|
|
|
*/
|
|
|
|
|
static int magnet_attach_content(lua_State *L) {
|
|
|
|
|
static int magnet_attach_content(server *srv, connection *con, plugin_data *p, lua_State *L) {
|
|
|
|
|
/**
|
|
|
|
|
* get the environment of the function
|
|
|
|
|
*/
|
|
|
|
|
server *srv;
|
|
|
|
|
connection *con;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
lua_pushstring(L, "lighty.srv");
|
|
|
|
|
lua_gettable(L, LUA_REGISTRYINDEX);
|
|
|
|
|
srv = lua_touserdata(L, -1);
|
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
|
|
lua_pushstring(L, "lighty.con");
|
|
|
|
|
lua_gettable(L, LUA_REGISTRYINDEX);
|
|
|
|
|
con = lua_touserdata(L, -1);
|
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
|
|
assert(lua_isfunction(L, -1)); /* this would be error in lighty */
|
|
|
|
|
lua_getfenv(L, -1); /* get the script-env */
|
|
|
|
|
assert(lua_isfunction(L, -1));
|
|
|
|
|
lua_getfenv(L, -1); /* -1 is the function */
|
|
|
|
|
|
|
|
|
|
lua_getfield(L, -1, "lighty"); /* lighty.* from the env */
|
|
|
|
|
if (!lua_istable(L, -1)) {
|
|
|
|
|
return luaL_error(L, "lighty.* was a table and get overwritten in your script");
|
|
|
|
|
}
|
|
|
|
|
assert(lua_istable(L, -1));
|
|
|
|
|
|
|
|
|
|
lua_getfield(L, -1, "content"); /* lighty.content */
|
|
|
|
|
if (!lua_istable(L, -1)) {
|
|
|
|
|
return luaL_error(L, "lighty.content was a table and get overwritten in your script");
|
|
|
|
|
}
|
|
|
|
|
if (lua_istable(L, -1)) {
|
|
|
|
|
int i;
|
|
|
|
|
/* header is found, and is a table */
|
|
|
|
|
|
|
|
|
|
for (i = 1; ; i++) {
|
|
|
|
|
lua_rawgeti(L, -1, i);
|
|
|
|
|
for (i = 1; ; i++) {
|
|
|
|
|
lua_rawgeti(L, -1, i);
|
|
|
|
|
|
|
|
|
|
/* -1 is the value and should be the value ... aka a table */
|
|
|
|
|
if (lua_isstring(L, -1)) {
|
|
|
|
|
size_t s_len = 0;
|
|
|
|
|
const char *s = lua_tolstring(L, -1, &s_len);
|
|
|
|
|
/* -1 is the value and should be the value ... aka a table */
|
|
|
|
|
if (lua_isstring(L, -1)) {
|
|
|
|
|
size_t s_len = 0;
|
|
|
|
|
const char *s = lua_tolstring(L, -1, &s_len);
|
|
|
|
|
|
|
|
|
|
chunkqueue_append_mem(con->write_queue, s, s_len + 1);
|
|
|
|
|
} else if (lua_istable(L, -1)) {
|
|
|
|
|
stat_cache_entry *sce;
|
|
|
|
|
buffer *fn;
|
|
|
|
|
chunkqueue_append_mem(con->write_queue, s, s_len + 1);
|
|
|
|
|
} else if (lua_istable(L, -1)) {
|
|
|
|
|
lua_getfield(L, -1, "filename");
|
|
|
|
|
lua_getfield(L, -2, "length");
|
|
|
|
|
lua_getfield(L, -3, "offset");
|
|
|
|
|
|
|
|
|
|
lua_getfield(L, -1, "filename");
|
|
|
|
|
lua_getfield(L, -2, "length");
|
|
|
|
|
lua_getfield(L, -3, "offset");
|
|
|
|
|
if (lua_isstring(L, -3)) { /* filename has to be a string */
|
|
|
|
|
buffer *fn = buffer_init();
|
|
|
|
|
stat_cache_entry *sce;
|
|
|
|
|
|
|
|
|
|
if (!lua_isstring(L, -3)) { /* filename has to be a string */
|
|
|
|
|
return luaL_error(L, "lighty.content[%d] is a table and requires the field \"filename\"", i);
|
|
|
|
|
}
|
|
|
|
|
fn = buffer_init();
|
|
|
|
|
buffer_copy_string(fn, lua_tostring(L, -3));
|
|
|
|
|
|
|
|
|
|
buffer_copy_string(fn, lua_tostring(L, -3));
|
|
|
|
|
if (HANDLER_GO_ON == stat_cache_get_entry(srv, con, fn, &sce)) {
|
|
|
|
|
off_t off = 0;
|
|
|
|
|
off_t len = 0;
|
|
|
|
|
|
|
|
|
|
if (HANDLER_GO_ON == stat_cache_get_entry(srv, con, fn, &sce)) {
|
|
|
|
|
off_t off = 0;
|
|
|
|
|
off_t len = 0;
|
|
|
|
|
if (lua_isnumber(L, -1)) {
|
|
|
|
|
off = lua_tonumber(L, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lua_isnumber(L, -1)) {
|
|
|
|
|
off = lua_tonumber(L, -1);
|
|
|
|
|
}
|
|
|
|
|
if (lua_isnumber(L, -2)) {
|
|
|
|
|
len = lua_tonumber(L, -2);
|
|
|
|
|
} else {
|
|
|
|
|
len = sce->st.st_size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (off < 0) {
|
|
|
|
|
return luaL_error(L, "offset for '%s' is negative", fn->ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lua_isnumber(L, -2)) {
|
|
|
|
|
len = lua_tonumber(L, -2);
|
|
|
|
|
if (len < off) {
|
|
|
|
|
return luaL_error(L, "offset > length for '%s'", fn->ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
chunkqueue_append_file(con->write_queue, fn, off, len - off);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buffer_free(fn);
|
|
|
|
|
} else {
|
|
|
|
|
len = sce->st.st_size;
|
|
|
|
|
}
|
|
|
|
|
lua_pop(L, 3 + 2); /* correct the stack */
|
|
|
|
|
|
|
|
|
|
if (off < 0) {
|
|
|
|
|
/* fn leaks mem */
|
|
|
|
|
return luaL_error(L, "offset for '%s' is negative", fn->ptr);
|
|
|
|
|
return luaL_error(L, "content[%d] is a table and requires the field \"filename\"", i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (len < off) {
|
|
|
|
|
/* fn leaks mem */
|
|
|
|
|
return luaL_error(L, "offset > length for '%s'", fn->ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
chunkqueue_append_file(con->write_queue, fn, off, len - off);
|
|
|
|
|
}
|
|
|
|
|
lua_pop(L, 3);
|
|
|
|
|
} else if (lua_isnil(L, -1)) {
|
|
|
|
|
/* oops, end of list */
|
|
|
|
|
|
|
|
|
|
buffer_free(fn);
|
|
|
|
|
} else if (lua_isnil(L, -1)) {
|
|
|
|
|
/* oops, end of list */
|
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
return luaL_error(L, "lighty.content[%d] is neither a string nor a table: ", i);
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
lua_pop(L, 4);
|
|
|
|
|
|
|
|
|
|
return luaL_error(L, "content[%d] is neither a string nor a table: ", i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lua_pop(L, 1); /* pop the content[...] table */
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return luaL_error(L, "lighty.content has to be a table");
|
|
|
|
|
}
|
|
|
|
|
lua_pop(L, 1); /* pop the header-table */
|
|
|
|
|
lua_pop(L, 1); /* pop the lighty-table */
|
|
|
|
|
lua_pop(L, 1); /* php the function env */
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@ -543,6 +558,8 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu
|
|
|
|
|
lua_pushlightuserdata(L, con);
|
|
|
|
|
lua_settable(L, LUA_REGISTRYINDEX); /* registery[<id>] = con */
|
|
|
|
|
|
|
|
|
|
lua_atpanic(L, magnet_atpanic);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* we want to create empty environment for our script
|
|
|
|
|
*
|
|
|
|
@ -638,23 +655,18 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu
|
|
|
|
|
|
|
|
|
|
magnet_copy_response_header(srv, con, p, L);
|
|
|
|
|
|
|
|
|
|
/* everything 3-digit number is a status-code */
|
|
|
|
|
if (lua_return_value > 99 && lua_return_value < 1000) {
|
|
|
|
|
if (lua_return_value > 99) {
|
|
|
|
|
con->http_status = lua_return_value;
|
|
|
|
|
con->file_finished = 1;
|
|
|
|
|
|
|
|
|
|
/* use the lua-system to call a lua-c-function
|
|
|
|
|
* that way I can use luaL_error() without problems
|
|
|
|
|
*/
|
|
|
|
|
if (lua_cpcall(L, magnet_attach_content, NULL)) {
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__,
|
|
|
|
|
"ss",
|
|
|
|
|
"magnet_attach_content():",
|
|
|
|
|
lua_tostring(L, -1));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* try { ...*/
|
|
|
|
|
if (0 == setjmp(exceptionjmp)) {
|
|
|
|
|
magnet_attach_content(srv, con, p, L);
|
|
|
|
|
} else {
|
|
|
|
|
/* } catch () { */
|
|
|
|
|
con->http_status = 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(lua_gettop(L) == 1); /* only the function should be on the stack */
|
|
|
|
|
|
|
|
|
|
/* we are finished */
|
|
|
|
|