From 915a9e3e8805d59619782394d8bacd0d13bc893a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Mon, 12 Oct 2009 19:49:43 +0000 Subject: [PATCH] Add some iterators for mod_magnet (fixes #1307) git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2644 152afb58-edef-0310-8abb-c4023f1b3aa9 --- NEWS | 1 + src/mod_magnet.c | 227 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 199 insertions(+), 29 deletions(-) diff --git a/NEWS b/NEWS index 970c46df..685db21c 100644 --- a/NEWS +++ b/NEWS @@ -51,6 +51,7 @@ NEWS * mod_usertrack: Use T_CONFIG_INT for max-age, solves range problem (#1455) * mod_accesslog: configurable timestamp logging (fixes #1479) * always define _GNU_SOURCE + * Add some iterators for mod_magnet (fixes #1307) - 1.4.23 - 2009-06-19 * Added some extra warning options in cmake and fix the resulting warnings (unused/static functions) diff --git a/src/mod_magnet.c b/src/mod_magnet.c index 81cda8d7..0f4aefdd 100644 --- a/src/mod_magnet.c +++ b/src/mod_magnet.c @@ -158,6 +158,80 @@ static int mod_magnet_patch_connection(server *srv, connection *con, plugin_data } #undef PATCH +/* See http://lua-users.org/wiki/GeneralizedPairsAndIpairs for implementation details. */ + +/* Override the default pairs() function to allow us to use a __pairs metakey */ +static int magnet_pairs(lua_State *L) { + luaL_checkany(L, 1); + + if (luaL_getmetafield(L, 1, "__pairs")) { + lua_insert(L, 1); + lua_call(L, lua_gettop(L) - 1, LUA_MULTRET); + return lua_gettop(L); + } else { + lua_pushvalue(L, lua_upvalueindex(1)); + lua_call(L, lua_gettop(L) - 1, LUA_MULTRET); + return lua_gettop(L); + } +} + +/* Define a function that will iterate over an array* (in upval 1) using current position (upval 2) */ +static int magnet_array_next(lua_State *L) { + data_unset *du; + data_string *ds; + data_integer *di; + + size_t pos = lua_tointeger(L, lua_upvalueindex(1)); + array *a = lua_touserdata(L, lua_upvalueindex(2)); + + lua_settop(L, 0); + + if (pos >= a->used) return 0; + if (NULL != (du = a->data[pos])) { + if (du->key->used) { + lua_pushlstring(L, du->key->ptr, du->key->used - 1); + } + else { + lua_pushlstring(L, "", 0); + } + switch (du->type) { + case TYPE_STRING: + ds = (data_string *)du; + if (ds->value && ds->value->used) { + lua_pushlstring(L, ds->value->ptr, ds->value->used - 1); + } else { + lua_pushnil(L); + } + break; + case TYPE_COUNT: + case TYPE_INTEGER: + di = (data_integer *)du; + lua_pushinteger(L, di->value); + break; + default: + lua_pushnil(L); + break; + } + + /* Update our positional upval to reflect our new current position */ + pos++; + lua_pushinteger(L, pos); + lua_replace(L, lua_upvalueindex(1)); + + /* Returning 2 items on the stack (key, value) */ + return 2; + } + return 0; +} + +/* Create the closure necessary to iterate over the array *a with the above function */ +static int magnet_array_pairs(lua_State *L, array *a) { + lua_pushinteger(L, 0); /* Push our current pos (the start) into upval 1 */ + lua_pushlightuserdata(L, a); /* Push our array *a into upval 2 */ + lua_pushcclosure(L, magnet_array_next, 2); /* Push our new closure with 2 upvals */ + return 1; +} + static int magnet_print(lua_State *L) { const char *s = luaL_checkstring(L, 1); server *srv; @@ -305,6 +379,17 @@ static int magnet_reqhdr_get(lua_State *L) { return 1; } +static int magnet_reqhdr_pairs(lua_State *L) { + connection *con; + + lua_pushstring(L, "lighty.con"); + lua_gettable(L, LUA_REGISTRYINDEX); + con = lua_touserdata(L, -1); + lua_pop(L, 1); + + return magnet_array_pairs(L, con->request.headers); +} + static int magnet_status_get(lua_State *L) { data_integer *di; server *srv; @@ -341,6 +426,17 @@ static int magnet_status_set(lua_State *L) { return 0; } +static int magnet_status_pairs(lua_State *L) { + server *srv; + + lua_pushstring(L, "lighty.srv"); + lua_gettable(L, LUA_REGISTRYINDEX); + srv = lua_touserdata(L, -1); + lua_pop(L, 1); + + return magnet_array_pairs(L, srv->status); +} + typedef struct { const char *name; enum { @@ -362,33 +458,32 @@ typedef struct { MAGNET_ENV_REQUEST_PATH_INFO, MAGNET_ENV_REQUEST_REMOTE_IP, MAGNET_ENV_REQUEST_PROTOCOL - } type; + } type; } magnet_env_t; -static buffer *magnet_env_get_buffer(server *srv, connection *con, const char *key) { - buffer *dest = NULL; - size_t i; +static const magnet_env_t magnet_env[] = { + { "physical.path", MAGNET_ENV_PHYICAL_PATH }, + { "physical.rel-path", MAGNET_ENV_PHYICAL_REL_PATH }, + { "physical.doc-root", MAGNET_ENV_PHYICAL_DOC_ROOT }, - const magnet_env_t env[] = { - { "physical.path", MAGNET_ENV_PHYICAL_PATH }, - { "physical.rel-path", MAGNET_ENV_PHYICAL_REL_PATH }, - { "physical.doc-root", MAGNET_ENV_PHYICAL_DOC_ROOT }, - - { "uri.path", MAGNET_ENV_URI_PATH }, - { "uri.path-raw", MAGNET_ENV_URI_PATH_RAW }, - { "uri.scheme", MAGNET_ENV_URI_SCHEME }, - { "uri.authority", MAGNET_ENV_URI_AUTHORITY }, - { "uri.query", MAGNET_ENV_URI_QUERY }, - - { "request.method", MAGNET_ENV_REQUEST_METHOD }, - { "request.uri", MAGNET_ENV_REQUEST_URI }, - { "request.orig-uri", MAGNET_ENV_REQUEST_ORIG_URI }, - { "request.path-info", MAGNET_ENV_REQUEST_PATH_INFO }, - { "request.remote-ip", MAGNET_ENV_REQUEST_REMOTE_IP }, - { "request.protocol", MAGNET_ENV_REQUEST_PROTOCOL }, - - { NULL, MAGNET_ENV_UNSET } - }; + { "uri.path", MAGNET_ENV_URI_PATH }, + { "uri.path-raw", MAGNET_ENV_URI_PATH_RAW }, + { "uri.scheme", MAGNET_ENV_URI_SCHEME }, + { "uri.authority", MAGNET_ENV_URI_AUTHORITY }, + { "uri.query", MAGNET_ENV_URI_QUERY }, + + { "request.method", MAGNET_ENV_REQUEST_METHOD }, + { "request.uri", MAGNET_ENV_REQUEST_URI }, + { "request.orig-uri", MAGNET_ENV_REQUEST_ORIG_URI }, + { "request.path-info", MAGNET_ENV_REQUEST_PATH_INFO }, + { "request.remote-ip", MAGNET_ENV_REQUEST_REMOTE_IP }, + { "request.protocol", MAGNET_ENV_REQUEST_PROTOCOL }, + + { NULL, MAGNET_ENV_UNSET } +}; + +static buffer *magnet_env_get_buffer_by_id(server *srv, connection *con, int id) { + buffer *dest = NULL; UNUSED(srv); @@ -397,11 +492,7 @@ static buffer *magnet_env_get_buffer(server *srv, connection *con, const char *k * */ - for (i = 0; env[i].name; i++) { - if (0 == strcmp(key, env[i].name)) break; - } - - switch (env[i].type) { + switch (id) { case MAGNET_ENV_PHYICAL_PATH: dest = con->physical.path; break; case MAGNET_ENV_PHYICAL_REL_PATH: dest = con->physical.rel_path; break; case MAGNET_ENV_PHYICAL_DOC_ROOT: dest = con->physical.doc_root; break; @@ -431,6 +522,16 @@ static buffer *magnet_env_get_buffer(server *srv, connection *con, const char *k return dest; } +static buffer *magnet_env_get_buffer(server *srv, connection *con, const char *key) { + size_t i; + + for (i = 0; magnet_env[i].name; i++) { + if (0 == strcmp(key, magnet_env[i].name)) break; + } + + return magnet_env_get_buffer_by_id(srv, con, magnet_env[i].type); +} + static int magnet_env_get(lua_State *L) { server *srv; connection *con; @@ -488,6 +589,50 @@ static int magnet_env_set(lua_State *L) { return 0; } +static int magnet_env_next(lua_State *L) { + server *srv; + connection *con; + int pos = lua_tointeger(L, lua_upvalueindex(1)); + + buffer *dest; + + 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); + + lua_settop(L, 0); + + if (NULL == magnet_env[pos].name) return 0; /* end of list */ + + lua_pushstring(L, magnet_env[pos].name); + + dest = magnet_env_get_buffer_by_id(srv, con, magnet_env[pos].type); + if (dest && dest->used) { + lua_pushlstring(L, dest->ptr, dest->used - 1); + } else { + lua_pushnil(L); + } + + /* Update our positional upval to reflect our new current position */ + pos++; + lua_pushinteger(L, pos); + lua_replace(L, lua_upvalueindex(1)); + + /* Returning 2 items on the stack (key, value) */ + return 2; +} + +static int magnet_env_pairs(lua_State *L) { + lua_pushinteger(L, 0); /* Push our current pos (the start) into upval 1 */ + lua_pushcclosure(L, magnet_env_next, 1); /* Push our new closure with 1 upvals */ + return 1; +} static int magnet_cgi_get(lua_State *L) { connection *con; @@ -524,6 +669,17 @@ static int magnet_cgi_set(lua_State *L) { return 0; } +static int magnet_cgi_pairs(lua_State *L) { + connection *con; + + lua_pushstring(L, "lighty.con"); + lua_gettable(L, LUA_REGISTRYINDEX); + con = lua_touserdata(L, -1); + lua_pop(L, 1); + + return magnet_array_pairs(L, con->environment); +} + static int magnet_copy_response_header(server *srv, connection *con, plugin_data *p, lua_State *L) { UNUSED(p); @@ -733,6 +889,8 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu 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_pushcfunction(L, magnet_reqhdr_pairs); /* (sp += 1) */ + lua_setfield(L, -2, "__pairs"); /* (sp -= 1) */ lua_setmetatable(L, -2); /* tie the metatable to request (sp -= 1) */ lua_setfield(L, -2, "request"); /* content = {} (sp -= 1) */ @@ -742,6 +900,8 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu lua_setfield(L, -2, "__index"); /* (sp -= 1) */ lua_pushcfunction(L, magnet_env_set); /* (sp += 1) */ lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */ + lua_pushcfunction(L, magnet_env_pairs); /* (sp += 1) */ + lua_setfield(L, -2, "__pairs"); /* (sp -= 1) */ lua_setmetatable(L, -2); /* tie the metatable to request (sp -= 1) */ lua_setfield(L, -2, "env"); /* content = {} (sp -= 1) */ @@ -751,6 +911,8 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu lua_setfield(L, -2, "__index"); /* (sp -= 1) */ lua_pushcfunction(L, magnet_cgi_set); /* (sp += 1) */ lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */ + lua_pushcfunction(L, magnet_cgi_pairs); /* (sp += 1) */ + lua_setfield(L, -2, "__pairs"); /* (sp -= 1) */ lua_setmetatable(L, -2); /* tie the metatable to req_env (sp -= 1) */ lua_setfield(L, -2, "req_env"); /* content = {} (sp -= 1) */ @@ -760,6 +922,8 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu lua_setfield(L, -2, "__index"); /* (sp -= 1) */ lua_pushcfunction(L, magnet_status_set); /* (sp += 1) */ lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */ + lua_pushcfunction(L, magnet_status_pairs); /* (sp += 1) */ + lua_setfield(L, -2, "__pairs"); /* (sp -= 1) */ lua_setmetatable(L, -2); /* tie the metatable to request (sp -= 1) */ lua_setfield(L, -2, "status"); /* content = {} (sp -= 1) */ @@ -778,6 +942,11 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu lua_setfield(L, -2, "lighty"); /* lighty.* (sp -= 1) */ + /* override the default pairs() function to our __pairs capable version */ + lua_getglobal(L, "pairs"); /* push original pairs() (sp += 1) */ + lua_pushcclosure(L, magnet_pairs, 1); + lua_setfield(L, -2, "pairs"); /* (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) */