summaryrefslogtreecommitdiff
path: root/src/mod_magnet.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_magnet.c')
-rw-r--r--src/mod_magnet.c244
1 files changed, 174 insertions, 70 deletions
diff --git a/src/mod_magnet.c b/src/mod_magnet.c
index d2fe7c7..4fd0795 100644
--- a/src/mod_magnet.c
+++ b/src/mod_magnet.c
@@ -14,6 +14,7 @@
#include "response.h"
#include "stat_cache.h"
#include "status_counter.h"
+#include "etag.h"
#ifdef HAVE_LUA_H
#include <lua.h>
@@ -34,36 +35,36 @@ typedef struct {
typedef struct {
PLUGIN_DATA;
-
+
script_cache *cache;
buffer *encode_buf;
-
+
plugin_config **config_storage;
-
- plugin_config conf;
+
+ plugin_config conf;
} plugin_data;
/* init the plugin data */
INIT_FUNC(mod_magnet_init) {
plugin_data *p;
-
+
p = calloc(1, sizeof(*p));
-
+
p->cache = script_cache_init();
p->encode_buf = buffer_init();
-
+
return p;
}
/* detroy the plugin data */
FREE_FUNC(mod_magnet_free) {
plugin_data *p = p_d;
-
+
UNUSED(srv);
if (!p) return HANDLER_GO_ON;
-
+
if (p->config_storage) {
size_t i;
@@ -71,20 +72,20 @@ FREE_FUNC(mod_magnet_free) {
plugin_config *s = p->config_storage[i];
if (!s) continue;
-
+
array_free(s->url_raw);
array_free(s->physical_path);
-
+
free(s);
}
free(p->config_storage);
}
-
+
script_cache_free(p->cache);
buffer_free(p->encode_buf);
-
+
free(p);
-
+
return HANDLER_GO_ON;
}
@@ -93,34 +94,34 @@ FREE_FUNC(mod_magnet_free) {
SETDEFAULTS_FUNC(mod_magnet_set_defaults) {
plugin_data *p = p_d;
size_t i = 0;
-
- config_values_t cv[] = {
+
+ config_values_t cv[] = {
{ MAGNET_CONFIG_RAW_URL, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
{ MAGNET_CONFIG_PHYSICAL_PATH, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
};
-
+
if (!p) return HANDLER_ERROR;
-
+
p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
-
+
for (i = 0; i < srv->config_context->used; i++) {
plugin_config *s;
-
+
s = calloc(1, sizeof(plugin_config));
s->url_raw = array_init();
s->physical_path = array_init();
-
+
cv[0].destination = s->url_raw;
cv[1].destination = s->physical_path;
-
+
p->config_storage[i] = s;
-
+
if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
return HANDLER_ERROR;
}
}
-
+
return HANDLER_GO_ON;
}
@@ -129,22 +130,22 @@ SETDEFAULTS_FUNC(mod_magnet_set_defaults) {
static int mod_magnet_patch_connection(server *srv, connection *con, plugin_data *p) {
size_t i, j;
plugin_config *s = p->config_storage[0];
-
+
PATCH(url_raw);
PATCH(physical_path);
-
+
/* skip the first, the global context */
for (i = 1; i < srv->config_context->used; i++) {
data_config *dc = (data_config *)srv->config_context->data[i];
s = p->config_storage[i];
-
+
/* condition didn't match */
if (!config_check_cond(srv, con, dc)) continue;
-
+
/* merge config */
for (j = 0; j < dc->value->used; j++) {
data_unset *du = dc->value->data[j];
-
+
if (buffer_is_equal_string(du->key, CONST_STR_LEN(MAGNET_CONFIG_RAW_URL))) {
PATCH(url_raw);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN(MAGNET_CONFIG_PHYSICAL_PATH))) {
@@ -152,7 +153,7 @@ static int mod_magnet_patch_connection(server *srv, connection *con, plugin_data
}
}
}
-
+
return 0;
}
#undef PATCH
@@ -166,12 +167,106 @@ static int magnet_print(lua_State *L) {
srv = lua_touserdata(L, -1);
lua_pop(L, 1);
- log_error_write(srv, __FILE__, __LINE__, "ss",
+ log_error_write(srv, __FILE__, __LINE__, "ss",
"(lua-print)", s);
return 0;
}
+static int magnet_stat(lua_State *L) {
+ const char *s = luaL_checkstring(L, 1);
+ server *srv;
+ connection *con;
+ buffer sb;
+ stat_cache_entry *sce = NULL;
+
+ 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);
+
+ sb.ptr = (char *)s;
+ sb.used = sb.size = strlen(s) + 1;
+
+ if (HANDLER_GO_ON != stat_cache_get_entry(srv, con, &sb, &sce)) {
+ lua_pushnil(L);
+
+ return 1;
+ }
+
+ lua_newtable(L);
+
+ lua_pushboolean(L, S_ISREG(sce->st.st_mode));
+ lua_setfield(L, -2, "is_file");
+
+ lua_pushboolean(L, S_ISDIR(sce->st.st_mode));
+ lua_setfield(L, -2, "is_dir");
+
+ lua_pushboolean(L, S_ISCHR(sce->st.st_mode));
+ lua_setfield(L, -2, "is_char");
+
+ lua_pushboolean(L, S_ISBLK(sce->st.st_mode));
+ lua_setfield(L, -2, "is_block");
+
+ lua_pushboolean(L, S_ISSOCK(sce->st.st_mode));
+ lua_setfield(L, -2, "is_socket");
+
+ lua_pushboolean(L, S_ISLNK(sce->st.st_mode));
+ lua_setfield(L, -2, "is_link");
+
+ lua_pushboolean(L, S_ISFIFO(sce->st.st_mode));
+ lua_setfield(L, -2, "is_fifo");
+
+ lua_pushinteger(L, sce->st.st_mtime);
+ lua_setfield(L, -2, "st_mtime");
+
+ lua_pushinteger(L, sce->st.st_ctime);
+ lua_setfield(L, -2, "st_ctime");
+
+ lua_pushinteger(L, sce->st.st_atime);
+ lua_setfield(L, -2, "st_atime");
+
+ lua_pushinteger(L, sce->st.st_uid);
+ lua_setfield(L, -2, "st_uid");
+
+ lua_pushinteger(L, sce->st.st_gid);
+ lua_setfield(L, -2, "st_gid");
+
+ lua_pushinteger(L, sce->st.st_size);
+ lua_setfield(L, -2, "st_size");
+
+ lua_pushinteger(L, sce->st.st_ino);
+ lua_setfield(L, -2, "st_ino");
+
+
+ if (!buffer_is_empty(sce->etag)) {
+ /* we have to mutate the etag */
+ buffer *b = buffer_init();
+ etag_mutate(b, sce->etag);
+
+ lua_pushlstring(L, b->ptr, b->used - 1);
+ buffer_free(b);
+ } else {
+ lua_pushnil(L);
+ }
+ lua_setfield(L, -2, "etag");
+
+ if (!buffer_is_empty(sce->content_type)) {
+ lua_pushlstring(L, sce->content_type->ptr, sce->content_type->used - 1);
+ } else {
+ lua_pushnil(L);
+ }
+ lua_setfield(L, -2, "content-type");
+
+ return 1;
+}
+
+
static int magnet_atpanic(lua_State *L) {
const char *s = luaL_checkstring(L, 1);
server *srv;
@@ -181,9 +276,9 @@ static int magnet_atpanic(lua_State *L) {
srv = lua_touserdata(L, -1);
lua_pop(L, 1);
- log_error_write(srv, __FILE__, __LINE__, "ss",
+ log_error_write(srv, __FILE__, __LINE__, "ss",
"(lua-atpanic)", s);
-
+
longjmp(exceptionjmp, 1);
}
@@ -254,7 +349,7 @@ static int magnet_status_set(lua_State *L) {
typedef struct {
const char *name;
- enum {
+ enum {
MAGNET_ENV_UNSET,
MAGNET_ENV_PHYICAL_PATH,
@@ -269,6 +364,7 @@ typedef struct {
MAGNET_ENV_REQUEST_METHOD,
MAGNET_ENV_REQUEST_URI,
+ MAGNET_ENV_REQUEST_ORIG_URI,
MAGNET_ENV_REQUEST_PROTOCOL
} type;
} magnet_env_t;
@@ -290,14 +386,16 @@ static buffer *magnet_env_get_buffer(server *srv, connection *con, const char *k
{ "request.method", MAGNET_ENV_REQUEST_METHOD },
{ "request.uri", MAGNET_ENV_REQUEST_URI },
+ { "request.orig-uri", MAGNET_ENV_REQUEST_ORIG_URI },
{ "request.protocol", MAGNET_ENV_REQUEST_PROTOCOL },
-
+
{ NULL, MAGNET_ENV_UNSET }
};
+ UNUSED(srv);
/**
- * map all internal variables to lua
+ * map all internal variables to lua
*
*/
@@ -318,6 +416,7 @@ static buffer *magnet_env_get_buffer(server *srv, connection *con, const char *k
case MAGNET_ENV_REQUEST_METHOD: break;
case MAGNET_ENV_REQUEST_URI: dest = con->request.uri; break;
+ case MAGNET_ENV_REQUEST_ORIG_URI: dest = con->request.orig_uri; break;
case MAGNET_ENV_REQUEST_PROTOCOL: break;
case MAGNET_ENV_UNSET: break;
@@ -385,6 +484,7 @@ static int magnet_env_set(lua_State *L) {
static int magnet_copy_response_header(server *srv, connection *con, plugin_data *p, lua_State *L) {
+ UNUSED(p);
/**
* get the environment of the function
*/
@@ -414,7 +514,7 @@ static int magnet_copy_response_header(server *srv, connection *con, plugin_data
lua_pop(L, 1);
}
- }
+ }
lua_pop(L, 1); /* pop the header-table */
lua_pop(L, 1); /* pop the lighty-env */
@@ -424,15 +524,16 @@ static int magnet_copy_response_header(server *srv, connection *con, plugin_data
}
/**
- * walk through the content array
+ * walk through the content array
*
- * content = { "<pre>", { file = "/content" } , "</pre>" }
+ * content = { "<pre>", { file = "/content" } , "</pre>" }
*
* header["Content-Type"] = "text/html"
- *
+ *
* return 200
*/
static int magnet_attach_content(server *srv, connection *con, plugin_data *p, lua_State *L) {
+ UNUSED(p);
/**
* get the environment of the function
*/
@@ -489,7 +590,7 @@ static int magnet_attach_content(server *srv, connection *con, plugin_data *p, l
if (len < off) {
return luaL_error(L, "offset > length for '%s'", fn->ptr);
}
-
+
chunkqueue_append_file(con->write_queue, fn, off, len - off);
}
@@ -534,7 +635,7 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu
L = script_cache_get_script(srv, con, p->cache, name);
if (lua_isstring(L, -1)) {
- log_error_write(srv, __FILE__, __LINE__,
+ log_error_write(srv, __FILE__, __LINE__,
"sbss",
"loading script",
name,
@@ -542,7 +643,7 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu
lua_tostring(L, -1));
lua_pop(L, 1);
-
+
assert(lua_gettop(L) == 0); /* only the function should be on the stack */
con->http_status = 500;
@@ -550,25 +651,25 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu
return HANDLER_FINISHED;
}
- lua_pushstring(L, "lighty.srv");
+ lua_pushstring(L, "lighty.srv");
lua_pushlightuserdata(L, srv);
lua_settable(L, LUA_REGISTRYINDEX); /* registery[<id>] = srv */
- lua_pushstring(L, "lighty.con");
+ lua_pushstring(L, "lighty.con");
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
- *
+ * we want to create empty environment for our script
+ *
* setmetatable({}, {__index = _G})
- *
- * if a function, symbol is not defined in our env, __index will lookup
+ *
+ * if a function, symbol is not defined in our env, __index will lookup
* in the global env.
*
- * all variables created in the script-env will be thrown
+ * all variables created in the script-env will be thrown
* away at the end of the script run.
*/
lua_newtable(L); /* my empty environment aka {} (sp += 1) */
@@ -578,8 +679,8 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu
lua_setfield(L, -2, "print"); /* -1 is the env we want to set(sp -= 1) */
/**
- * lighty.request[] has the HTTP-request headers
- * lighty.content[] is a table of string/file
+ * lighty.request[] has the HTTP-request headers
+ * lighty.content[] is a table of string/file
* lighty.header[] is a array to set response headers
*/
@@ -588,25 +689,25 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu
lua_newtable(L); /* {} (sp += 1) */
lua_newtable(L); /* the meta-table for the request-table (sp += 1) */
lua_pushcfunction(L, magnet_reqhdr_get); /* (sp += 1) */
- lua_setfield(L, -2, "__index"); /* (sp -= 1) */
+ lua_setfield(L, -2, "__index"); /* (sp -= 1) */
lua_setmetatable(L, -2); /* tie the metatable to request (sp -= 1) */
lua_setfield(L, -2, "request"); /* content = {} (sp -= 1) */
lua_newtable(L); /* {} (sp += 1) */
lua_newtable(L); /* the meta-table for the request-table (sp += 1) */
lua_pushcfunction(L, magnet_env_get); /* (sp += 1) */
- lua_setfield(L, -2, "__index"); /* (sp -= 1) */
+ lua_setfield(L, -2, "__index"); /* (sp -= 1) */
lua_pushcfunction(L, magnet_env_set); /* (sp += 1) */
- lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */
+ lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */
lua_setmetatable(L, -2); /* tie the metatable to request (sp -= 1) */
lua_setfield(L, -2, "env"); /* content = {} (sp -= 1) */
lua_newtable(L); /* {} (sp += 1) */
lua_newtable(L); /* the meta-table for the request-table (sp += 1) */
lua_pushcfunction(L, magnet_status_get); /* (sp += 1) */
- lua_setfield(L, -2, "__index"); /* (sp -= 1) */
+ lua_setfield(L, -2, "__index"); /* (sp -= 1) */
lua_pushcfunction(L, magnet_status_set); /* (sp += 1) */
- lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */
+ lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */
lua_setmetatable(L, -2); /* tie the metatable to request (sp -= 1) */
lua_setfield(L, -2, "status"); /* content = {} (sp -= 1) */
@@ -620,19 +721,22 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu
lua_pushinteger(L, MAGNET_RESTART_REQUEST);
lua_setfield(L, -2, "RESTART_REQUEST");
+ lua_pushcfunction(L, magnet_stat); /* (sp += 1) */
+ lua_setfield(L, -2, "stat"); /* -1 is the env we want to set (sp -= 1) */
+
lua_setfield(L, -2, "lighty"); /* lighty.* (sp -= 1) */
-
+
lua_newtable(L); /* the meta-table for the new env (sp += 1) */
lua_pushvalue(L, LUA_GLOBALSINDEX); /* (sp += 1) */
lua_setfield(L, -2, "__index"); /* { __index = _G } (sp -= 1) */
lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) (sp -= 1) */
-
+
lua_setfenv(L, -2); /* on the stack should be a modified env (sp -= 1) */
if (lua_pcall(L, 0, 1, 0)) {
- log_error_write(srv, __FILE__, __LINE__,
- "ss",
+ log_error_write(srv, __FILE__, __LINE__,
+ "ss",
"lua_pcall():",
lua_tostring(L, -1));
lua_pop(L, 1); /* remove the error-msg and the function copy from the stack */
@@ -658,7 +762,7 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu
if (lua_return_value > 99) {
con->http_status = lua_return_value;
con->file_finished = 1;
-
+
/* try { ...*/
if (0 == setjmp(exceptionjmp)) {
magnet_attach_content(srv, con, p, L);
@@ -666,7 +770,7 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu
/* } catch () { */
con->http_status = 500;
}
-
+
assert(lua_gettop(L) == 1); /* only the function should be on the stack */
/* we are finished */
@@ -677,7 +781,7 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu
return HANDLER_COMEBACK;
} else {
assert(lua_gettop(L) == 1); /* only the function should be on the stack */
-
+
return HANDLER_GO_ON;
}
}
@@ -696,7 +800,7 @@ static handler_t magnet_attract_array(server *srv, connection *con, plugin_data
handler_t ret;
if (buffer_is_empty(ds->value)) continue;
-
+
ret = magnet_attract(srv, con, p, ds->value);
if (ret != HANDLER_GO_ON) return ret;
@@ -707,7 +811,7 @@ static handler_t magnet_attract_array(server *srv, connection *con, plugin_data
URIHANDLER_FUNC(mod_magnet_uri_handler) {
plugin_data *p = p_d;
-
+
mod_magnet_patch_connection(srv, con, p);
return magnet_attract_array(srv, con, p, p->conf.url_raw);
@@ -715,7 +819,7 @@ URIHANDLER_FUNC(mod_magnet_uri_handler) {
URIHANDLER_FUNC(mod_magnet_physical) {
plugin_data *p = p_d;
-
+
mod_magnet_patch_connection(srv, con, p);
return magnet_attract_array(srv, con, p, p->conf.physical_path);
@@ -727,15 +831,15 @@ URIHANDLER_FUNC(mod_magnet_physical) {
int mod_magnet_plugin_init(plugin *p) {
p->version = LIGHTTPD_VERSION_ID;
p->name = buffer_init_string("magnet");
-
+
p->init = mod_magnet_init;
p->handle_uri_clean = mod_magnet_uri_handler;
p->handle_physical = mod_magnet_physical;
p->set_defaults = mod_magnet_set_defaults;
p->cleanup = mod_magnet_free;
-
+
p->data = NULL;
-
+
return 0;
}