3 Copyright (C) 2013 PilzAdam <pilzadam@minetest.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "lua_api/l_settings.h"
21 #include "lua_api/l_internal.h"
22 #include "cpp_api/s_security.h"
23 #include "util/string.h" // FlagDesc
29 #define SET_SECURITY_CHECK(L, name) \
30 if (o->m_settings == g_settings && ScriptApiSecurity::isSecure(L) && \
31 name.compare(0, 7, "secure.") == 0) { \
32 throw LuaError("Attempt to set secure setting."); \
35 LuaSettings::LuaSettings(Settings *settings, const std::string &filename) :
41 LuaSettings::LuaSettings(const std::string &filename, bool write_allowed) :
43 m_is_own_settings(true),
44 m_write_allowed(write_allowed)
46 m_settings = new Settings();
47 m_settings->readConfigFile(filename.c_str());
50 LuaSettings::~LuaSettings()
52 if (m_is_own_settings)
57 void LuaSettings::create(lua_State *L, Settings *settings,
58 const std::string &filename)
60 LuaSettings *o = new LuaSettings(settings, filename);
61 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
62 luaL_getmetatable(L, className);
63 lua_setmetatable(L, -2);
68 int LuaSettings::gc_object(lua_State* L)
70 LuaSettings* o = *(LuaSettings **)(lua_touserdata(L, 1));
76 // get(self, key) -> value
77 int LuaSettings::l_get(lua_State* L)
80 LuaSettings* o = checkobject(L, 1);
82 std::string key = std::string(luaL_checkstring(L, 2));
83 if (o->m_settings->exists(key)) {
84 std::string value = o->m_settings->get(key);
85 lua_pushstring(L, value.c_str());
93 // get_bool(self, key) -> boolean
94 int LuaSettings::l_get_bool(lua_State* L)
97 LuaSettings* o = checkobject(L, 1);
99 std::string key = std::string(luaL_checkstring(L, 2));
100 if (o->m_settings->exists(key)) {
101 bool value = o->m_settings->getBool(key);
102 lua_pushboolean(L, value);
104 // Push default value
105 if (lua_isboolean(L, 3))
106 lua_pushboolean(L, readParam<bool>(L, 3));
114 // get_np_group(self, key) -> value
115 int LuaSettings::l_get_np_group(lua_State *L)
117 NO_MAP_LOCK_REQUIRED;
118 LuaSettings *o = checkobject(L, 1);
120 std::string key = std::string(luaL_checkstring(L, 2));
121 if (o->m_settings->exists(key)) {
123 o->m_settings->getNoiseParams(key, np);
124 push_noiseparams(L, &np);
132 int LuaSettings::l_get_flags(lua_State *L)
134 NO_MAP_LOCK_REQUIRED;
135 LuaSettings *o = checkobject(L, 1);
136 std::string key = std::string(luaL_checkstring(L, 2));
139 auto flagdesc = o->m_settings->getFlagDescFallback(key);
140 if (o->m_settings->getFlagStrNoEx(key, flags, flagdesc)) {
142 int table = lua_gettop(L);
143 for (size_t i = 0; flagdesc[i].name; ++i) {
144 lua_pushboolean(L, flags & flagdesc[i].flag);
145 lua_setfield(L, table, flagdesc[i].name);
147 lua_pushvalue(L, table);
155 // set(self, key, value)
156 int LuaSettings::l_set(lua_State* L)
158 NO_MAP_LOCK_REQUIRED;
159 LuaSettings* o = checkobject(L, 1);
161 std::string key = std::string(luaL_checkstring(L, 2));
162 const char* value = luaL_checkstring(L, 3);
164 SET_SECURITY_CHECK(L, key);
166 if (!o->m_settings->set(key, value))
167 throw LuaError("Invalid sequence found in setting parameters");
172 // set_bool(self, key, value)
173 int LuaSettings::l_set_bool(lua_State* L)
175 NO_MAP_LOCK_REQUIRED;
176 LuaSettings* o = checkobject(L, 1);
178 std::string key = std::string(luaL_checkstring(L, 2));
179 bool value = readParam<bool>(L, 3);
181 SET_SECURITY_CHECK(L, key);
183 o->m_settings->setBool(key, value);
188 // set(self, key, value)
189 int LuaSettings::l_set_np_group(lua_State *L)
191 NO_MAP_LOCK_REQUIRED;
192 LuaSettings *o = checkobject(L, 1);
194 std::string key = std::string(luaL_checkstring(L, 2));
196 read_noiseparams(L, 3, &value);
198 SET_SECURITY_CHECK(L, key);
200 o->m_settings->setNoiseParams(key, value, false);
205 // remove(self, key) -> success
206 int LuaSettings::l_remove(lua_State* L)
208 NO_MAP_LOCK_REQUIRED;
209 LuaSettings* o = checkobject(L, 1);
211 std::string key = std::string(luaL_checkstring(L, 2));
213 SET_SECURITY_CHECK(L, key);
215 bool success = o->m_settings->remove(key);
216 lua_pushboolean(L, success);
221 // get_names(self) -> {key1, ...}
222 int LuaSettings::l_get_names(lua_State* L)
224 NO_MAP_LOCK_REQUIRED;
225 LuaSettings* o = checkobject(L, 1);
227 std::vector<std::string> keys = o->m_settings->getNames();
230 for (unsigned int i=0; i < keys.size(); i++)
232 lua_pushstring(L, keys[i].c_str());
233 lua_rawseti(L, -2, i + 1);
239 // write(self) -> success
240 int LuaSettings::l_write(lua_State* L)
242 NO_MAP_LOCK_REQUIRED;
243 LuaSettings* o = checkobject(L, 1);
245 if (!o->m_write_allowed) {
246 throw LuaError("Settings: writing " + o->m_filename +
247 " not allowed with mod security on.");
250 bool success = o->m_settings->updateConfigFile(o->m_filename.c_str());
251 lua_pushboolean(L, success);
256 // to_table(self) -> {[key1]=value1,...}
257 int LuaSettings::l_to_table(lua_State* L)
259 NO_MAP_LOCK_REQUIRED;
260 LuaSettings* o = checkobject(L, 1);
262 std::vector<std::string> keys = o->m_settings->getNames();
265 for (const std::string &key : keys) {
266 lua_pushstring(L, o->m_settings->get(key).c_str());
267 lua_setfield(L, -2, key.c_str());
274 void LuaSettings::Register(lua_State* L)
277 int methodtable = lua_gettop(L);
278 luaL_newmetatable(L, className);
279 int metatable = lua_gettop(L);
281 lua_pushliteral(L, "__metatable");
282 lua_pushvalue(L, methodtable);
283 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
285 lua_pushliteral(L, "__index");
286 lua_pushvalue(L, methodtable);
287 lua_settable(L, metatable);
289 lua_pushliteral(L, "__gc");
290 lua_pushcfunction(L, gc_object);
291 lua_settable(L, metatable);
293 lua_pop(L, 1); // drop metatable
295 luaL_openlib(L, 0, methods, 0); // fill methodtable
296 lua_pop(L, 1); // drop methodtable
298 // Can be created from Lua (Settings(filename))
299 lua_register(L, className, create_object);
302 // LuaSettings(filename)
303 // Creates a LuaSettings and leaves it on top of the stack
304 int LuaSettings::create_object(lua_State* L)
306 NO_MAP_LOCK_REQUIRED;
307 bool write_allowed = true;
308 const char* filename = luaL_checkstring(L, 1);
309 CHECK_SECURE_PATH_POSSIBLE_WRITE(L, filename, &write_allowed);
310 LuaSettings* o = new LuaSettings(filename, write_allowed);
311 *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
312 luaL_getmetatable(L, className);
313 lua_setmetatable(L, -2);
317 LuaSettings* LuaSettings::checkobject(lua_State* L, int narg)
319 NO_MAP_LOCK_REQUIRED;
320 luaL_checktype(L, narg, LUA_TUSERDATA);
321 void *ud = luaL_checkudata(L, narg, className);
323 luaL_typerror(L, narg, className);
324 return *(LuaSettings**) ud; // unbox pointer
327 const char LuaSettings::className[] = "Settings";
328 const luaL_Reg LuaSettings::methods[] = {
329 luamethod(LuaSettings, get),
330 luamethod(LuaSettings, get_bool),
331 luamethod(LuaSettings, get_np_group),
332 luamethod(LuaSettings, get_flags),
333 luamethod(LuaSettings, set),
334 luamethod(LuaSettings, set_bool),
335 luamethod(LuaSettings, set_np_group),
336 luamethod(LuaSettings, remove),
337 luamethod(LuaSettings, get_names),
338 luamethod(LuaSettings, write),
339 luamethod(LuaSettings, to_table),