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