static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, buffer *name) { lua_State *L; int lua_return_value; const int func_ndx = 1; const int lighty_table_ndx = 2; /* get the script-context */ L = script_cache_get_script(srv, con, p->cache, name); if (lua_isstring(L, -1)) { log_error_write(srv, __FILE__, __LINE__, "sbss", "loading script", name, "failed:", lua_tostring(L, -1)); lua_pop(L, 1); force_assert(lua_gettop(L) == 0); /* only the error should have been on the stack */ con->http_status = 500; con->mode = DIRECT; return HANDLER_FINISHED; } force_assert(lua_gettop(L) == 1); force_assert(lua_isfunction(L, func_ndx)); lua_pushlightuserdata(L, srv); lua_setfield(L, LUA_REGISTRYINDEX, LUA_RIDX_LIGHTTPD_SERVER); lua_pushlightuserdata(L, con); lua_setfield(L, LUA_REGISTRYINDEX, LUA_RIDX_LIGHTTPD_CONNECTION); lua_atpanic(L, magnet_atpanic); /** * 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 * in the global env. * * 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) */ /* we have to overwrite the print function */ lua_pushcfunction(L, magnet_print); /* (sp += 1) */ lua_setfield(L, -2, "print"); /* -1 is the env we want to set(sp -= 1) */ /** * lighty.request[] (ro) has the HTTP-request headers * lighty.env[] (rw) has various url/physical file paths and * request meta data; might contain nil values * lighty.req_env[] (ro) has the cgi environment * lighty.status[] (ro) has the status counters * lighty.content[] (rw) is a table of string/file * lighty.header[] (rw) is a array to set response headers */ lua_newtable(L); /* lighty.* (sp += 1) */ 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_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) */ lua_newtable(L); /* {} (sp += 1) */ lua_newtable(L); /* the meta-table for the env-table (sp += 1) */ lua_pushcfunction(L, magnet_env_get); /* (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_pushcfunction(L, magnet_env_pairs); /* (sp += 1) */ lua_setfield(L, -2, "__pairs"); /* (sp -= 1) */ lua_setmetatable(L, -2); /* tie the metatable to env (sp -= 1) */ lua_setfield(L, -2, "env"); /* content = {} (sp -= 1) */ lua_newtable(L); /* {} (sp += 1) */ lua_newtable(L); /* the meta-table for the req_env-table (sp += 1) */ lua_pushcfunction(L, magnet_cgi_get); /* (sp += 1) */ 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) */ lua_newtable(L); /* {} (sp += 1) */ lua_newtable(L); /* the meta-table for the status-table (sp += 1) */ lua_pushcfunction(L, magnet_status_get); /* (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_pushcfunction(L, magnet_status_pairs); /* (sp += 1) */ lua_setfield(L, -2, "__pairs"); /* (sp -= 1) */ lua_setmetatable(L, -2); /* tie the metatable to statzs (sp -= 1) */ lua_setfield(L, -2, "status"); /* content = {} (sp -= 1) */ /* add empty 'content' and 'header' tables */ lua_newtable(L); /* {} (sp += 1) */ lua_setfield(L, -2, "content"); /* content = {} (sp -= 1) */ lua_newtable(L); /* {} (sp += 1) */ lua_setfield(L, -2, "header"); /* header = {} (sp -= 1) */ 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) */ /* insert lighty table at index 2 */ lua_pushvalue(L, -1); lua_insert(L, lighty_table_ndx); lua_setfield(L, -2, "lighty"); /* lighty.* (sp -= 1) */ #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502 /* override the default pairs() function to our __pairs capable version; * not needed for lua 5.2+ */ lua_getglobal(L, "pairs"); /* push original pairs() (sp += 1) */ lua_pushcclosure(L, magnet_pairs, 1); lua_setfield(L, -2, "pairs"); /* (sp -= 1) */ #endif lua_newtable(L); /* the meta-table for the new env (sp += 1) */ magnet_get_global_table(L); /* (sp += 1) */ lua_setfield(L, -2, "__index"); /* { __index = _G } (sp -= 1) */ lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) (sp -= 1) */ magnet_setfenv_mainfn(L, 1); /* (sp -= 1) */ /* pcall will destroy the func value, duplicate it */ /* (sp += 1) */ lua_pushvalue(L, func_ndx); { int errfunc = push_traceback(L, 0); int ret = lua_pcall(L, 0, 1, errfunc); lua_remove(L, errfunc); /* reset environment */ magnet_get_global_table(L); /* (sp += 1) */ magnet_setfenv_mainfn(L, 1); /* (sp -= 1) */ if (0 != ret) { log_error_write(srv, __FILE__, __LINE__, "ss", "lua_pcall():", lua_tostring(L, -1)); lua_pop(L, 2); /* remove the error-msg and the lighty table at index 2 */ force_assert(lua_gettop(L) == 1); /* only the function should be on the stack */ con->http_status = 500; con->mode = DIRECT; return HANDLER_FINISHED; } } /* we should have the function, the lighty table and the return value on the stack */ force_assert(lua_gettop(L) == 3); lua_return_value = (int) luaL_optinteger(L, -1, -1); lua_pop(L, 1); /* pop return value */ magnet_copy_response_header(srv, con, L, lighty_table_ndx); { handler_t result = HANDLER_GO_ON; 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, L, lighty_table_ndx); if (!chunkqueue_is_empty(con->write_queue)) { con->mode = p->id; } } else { lua_settop(L, 2); /* remove all but function and lighty table */ /* } catch () { */ con->http_status = 500; con->mode = DIRECT; } result = HANDLER_FINISHED; } else if (MAGNET_RESTART_REQUEST == lua_return_value) { result = HANDLER_COMEBACK; } lua_pop(L, 1); /* pop the lighty table */ force_assert(lua_gettop(L) == 1); /* only the function should remain on the stack */ return result; } }
static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, buffer *name) { lua_State *L; int lua_return_value = -1; /* get the script-context */ L = script_cache_get_script(srv, con, p->cache, name); if (lua_isstring(L, -1)) { log_error_write(srv, __FILE__, __LINE__, "sbss", "loading script", name, "failed:", 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; con->mode = DIRECT; return HANDLER_FINISHED; } lua_pushstring(L, "lighty.srv"); lua_pushlightuserdata(L, srv); lua_settable(L, LUA_REGISTRYINDEX); /* registery[<id>] = srv */ 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 * * setmetatable({}, {__index = _G}) * * 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 * away at the end of the script run. */ lua_newtable(L); /* my empty environment aka {} (sp += 1) */ /* we have to overwrite the print function */ lua_pushcfunction(L, magnet_print); /* (sp += 1) */ 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.header[] is a array to set response headers */ lua_newtable(L); /* lighty.* (sp += 1) */ 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_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_pushcfunction(L, magnet_env_set); /* (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_pushcfunction(L, magnet_status_set); /* (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) */ /* add empty 'content' and 'header' tables */ lua_newtable(L); /* {} (sp += 1) */ lua_setfield(L, -2, "content"); /* content = {} (sp -= 1) */ lua_newtable(L); /* {} (sp += 1) */ lua_setfield(L, -2, "header"); /* header = {} (sp -= 1) */ 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", "lua_pcall():", lua_tostring(L, -1)); lua_pop(L, 1); /* remove the error-msg and the function copy from the stack */ assert(lua_gettop(L) == 1); /* only the function should be on the stack */ con->http_status = 500; con->mode = DIRECT; return HANDLER_FINISHED; } /* we should have the function-copy and the return value on the stack */ assert(lua_gettop(L) == 2); if (lua_isnumber(L, -1)) { /* if the ret-value is a number, take it */ lua_return_value = (int)lua_tonumber(L, -1); } lua_pop(L, 1); /* pop the ret-value */ magnet_copy_response_header(srv, con, p, L); 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); if (!chunkqueue_is_empty(con->write_queue)) { con->mode = p->id; } } else { /* } catch () { */ con->http_status = 500; con->mode = DIRECT; } assert(lua_gettop(L) == 1); /* only the function should be on the stack */ /* we are finished */ return HANDLER_FINISHED; } else if (MAGNET_RESTART_REQUEST == lua_return_value) { assert(lua_gettop(L) == 1); /* only the function should be on the stack */ return HANDLER_COMEBACK; } else { assert(lua_gettop(L) == 1); /* only the function should be on the stack */ return HANDLER_GO_ON; } }