]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_settings.cpp
Revert "Make Lint Happy"
[dragonfireclient.git] / src / script / lua_api / l_settings.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 PilzAdam <pilzadam@minetest.net>
4
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.
9
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.
14
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.
18 */
19
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
24 #include "settings.h"
25 #include "noise.h"
26 #include "log.h"
27
28
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."); \
33         }
34
35 LuaSettings::LuaSettings(Settings *settings, const std::string &filename) :
36         m_settings(settings),
37         m_filename(filename)
38 {
39 }
40
41 LuaSettings::LuaSettings(const std::string &filename, bool write_allowed) :
42         m_filename(filename),
43         m_is_own_settings(true),
44         m_write_allowed(write_allowed)
45 {
46         m_settings = new Settings();
47         m_settings->readConfigFile(filename.c_str());
48 }
49
50 LuaSettings::~LuaSettings()
51 {
52         if (m_is_own_settings)
53                 delete m_settings;
54 }
55
56
57 void LuaSettings::create(lua_State *L, Settings *settings,
58                 const std::string &filename)
59 {
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);
64 }
65
66
67 // garbage collector
68 int LuaSettings::gc_object(lua_State* L)
69 {
70         LuaSettings* o = *(LuaSettings **)(lua_touserdata(L, 1));
71         delete o;
72         return 0;
73 }
74
75
76 // get(self, key) -> value
77 int LuaSettings::l_get(lua_State* L)
78 {
79         NO_MAP_LOCK_REQUIRED;
80         LuaSettings* o = checkobject(L, 1);
81
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());
86         } else {
87                 lua_pushnil(L);
88         }
89
90         return 1;
91 }
92
93 // get_bool(self, key) -> boolean
94 int LuaSettings::l_get_bool(lua_State* L)
95 {
96         NO_MAP_LOCK_REQUIRED;
97         LuaSettings* o = checkobject(L, 1);
98
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);
103         } else {
104                 // Push default value
105                 if (lua_isboolean(L, 3))
106                         lua_pushboolean(L, readParam<bool>(L, 3));
107                 else
108                         lua_pushnil(L);
109         }
110
111         return 1;
112 }
113
114 // get_np_group(self, key) -> value
115 int LuaSettings::l_get_np_group(lua_State *L)
116 {
117         NO_MAP_LOCK_REQUIRED;
118         LuaSettings *o = checkobject(L, 1);
119
120         std::string key = std::string(luaL_checkstring(L, 2));
121         if (o->m_settings->exists(key)) {
122                 NoiseParams np;
123                 o->m_settings->getNoiseParams(key, np);
124                 push_noiseparams(L, &np);
125         } else {
126                 lua_pushnil(L);
127         }
128
129         return 1;
130 }
131
132 int LuaSettings::l_get_flags(lua_State *L)
133 {
134         NO_MAP_LOCK_REQUIRED;
135         LuaSettings *o = checkobject(L, 1);
136         std::string key = std::string(luaL_checkstring(L, 2));
137
138         u32 flags = 0;
139         auto flagdesc = o->m_settings->getFlagDescFallback(key);
140         if (o->m_settings->getFlagStrNoEx(key, flags, flagdesc)) {
141                 lua_newtable(L);
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);
146                 }
147                 lua_pushvalue(L, table);
148         } else {
149                 lua_pushnil(L);
150         }
151
152         return 1;
153 }
154
155 // set(self, key, value)
156 int LuaSettings::l_set(lua_State* L)
157 {
158         NO_MAP_LOCK_REQUIRED;
159         LuaSettings* o = checkobject(L, 1);
160
161         std::string key = std::string(luaL_checkstring(L, 2));
162         const char* value = luaL_checkstring(L, 3);
163
164         SET_SECURITY_CHECK(L, key);
165
166         if (!o->m_settings->set(key, value))
167                 throw LuaError("Invalid sequence found in setting parameters");
168
169         return 0;
170 }
171
172 // set_bool(self, key, value)
173 int LuaSettings::l_set_bool(lua_State* L)
174 {
175         NO_MAP_LOCK_REQUIRED;
176         LuaSettings* o = checkobject(L, 1);
177
178         std::string key = std::string(luaL_checkstring(L, 2));
179         bool value = readParam<bool>(L, 3);
180
181         SET_SECURITY_CHECK(L, key);
182
183         o->m_settings->setBool(key, value);
184
185         return 1;
186 }
187
188 // set(self, key, value)
189 int LuaSettings::l_set_np_group(lua_State *L)
190 {
191         NO_MAP_LOCK_REQUIRED;
192         LuaSettings *o = checkobject(L, 1);
193
194         std::string key = std::string(luaL_checkstring(L, 2));
195         NoiseParams value;
196         read_noiseparams(L, 3, &value);
197
198         SET_SECURITY_CHECK(L, key);
199
200         o->m_settings->setNoiseParams(key, value, false);
201
202         return 0;
203 }
204
205 // remove(self, key) -> success
206 int LuaSettings::l_remove(lua_State* L)
207 {
208         NO_MAP_LOCK_REQUIRED;
209         LuaSettings* o = checkobject(L, 1);
210
211         std::string key = std::string(luaL_checkstring(L, 2));
212
213         SET_SECURITY_CHECK(L, key);
214
215         bool success = o->m_settings->remove(key);
216         lua_pushboolean(L, success);
217
218         return 1;
219 }
220
221 // get_names(self) -> {key1, ...}
222 int LuaSettings::l_get_names(lua_State* L)
223 {
224         NO_MAP_LOCK_REQUIRED;
225         LuaSettings* o = checkobject(L, 1);
226
227         std::vector<std::string> keys = o->m_settings->getNames();
228
229         lua_newtable(L);
230         for (unsigned int i=0; i < keys.size(); i++)
231         {
232                 lua_pushstring(L, keys[i].c_str());
233                 lua_rawseti(L, -2, i + 1);
234         }
235
236         return 1;
237 }
238
239 // write(self) -> success
240 int LuaSettings::l_write(lua_State* L)
241 {
242         NO_MAP_LOCK_REQUIRED;
243         LuaSettings* o = checkobject(L, 1);
244
245         if (!o->m_write_allowed) {
246                 throw LuaError("Settings: writing " + o->m_filename +
247                                 " not allowed with mod security on.");
248         }
249
250         bool success = o->m_settings->updateConfigFile(o->m_filename.c_str());
251         lua_pushboolean(L, success);
252
253         return 1;
254 }
255
256 // to_table(self) -> {[key1]=value1,...}
257 int LuaSettings::l_to_table(lua_State* L)
258 {
259         NO_MAP_LOCK_REQUIRED;
260         LuaSettings* o = checkobject(L, 1);
261
262         std::vector<std::string> keys = o->m_settings->getNames();
263
264         lua_newtable(L);
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());
268         }
269
270         return 1;
271 }
272
273
274 void LuaSettings::Register(lua_State* L)
275 {
276         lua_newtable(L);
277         int methodtable = lua_gettop(L);
278         luaL_newmetatable(L, className);
279         int metatable = lua_gettop(L);
280
281         lua_pushliteral(L, "__metatable");
282         lua_pushvalue(L, methodtable);
283         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
284
285         lua_pushliteral(L, "__index");
286         lua_pushvalue(L, methodtable);
287         lua_settable(L, metatable);
288
289         lua_pushliteral(L, "__gc");
290         lua_pushcfunction(L, gc_object);
291         lua_settable(L, metatable);
292
293         lua_pop(L, 1);  // drop metatable
294
295         luaL_openlib(L, 0, methods, 0);  // fill methodtable
296         lua_pop(L, 1);  // drop methodtable
297
298         // Can be created from Lua (Settings(filename))
299         lua_register(L, className, create_object);
300 }
301
302 // LuaSettings(filename)
303 // Creates a LuaSettings and leaves it on top of the stack
304 int LuaSettings::create_object(lua_State* L)
305 {
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);
314         return 1;
315 }
316
317 LuaSettings* LuaSettings::checkobject(lua_State* L, int narg)
318 {
319         NO_MAP_LOCK_REQUIRED;
320         luaL_checktype(L, narg, LUA_TUSERDATA);
321         void *ud = luaL_checkudata(L, narg, className);
322         if (!ud)
323                 luaL_typerror(L, narg, className);
324         return *(LuaSettings**) ud;  // unbox pointer
325 }
326
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),
340         {0,0}
341 };