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"
34 #include "util/auth.h"
38 // Writes a line to the logger.
39 // The one-argument version logs to infostream.
40 // The two-argument version accepts a log level.
41 // Either the special case "deprecated" for deprecation notices, or any specified in
42 // Logger::stringToLevel(name).
43 int ModApiUtil::l_log(lua_State *L)
47 LogLevel level = LL_NONE;
48 if (lua_isnone(L, 2)) {
49 text = luaL_checkstring(L, 1);
51 std::string name = luaL_checkstring(L, 1);
52 text = luaL_checkstring(L, 2);
53 if (name == "deprecated") {
54 log_deprecated(L, text);
57 level = Logger::stringToLevel(name);
58 if (level == LL_MAX) {
59 warningstream << "Tried to log at unknown level '" << name
60 << "'. Defaulting to \"none\"." << std::endl;
64 g_logger.log(level, text);
69 int ModApiUtil::l_get_us_time(lua_State *L)
72 lua_pushnumber(L, porting::getTimeUs());
76 #define CHECK_SECURE_SETTING(L, name) \
77 if (ScriptApiSecurity::isSecure(L) && \
78 name.compare(0, 7, "secure.") == 0) { \
79 throw LuaError("Attempt to set secure setting."); \
82 // setting_set(name, value)
83 int ModApiUtil::l_setting_set(lua_State *L)
86 std::string name = luaL_checkstring(L, 1);
87 std::string value = luaL_checkstring(L, 2);
88 CHECK_SECURE_SETTING(L, name);
89 g_settings->set(name, value);
94 int ModApiUtil::l_setting_get(lua_State *L)
97 const char *name = luaL_checkstring(L, 1);
99 std::string value = g_settings->get(name);
100 lua_pushstring(L, value.c_str());
101 } catch(SettingNotFoundException &e){
107 // setting_setbool(name)
108 int ModApiUtil::l_setting_setbool(lua_State *L)
110 NO_MAP_LOCK_REQUIRED;
111 std::string name = luaL_checkstring(L, 1);
112 bool value = lua_toboolean(L, 2);
113 CHECK_SECURE_SETTING(L, name);
114 g_settings->setBool(name, value);
118 // setting_getbool(name)
119 int ModApiUtil::l_setting_getbool(lua_State *L)
121 NO_MAP_LOCK_REQUIRED;
122 const char *name = luaL_checkstring(L, 1);
124 bool value = g_settings->getBool(name);
125 lua_pushboolean(L, value);
126 } catch(SettingNotFoundException &e){
133 int ModApiUtil::l_setting_save(lua_State *L)
135 NO_MAP_LOCK_REQUIRED;
136 if(g_settings_path != "")
137 g_settings->updateConfigFile(g_settings_path.c_str());
141 // parse_json(str[, nullvalue])
142 int ModApiUtil::l_parse_json(lua_State *L)
144 NO_MAP_LOCK_REQUIRED;
146 const char *jsonstr = luaL_checkstring(L, 1);
148 // Use passed nullvalue or default to nil
150 if (lua_isnone(L, nullindex)) {
152 nullindex = lua_gettop(L);
159 std::istringstream stream(jsonstr);
161 if (!reader.parse(stream, root)) {
162 errorstream << "Failed to parse json data "
163 << reader.getFormattedErrorMessages();
164 size_t jlen = strlen(jsonstr);
166 errorstream << "Data (" << jlen
167 << " bytes) printed to warningstream." << std::endl;
168 warningstream << "data: \"" << jsonstr << "\"" << std::endl;
170 errorstream << "data: \"" << jsonstr << "\"" << std::endl;
177 if (!push_json_value(L, root, nullindex)) {
178 errorstream << "Failed to parse json data, "
179 << "depth exceeds lua stack limit" << std::endl;
180 errorstream << "data: \"" << jsonstr << "\"" << std::endl;
186 // write_json(data[, styled]) -> string or nil and error message
187 int ModApiUtil::l_write_json(lua_State *L)
189 NO_MAP_LOCK_REQUIRED;
192 if (!lua_isnone(L, 2)) {
193 styled = lua_toboolean(L, 2);
199 read_json_value(L, root, 1);
200 } catch (SerializationError &e) {
202 lua_pushstring(L, e.what());
208 Json::StyledWriter writer;
209 out = writer.write(root);
211 Json::FastWriter writer;
212 out = writer.write(root);
214 lua_pushlstring(L, out.c_str(), out.size());
218 // get_dig_params(groups, tool_capabilities[, time_from_last_punch])
219 int ModApiUtil::l_get_dig_params(lua_State *L)
221 NO_MAP_LOCK_REQUIRED;
222 std::map<std::string, int> groups;
223 read_groups(L, 1, groups);
224 ToolCapabilities tp = read_tool_capabilities(L, 2);
225 if(lua_isnoneornil(L, 3))
226 push_dig_params(L, getDigParams(groups, &tp));
228 push_dig_params(L, getDigParams(groups, &tp,
229 luaL_checknumber(L, 3)));
233 // get_hit_params(groups, tool_capabilities[, time_from_last_punch])
234 int ModApiUtil::l_get_hit_params(lua_State *L)
236 NO_MAP_LOCK_REQUIRED;
237 std::map<std::string, int> groups;
238 read_groups(L, 1, groups);
239 ToolCapabilities tp = read_tool_capabilities(L, 2);
240 if(lua_isnoneornil(L, 3))
241 push_hit_params(L, getHitParams(groups, &tp));
243 push_hit_params(L, getHitParams(groups, &tp,
244 luaL_checknumber(L, 3)));
248 // get_password_hash(name, raw_password)
249 int ModApiUtil::l_get_password_hash(lua_State *L)
251 NO_MAP_LOCK_REQUIRED;
252 std::string name = luaL_checkstring(L, 1);
253 std::string raw_password = luaL_checkstring(L, 2);
254 std::string hash = translatePassword(name, raw_password);
255 lua_pushstring(L, hash.c_str());
260 int ModApiUtil::l_is_yes(lua_State *L)
262 NO_MAP_LOCK_REQUIRED;
264 lua_getglobal(L, "tostring"); // function to be called
265 lua_pushvalue(L, 1); // 1st argument
266 lua_call(L, 1, 1); // execute function
267 std::string str(lua_tostring(L, -1)); // get result
270 bool yes = is_yes(str);
271 lua_pushboolean(L, yes);
275 int ModApiUtil::l_get_builtin_path(lua_State *L)
277 NO_MAP_LOCK_REQUIRED;
279 std::string path = porting::path_share + DIR_DELIM + "builtin";
280 lua_pushstring(L, path.c_str());
284 // compress(data, method, level)
285 int ModApiUtil::l_compress(lua_State *L)
287 NO_MAP_LOCK_REQUIRED;
290 const char *data = luaL_checklstring(L, 1, &size);
293 if (!lua_isnone(L, 3) && !lua_isnil(L, 3))
294 level = luaL_checknumber(L, 3);
296 std::ostringstream os;
297 compressZlib(std::string(data, size), os, level);
299 std::string out = os.str();
301 lua_pushlstring(L, out.data(), out.size());
305 // decompress(data, method)
306 int ModApiUtil::l_decompress(lua_State *L)
308 NO_MAP_LOCK_REQUIRED;
311 const char *data = luaL_checklstring(L, 1, &size);
313 std::istringstream is(std::string(data, size));
314 std::ostringstream os;
315 decompressZlib(is, os);
317 std::string out = os.str();
319 lua_pushlstring(L, out.data(), out.size());
324 int ModApiUtil::l_mkdir(lua_State *L)
326 NO_MAP_LOCK_REQUIRED;
327 const char *path = luaL_checkstring(L, 1);
328 CHECK_SECURE_PATH_OPTIONAL(L, path);
329 lua_pushboolean(L, fs::CreateAllDirs(path));
333 // get_dir_list(path, is_dir)
334 int ModApiUtil::l_get_dir_list(lua_State *L)
336 NO_MAP_LOCK_REQUIRED;
337 const char *path = luaL_checkstring(L, 1);
338 short is_dir = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : -1;
340 CHECK_SECURE_PATH_OPTIONAL(L, path);
342 std::vector<fs::DirListNode> list = fs::GetDirListing(path);
347 for (size_t i = 0; i < list.size(); i++) {
348 if (is_dir == -1 || is_dir == list[i].dir) {
349 lua_pushstring(L, list[i].name.c_str());
350 lua_rawseti(L, -2, ++index);
357 int ModApiUtil::l_request_insecure_environment(lua_State *L)
359 NO_MAP_LOCK_REQUIRED;
361 // Just return _G if security is disabled
362 if (!ScriptApiSecurity::isSecure(L)) {
363 lua_getglobal(L, "_G");
367 // We have to make sure that this function is being called directly by
368 // a mod, otherwise a malicious mod could override this function and
369 // steal its return value.
371 // Make sure there's only one item below this function on the stack...
372 if (lua_getstack(L, 2, &info)) {
375 FATAL_ERROR_IF(!lua_getstack(L, 1, &info), "lua_getstack() failed");
376 FATAL_ERROR_IF(!lua_getinfo(L, "S", &info), "lua_getinfo() failed");
377 // ...and that that item is the main file scope.
378 if (strcmp(info.what, "main") != 0) {
383 lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_CURRENT_MOD_NAME);
384 if (!lua_isstring(L, -1)) {
388 // Check secure.trusted_mods
389 const char *mod_name = lua_tostring(L, -1);
390 std::string trusted_mods = g_settings->get("secure.trusted_mods");
391 trusted_mods.erase(std::remove(trusted_mods.begin(),
392 trusted_mods.end(), ' '), trusted_mods.end());
393 std::vector<std::string> mod_list = str_split(trusted_mods, ',');
394 if (std::find(mod_list.begin(), mod_list.end(), mod_name) ==
399 // Push insecure environment
400 lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_GLOBALS_BACKUP);
405 void ModApiUtil::Initialize(lua_State *L, int top)
409 API_FCT(get_us_time);
411 API_FCT(setting_set);
412 API_FCT(setting_get);
413 API_FCT(setting_setbool);
414 API_FCT(setting_getbool);
415 API_FCT(setting_save);
420 API_FCT(get_dig_params);
421 API_FCT(get_hit_params);
423 API_FCT(get_password_hash);
427 API_FCT(get_builtin_path);
433 API_FCT(get_dir_list);
435 API_FCT(request_insecure_environment);
438 void ModApiUtil::InitializeAsync(AsyncEngine& engine)
442 ASYNC_API_FCT(get_us_time);
444 //ASYNC_API_FCT(setting_set);
445 ASYNC_API_FCT(setting_get);
446 //ASYNC_API_FCT(setting_setbool);
447 ASYNC_API_FCT(setting_getbool);
448 //ASYNC_API_FCT(setting_save);
450 ASYNC_API_FCT(parse_json);
451 ASYNC_API_FCT(write_json);
453 ASYNC_API_FCT(is_yes);
455 ASYNC_API_FCT(get_builtin_path);
457 ASYNC_API_FCT(compress);
458 ASYNC_API_FCT(decompress);
460 ASYNC_API_FCT(mkdir);
461 ASYNC_API_FCT(get_dir_list);