]> git.lizzy.rs Git - minetest.git/blob - src/script/lua_api/l_util.cpp
Refactor around translatePassword
[minetest.git] / src / script / lua_api / l_util.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
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_util.h"
21 #include "lua_api/l_internal.h"
22 #include "common/c_converter.h"
23 #include "common/c_content.h"
24 #include "cpp_api/s_async.h"
25 #include "serialization.h"
26 #include "json/json.h"
27 #include "debug.h"
28 #include "porting.h"
29 #include "log.h"
30 #include "tool.h"
31 #include "filesys.h"
32 #include "settings.h"
33
34 // debug(...)
35 // Writes a line to dstream
36 int ModApiUtil::l_debug(lua_State *L)
37 {
38         NO_MAP_LOCK_REQUIRED;
39         // Handle multiple parameters to behave like standard lua print()
40         int n = lua_gettop(L);
41         lua_getglobal(L, "tostring");
42         for (int i = 1; i <= n; i++) {
43                 /*
44                         Call tostring(i-th argument).
45                         This is what print() does, and it behaves a bit
46                         differently from directly calling lua_tostring.
47                 */
48                 lua_pushvalue(L, -1);  /* function to be called */
49                 lua_pushvalue(L, i);   /* value to print */
50                 lua_call(L, 1, 1);
51                 size_t len;
52                 const char *s = lua_tolstring(L, -1, &len);
53                 if (i > 1)
54                         dstream << "\t";
55                 if (s)
56                         dstream << std::string(s, len);
57                 lua_pop(L, 1);
58         }
59         dstream << std::endl;
60         return 0;
61 }
62
63 // log([level,] text)
64 // Writes a line to the logger.
65 // The one-argument version logs to infostream.
66 // The two-argument version accept a log level: error, action, info, or verbose.
67 int ModApiUtil::l_log(lua_State *L)
68 {
69         NO_MAP_LOCK_REQUIRED;
70         std::string text;
71         LogMessageLevel level = LMT_INFO;
72         if (lua_isnone(L, 2)) {
73                 text = lua_tostring(L, 1);
74         }
75         else {
76                 std::string levelname = luaL_checkstring(L, 1);
77                 text = luaL_checkstring(L, 2);
78                 if(levelname == "error")
79                         level = LMT_ERROR;
80                 else if(levelname == "action")
81                         level = LMT_ACTION;
82                 else if(levelname == "verbose")
83                         level = LMT_VERBOSE;
84                 else if (levelname == "deprecated") {
85                         log_deprecated(L,text);
86                         return 0;
87                 }
88
89         }
90         log_printline(level, text);
91         return 0;
92 }
93
94 // setting_set(name, value)
95 int ModApiUtil::l_setting_set(lua_State *L)
96 {
97         NO_MAP_LOCK_REQUIRED;
98         const char *name = luaL_checkstring(L, 1);
99         const char *value = luaL_checkstring(L, 2);
100         g_settings->set(name, value);
101         return 0;
102 }
103
104 // setting_get(name)
105 int ModApiUtil::l_setting_get(lua_State *L)
106 {
107         NO_MAP_LOCK_REQUIRED;
108         const char *name = luaL_checkstring(L, 1);
109         try{
110                 std::string value = g_settings->get(name);
111                 lua_pushstring(L, value.c_str());
112         } catch(SettingNotFoundException &e){
113                 lua_pushnil(L);
114         }
115         return 1;
116 }
117
118 // setting_setbool(name)
119 int ModApiUtil::l_setting_setbool(lua_State *L)
120 {
121         NO_MAP_LOCK_REQUIRED;
122         const char *name = luaL_checkstring(L, 1);
123         bool value = lua_toboolean(L, 2);
124         g_settings->setBool(name, value);
125         return 0;
126 }
127
128 // setting_getbool(name)
129 int ModApiUtil::l_setting_getbool(lua_State *L)
130 {
131         NO_MAP_LOCK_REQUIRED;
132         const char *name = luaL_checkstring(L, 1);
133         try{
134                 bool value = g_settings->getBool(name);
135                 lua_pushboolean(L, value);
136         } catch(SettingNotFoundException &e){
137                 lua_pushnil(L);
138         }
139         return 1;
140 }
141
142 // setting_save()
143 int ModApiUtil::l_setting_save(lua_State *L)
144 {
145         NO_MAP_LOCK_REQUIRED;
146         if(g_settings_path != "")
147                 g_settings->updateConfigFile(g_settings_path.c_str());
148         return 0;
149 }
150
151 // parse_json(str[, nullvalue])
152 int ModApiUtil::l_parse_json(lua_State *L)
153 {
154         NO_MAP_LOCK_REQUIRED;
155
156         const char *jsonstr = luaL_checkstring(L, 1);
157
158         // Use passed nullvalue or default to nil
159         int nullindex = 2;
160         if (lua_isnone(L, nullindex)) {
161                 lua_pushnil(L);
162                 nullindex = lua_gettop(L);
163         }
164
165         Json::Value root;
166
167         {
168                 Json::Reader reader;
169                 std::istringstream stream(jsonstr);
170
171                 if (!reader.parse(stream, root)) {
172                         errorstream << "Failed to parse json data "
173                                 << reader.getFormattedErrorMessages();
174                         errorstream << "data: \"" << jsonstr << "\""
175                                 << std::endl;
176                         lua_pushnil(L);
177                         return 1;
178                 }
179         }
180
181         if (!push_json_value(L, root, nullindex)) {
182                 errorstream << "Failed to parse json data, "
183                         << "depth exceeds lua stack limit" << std::endl;
184                 errorstream << "data: \"" << jsonstr << "\"" << std::endl;
185                 lua_pushnil(L);
186         }
187         return 1;
188 }
189
190 // write_json(data[, styled]) -> string or nil and error message
191 int ModApiUtil::l_write_json(lua_State *L)
192 {
193         NO_MAP_LOCK_REQUIRED;
194
195         bool styled = false;
196         if (!lua_isnone(L, 2)) {
197                 styled = lua_toboolean(L, 2);
198                 lua_pop(L, 1);
199         }
200
201         Json::Value root;
202         try {
203                 read_json_value(L, root, 1);
204         } catch (SerializationError &e) {
205                 lua_pushnil(L);
206                 lua_pushstring(L, e.what());
207                 return 2;
208         }
209
210         std::string out;
211         if (styled) {
212                 Json::StyledWriter writer;
213                 out = writer.write(root);
214         } else {
215                 Json::FastWriter writer;
216                 out = writer.write(root);
217         }
218         lua_pushlstring(L, out.c_str(), out.size());
219         return 1;
220 }
221
222 // get_dig_params(groups, tool_capabilities[, time_from_last_punch])
223 int ModApiUtil::l_get_dig_params(lua_State *L)
224 {
225         NO_MAP_LOCK_REQUIRED;
226         std::map<std::string, int> groups;
227         read_groups(L, 1, groups);
228         ToolCapabilities tp = read_tool_capabilities(L, 2);
229         if(lua_isnoneornil(L, 3))
230                 push_dig_params(L, getDigParams(groups, &tp));
231         else
232                 push_dig_params(L, getDigParams(groups, &tp,
233                                         luaL_checknumber(L, 3)));
234         return 1;
235 }
236
237 // get_hit_params(groups, tool_capabilities[, time_from_last_punch])
238 int ModApiUtil::l_get_hit_params(lua_State *L)
239 {
240         NO_MAP_LOCK_REQUIRED;
241         std::map<std::string, int> groups;
242         read_groups(L, 1, groups);
243         ToolCapabilities tp = read_tool_capabilities(L, 2);
244         if(lua_isnoneornil(L, 3))
245                 push_hit_params(L, getHitParams(groups, &tp));
246         else
247                 push_hit_params(L, getHitParams(groups, &tp,
248                                         luaL_checknumber(L, 3)));
249         return 1;
250 }
251
252 // get_password_hash(name, raw_password)
253 int ModApiUtil::l_get_password_hash(lua_State *L)
254 {
255         NO_MAP_LOCK_REQUIRED;
256         std::string name = luaL_checkstring(L, 1);
257         std::string raw_password = luaL_checkstring(L, 2);
258         std::string hash = translatePassword(name, raw_password);
259         lua_pushstring(L, hash.c_str());
260         return 1;
261 }
262
263 // is_yes(arg)
264 int ModApiUtil::l_is_yes(lua_State *L)
265 {
266         NO_MAP_LOCK_REQUIRED;
267
268         lua_getglobal(L, "tostring"); // function to be called
269         lua_pushvalue(L, 1); // 1st argument
270         lua_call(L, 1, 1); // execute function
271         std::string str(lua_tostring(L, -1)); // get result
272         lua_pop(L, 1);
273
274         bool yes = is_yes(str);
275         lua_pushboolean(L, yes);
276         return 1;
277 }
278
279 int ModApiUtil::l_get_builtin_path(lua_State *L)
280 {
281         std::string path = porting::path_share + DIR_DELIM + "builtin";
282         lua_pushstring(L, path.c_str());
283         return 1;
284 }
285
286 // compress(data, method, level)
287 int ModApiUtil::l_compress(lua_State *L)
288 {
289         size_t size;
290         const char *data = luaL_checklstring(L, 1, &size);
291
292         int level = -1;
293         if (!lua_isnone(L, 3) && !lua_isnil(L, 3))
294                 level = luaL_checknumber(L, 3);
295
296         std::ostringstream os;
297         compressZlib(std::string(data, size), os, level);
298
299         std::string out = os.str();
300
301         lua_pushlstring(L, out.data(), out.size());
302         return 1;
303 }
304
305 // decompress(data, method)
306 int ModApiUtil::l_decompress(lua_State *L)
307 {
308         size_t size;
309         const char * data = luaL_checklstring(L, 1, &size);
310
311         std::istringstream is(std::string(data, size));
312         std::ostringstream os;
313         decompressZlib(is, os);
314
315         std::string out = os.str();
316
317         lua_pushlstring(L, out.data(), out.size());
318         return 1;
319 }
320
321 void ModApiUtil::Initialize(lua_State *L, int top)
322 {
323         API_FCT(debug);
324         API_FCT(log);
325
326         API_FCT(setting_set);
327         API_FCT(setting_get);
328         API_FCT(setting_setbool);
329         API_FCT(setting_getbool);
330         API_FCT(setting_save);
331
332         API_FCT(parse_json);
333         API_FCT(write_json);
334
335         API_FCT(get_dig_params);
336         API_FCT(get_hit_params);
337
338         API_FCT(get_password_hash);
339
340         API_FCT(is_yes);
341
342         API_FCT(get_builtin_path);
343
344         API_FCT(compress);
345         API_FCT(decompress);
346 }
347
348 void ModApiUtil::InitializeAsync(AsyncEngine& engine)
349 {
350         ASYNC_API_FCT(debug);
351         ASYNC_API_FCT(log);
352
353         //ASYNC_API_FCT(setting_set);
354         ASYNC_API_FCT(setting_get);
355         //ASYNC_API_FCT(setting_setbool);
356         ASYNC_API_FCT(setting_getbool);
357         //ASYNC_API_FCT(setting_save);
358
359         ASYNC_API_FCT(parse_json);
360         ASYNC_API_FCT(write_json);
361
362         ASYNC_API_FCT(is_yes);
363
364         ASYNC_API_FCT(get_builtin_path);
365
366         ASYNC_API_FCT(compress);
367         ASYNC_API_FCT(decompress);
368 }
369