3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
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_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 "cpp_api/s_security.h"
28 #include "areastore.h"
35 #include "util/auth.h"
39 // Writes a line to dstream
40 int ModApiUtil::l_debug(lua_State *L)
43 // Handle multiple parameters to behave like standard lua print()
44 int n = lua_gettop(L);
45 lua_getglobal(L, "tostring");
46 for (int i = 1; i <= n; i++) {
48 Call tostring(i-th argument).
49 This is what print() does, and it behaves a bit
50 differently from directly calling lua_tostring.
52 lua_pushvalue(L, -1); /* function to be called */
53 lua_pushvalue(L, i); /* value to print */
56 const char *s = lua_tolstring(L, -1, &len);
60 dstream << std::string(s, len);
68 // Writes a line to the logger.
69 // The one-argument version logs to infostream.
70 // The two-argument version accept a log level: error, action, info, or verbose.
71 int ModApiUtil::l_log(lua_State *L)
75 LogMessageLevel level = LMT_INFO;
76 if (lua_isnone(L, 2)) {
77 text = lua_tostring(L, 1);
80 std::string levelname = luaL_checkstring(L, 1);
81 text = luaL_checkstring(L, 2);
82 if(levelname == "error")
84 else if(levelname == "action")
86 else if(levelname == "verbose")
88 else if (levelname == "deprecated") {
89 log_deprecated(L,text);
94 log_printline(level, text);
98 #define CHECK_SECURE_SETTING(L, name) \
99 if (name.compare(0, 7, "secure.") == 0) {\
100 lua_pushliteral(L, "Attempt to set secure setting.");\
104 // setting_set(name, value)
105 int ModApiUtil::l_setting_set(lua_State *L)
107 NO_MAP_LOCK_REQUIRED;
108 std::string name = luaL_checkstring(L, 1);
109 std::string value = luaL_checkstring(L, 2);
110 CHECK_SECURE_SETTING(L, name);
111 g_settings->set(name, value);
116 int ModApiUtil::l_setting_get(lua_State *L)
118 NO_MAP_LOCK_REQUIRED;
119 const char *name = luaL_checkstring(L, 1);
121 std::string value = g_settings->get(name);
122 lua_pushstring(L, value.c_str());
123 } catch(SettingNotFoundException &e){
129 // setting_setbool(name)
130 int ModApiUtil::l_setting_setbool(lua_State *L)
132 NO_MAP_LOCK_REQUIRED;
133 std::string name = luaL_checkstring(L, 1);
134 bool value = lua_toboolean(L, 2);
135 CHECK_SECURE_SETTING(L, name);
136 g_settings->setBool(name, value);
140 // setting_getbool(name)
141 int ModApiUtil::l_setting_getbool(lua_State *L)
143 NO_MAP_LOCK_REQUIRED;
144 const char *name = luaL_checkstring(L, 1);
146 bool value = g_settings->getBool(name);
147 lua_pushboolean(L, value);
148 } catch(SettingNotFoundException &e){
155 int ModApiUtil::l_setting_save(lua_State *L)
157 NO_MAP_LOCK_REQUIRED;
158 if(g_settings_path != "")
159 g_settings->updateConfigFile(g_settings_path.c_str());
163 // parse_json(str[, nullvalue])
164 int ModApiUtil::l_parse_json(lua_State *L)
166 NO_MAP_LOCK_REQUIRED;
168 const char *jsonstr = luaL_checkstring(L, 1);
170 // Use passed nullvalue or default to nil
172 if (lua_isnone(L, nullindex)) {
174 nullindex = lua_gettop(L);
181 std::istringstream stream(jsonstr);
183 if (!reader.parse(stream, root)) {
184 errorstream << "Failed to parse json data "
185 << reader.getFormattedErrorMessages();
186 errorstream << "data: \"" << jsonstr << "\""
193 if (!push_json_value(L, root, nullindex)) {
194 errorstream << "Failed to parse json data, "
195 << "depth exceeds lua stack limit" << std::endl;
196 errorstream << "data: \"" << jsonstr << "\"" << std::endl;
202 // write_json(data[, styled]) -> string or nil and error message
203 int ModApiUtil::l_write_json(lua_State *L)
205 NO_MAP_LOCK_REQUIRED;
208 if (!lua_isnone(L, 2)) {
209 styled = lua_toboolean(L, 2);
215 read_json_value(L, root, 1);
216 } catch (SerializationError &e) {
218 lua_pushstring(L, e.what());
224 Json::StyledWriter writer;
225 out = writer.write(root);
227 Json::FastWriter writer;
228 out = writer.write(root);
230 lua_pushlstring(L, out.c_str(), out.size());
234 // get_dig_params(groups, tool_capabilities[, time_from_last_punch])
235 int ModApiUtil::l_get_dig_params(lua_State *L)
237 NO_MAP_LOCK_REQUIRED;
238 std::map<std::string, int> groups;
239 read_groups(L, 1, groups);
240 ToolCapabilities tp = read_tool_capabilities(L, 2);
241 if(lua_isnoneornil(L, 3))
242 push_dig_params(L, getDigParams(groups, &tp));
244 push_dig_params(L, getDigParams(groups, &tp,
245 luaL_checknumber(L, 3)));
249 // get_hit_params(groups, tool_capabilities[, time_from_last_punch])
250 int ModApiUtil::l_get_hit_params(lua_State *L)
252 NO_MAP_LOCK_REQUIRED;
253 std::map<std::string, int> groups;
254 read_groups(L, 1, groups);
255 ToolCapabilities tp = read_tool_capabilities(L, 2);
256 if(lua_isnoneornil(L, 3))
257 push_hit_params(L, getHitParams(groups, &tp));
259 push_hit_params(L, getHitParams(groups, &tp,
260 luaL_checknumber(L, 3)));
264 // get_password_hash(name, raw_password)
265 int ModApiUtil::l_get_password_hash(lua_State *L)
267 NO_MAP_LOCK_REQUIRED;
268 std::string name = luaL_checkstring(L, 1);
269 std::string raw_password = luaL_checkstring(L, 2);
270 std::string hash = translatePassword(name, raw_password);
271 lua_pushstring(L, hash.c_str());
276 int ModApiUtil::l_is_yes(lua_State *L)
278 NO_MAP_LOCK_REQUIRED;
280 lua_getglobal(L, "tostring"); // function to be called
281 lua_pushvalue(L, 1); // 1st argument
282 lua_call(L, 1, 1); // execute function
283 std::string str(lua_tostring(L, -1)); // get result
286 bool yes = is_yes(str);
287 lua_pushboolean(L, yes);
291 int ModApiUtil::l_get_builtin_path(lua_State *L)
293 std::string path = porting::path_share + DIR_DELIM + "builtin";
294 lua_pushstring(L, path.c_str());
298 // compress(data, method, level)
299 int ModApiUtil::l_compress(lua_State *L)
302 const char *data = luaL_checklstring(L, 1, &size);
305 if (!lua_isnone(L, 3) && !lua_isnil(L, 3))
306 level = luaL_checknumber(L, 3);
308 std::ostringstream os;
309 compressZlib(std::string(data, size), os, level);
311 std::string out = os.str();
313 lua_pushlstring(L, out.data(), out.size());
317 // decompress(data, method)
318 int ModApiUtil::l_decompress(lua_State *L)
321 const char *data = luaL_checklstring(L, 1, &size);
323 std::istringstream is(std::string(data, size));
324 std::ostringstream os;
325 decompressZlib(is, os);
327 std::string out = os.str();
329 lua_pushlstring(L, out.data(), out.size());
334 int ModApiUtil::l_mkdir(lua_State *L)
336 NO_MAP_LOCK_REQUIRED;
337 const char *path = luaL_checkstring(L, 1);
338 CHECK_SECURE_PATH_OPTIONAL(L, path);
339 lua_pushboolean(L, fs::CreateAllDirs(path));
343 // get_dir_list(path, is_dir)
344 int ModApiUtil::l_get_dir_list(lua_State *L)
346 NO_MAP_LOCK_REQUIRED;
347 const char *path = luaL_checkstring(L, 1);
348 short is_dir = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : -1;
350 CHECK_SECURE_PATH_OPTIONAL(L, path);
352 std::vector<fs::DirListNode> list = fs::GetDirListing(path);
357 for (size_t i = 0; i < list.size(); i++) {
358 if (is_dir == -1 || is_dir == list[i].dir) {
359 lua_pushstring(L, list[i].name.c_str());
360 lua_rawseti(L, -2, ++index);
367 int ModApiUtil::l_request_insecure_environment(lua_State *L)
369 NO_MAP_LOCK_REQUIRED;
370 if (!ScriptApiSecurity::isSecure(L)) {
371 lua_getglobal(L, "_G");
374 lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
375 if (!lua_isstring(L, -1)) {
379 const char *mod_name = lua_tostring(L, -1);
380 std::string trusted_mods = g_settings->get("secure.trusted_mods");
381 std::vector<std::string> mod_list = str_split(trusted_mods, ',');
382 if (std::find(mod_list.begin(), mod_list.end(), mod_name) == mod_list.end()) {
386 lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_GLOBALS_BACKUP);
391 void ModApiUtil::Initialize(lua_State *L, int top)
396 API_FCT(setting_set);
397 API_FCT(setting_get);
398 API_FCT(setting_setbool);
399 API_FCT(setting_getbool);
400 API_FCT(setting_save);
405 API_FCT(get_dig_params);
406 API_FCT(get_hit_params);
408 API_FCT(get_password_hash);
412 API_FCT(get_builtin_path);
418 API_FCT(get_dir_list);
420 API_FCT(request_insecure_environment);
423 void ModApiUtil::InitializeAsync(AsyncEngine& engine)
425 ASYNC_API_FCT(debug);
428 //ASYNC_API_FCT(setting_set);
429 ASYNC_API_FCT(setting_get);
430 //ASYNC_API_FCT(setting_setbool);
431 ASYNC_API_FCT(setting_getbool);
432 //ASYNC_API_FCT(setting_save);
434 ASYNC_API_FCT(parse_json);
435 ASYNC_API_FCT(write_json);
437 ASYNC_API_FCT(is_yes);
439 ASYNC_API_FCT(get_builtin_path);
441 ASYNC_API_FCT(compress);
442 ASYNC_API_FCT(decompress);
444 ASYNC_API_FCT(mkdir);
445 ASYNC_API_FCT(get_dir_list);