LCOV - code coverage report
Current view: top level - src/script/lua_api - l_util.cpp (source / functions) Hit Total Coverage
Test: report Lines: 85 243 35.0 %
Date: 2015-07-11 18:23:49 Functions: 10 23 43.5 %

          Line data    Source code
       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 "cpp_api/s_security.h"
      28             : #include "debug.h"
      29             : #include "porting.h"
      30             : #include "log.h"
      31             : #include "tool.h"
      32             : #include "filesys.h"
      33             : #include "settings.h"
      34             : #include "util/auth.h"
      35             : #include <algorithm>
      36             : 
      37             : // debug(...)
      38             : // Writes a line to dstream
      39           0 : int ModApiUtil::l_debug(lua_State *L)
      40             : {
      41           0 :         NO_MAP_LOCK_REQUIRED;
      42             :         // Handle multiple parameters to behave like standard lua print()
      43           0 :         int n = lua_gettop(L);
      44           0 :         lua_getglobal(L, "tostring");
      45           0 :         for (int i = 1; i <= n; i++) {
      46             :                 /*
      47             :                         Call tostring(i-th argument).
      48             :                         This is what print() does, and it behaves a bit
      49             :                         differently from directly calling lua_tostring.
      50             :                 */
      51           0 :                 lua_pushvalue(L, -1);  /* function to be called */
      52           0 :                 lua_pushvalue(L, i);   /* value to print */
      53           0 :                 lua_call(L, 1, 1);
      54             :                 size_t len;
      55           0 :                 const char *s = lua_tolstring(L, -1, &len);
      56           0 :                 if (i > 1)
      57           0 :                         dstream << "\t";
      58           0 :                 if (s)
      59           0 :                         dstream << std::string(s, len);
      60           0 :                 lua_pop(L, 1);
      61             :         }
      62           0 :         dstream << std::endl;
      63           0 :         return 0;
      64             : }
      65             : 
      66             : // log([level,] text)
      67             : // Writes a line to the logger.
      68             : // The one-argument version logs to infostream.
      69             : // The two-argument version accept a log level: error, action, info, or verbose.
      70           4 : int ModApiUtil::l_log(lua_State *L)
      71             : {
      72           8 :         NO_MAP_LOCK_REQUIRED;
      73           8 :         std::string text;
      74           4 :         LogMessageLevel level = LMT_INFO;
      75           4 :         if (lua_isnone(L, 2)) {
      76           0 :                 text = lua_tostring(L, 1);
      77             :         }
      78             :         else {
      79           8 :                 std::string levelname = luaL_checkstring(L, 1);
      80           4 :                 text = luaL_checkstring(L, 2);
      81           4 :                 if(levelname == "error")
      82           0 :                         level = LMT_ERROR;
      83           4 :                 else if(levelname == "action")
      84           0 :                         level = LMT_ACTION;
      85           4 :                 else if(levelname == "verbose")
      86           0 :                         level = LMT_VERBOSE;
      87           4 :                 else if (levelname == "deprecated") {
      88           0 :                         log_deprecated(L,text);
      89           0 :                         return 0;
      90             :                 }
      91             : 
      92             :         }
      93           4 :         log_printline(level, text);
      94           4 :         return 0;
      95             : }
      96             : 
      97             : #define CHECK_SECURE_SETTING(L, name) \
      98             :         if (name.compare(0, 7, "secure.") == 0) {\
      99             :                 lua_pushliteral(L, "Attempt to set secure setting.");\
     100             :                 lua_error(L);\
     101             :         }
     102             : 
     103             : // setting_set(name, value)
     104          10 : int ModApiUtil::l_setting_set(lua_State *L)
     105             : {
     106          20 :         NO_MAP_LOCK_REQUIRED;
     107          20 :         std::string name = luaL_checkstring(L, 1);
     108          20 :         std::string value = luaL_checkstring(L, 2);
     109          10 :         CHECK_SECURE_SETTING(L, name);
     110          10 :         g_settings->set(name, value);
     111          20 :         return 0;
     112             : }
     113             : 
     114             : // setting_get(name)
     115          16 : int ModApiUtil::l_setting_get(lua_State *L)
     116             : {
     117          32 :         NO_MAP_LOCK_REQUIRED;
     118          16 :         const char *name = luaL_checkstring(L, 1);
     119             :         try{
     120          32 :                 std::string value = g_settings->get(name);
     121          15 :                 lua_pushstring(L, value.c_str());
     122           2 :         } catch(SettingNotFoundException &e){
     123           1 :                 lua_pushnil(L);
     124             :         }
     125          32 :         return 1;
     126             : }
     127             : 
     128             : // setting_setbool(name)
     129           0 : int ModApiUtil::l_setting_setbool(lua_State *L)
     130             : {
     131           0 :         NO_MAP_LOCK_REQUIRED;
     132           0 :         std::string name = luaL_checkstring(L, 1);
     133           0 :         bool value = lua_toboolean(L, 2);
     134           0 :         CHECK_SECURE_SETTING(L, name);
     135           0 :         g_settings->setBool(name, value);
     136           0 :         return 0;
     137             : }
     138             : 
     139             : // setting_getbool(name)
     140          15 : int ModApiUtil::l_setting_getbool(lua_State *L)
     141             : {
     142          30 :         NO_MAP_LOCK_REQUIRED;
     143          15 :         const char *name = luaL_checkstring(L, 1);
     144             :         try{
     145          29 :                 bool value = g_settings->getBool(name);
     146           1 :                 lua_pushboolean(L, value);
     147          28 :         } catch(SettingNotFoundException &e){
     148          14 :                 lua_pushnil(L);
     149             :         }
     150          30 :         return 1;
     151             : }
     152             : 
     153             : // setting_save()
     154           0 : int ModApiUtil::l_setting_save(lua_State *L)
     155             : {
     156           0 :         NO_MAP_LOCK_REQUIRED;
     157           0 :         if(g_settings_path != "")
     158           0 :                 g_settings->updateConfigFile(g_settings_path.c_str());
     159           0 :         return 0;
     160             : }
     161             : 
     162             : // parse_json(str[, nullvalue])
     163           0 : int ModApiUtil::l_parse_json(lua_State *L)
     164             : {
     165           0 :         NO_MAP_LOCK_REQUIRED;
     166             : 
     167           0 :         const char *jsonstr = luaL_checkstring(L, 1);
     168             : 
     169             :         // Use passed nullvalue or default to nil
     170           0 :         int nullindex = 2;
     171           0 :         if (lua_isnone(L, nullindex)) {
     172           0 :                 lua_pushnil(L);
     173           0 :                 nullindex = lua_gettop(L);
     174             :         }
     175             : 
     176           0 :         Json::Value root;
     177             : 
     178             :         {
     179           0 :                 Json::Reader reader;
     180           0 :                 std::istringstream stream(jsonstr);
     181             : 
     182           0 :                 if (!reader.parse(stream, root)) {
     183           0 :                         errorstream << "Failed to parse json data "
     184           0 :                                 << reader.getFormattedErrorMessages();
     185           0 :                         errorstream << "data: \"" << jsonstr << "\""
     186           0 :                                 << std::endl;
     187           0 :                         lua_pushnil(L);
     188           0 :                         return 1;
     189             :                 }
     190             :         }
     191             : 
     192           0 :         if (!push_json_value(L, root, nullindex)) {
     193           0 :                 errorstream << "Failed to parse json data, "
     194           0 :                         << "depth exceeds lua stack limit" << std::endl;
     195           0 :                 errorstream << "data: \"" << jsonstr << "\"" << std::endl;
     196           0 :                 lua_pushnil(L);
     197             :         }
     198           0 :         return 1;
     199             : }
     200             : 
     201             : // write_json(data[, styled]) -> string or nil and error message
     202           0 : int ModApiUtil::l_write_json(lua_State *L)
     203             : {
     204           0 :         NO_MAP_LOCK_REQUIRED;
     205             : 
     206           0 :         bool styled = false;
     207           0 :         if (!lua_isnone(L, 2)) {
     208           0 :                 styled = lua_toboolean(L, 2);
     209           0 :                 lua_pop(L, 1);
     210             :         }
     211             : 
     212           0 :         Json::Value root;
     213             :         try {
     214           0 :                 read_json_value(L, root, 1);
     215           0 :         } catch (SerializationError &e) {
     216           0 :                 lua_pushnil(L);
     217           0 :                 lua_pushstring(L, e.what());
     218           0 :                 return 2;
     219             :         }
     220             : 
     221           0 :         std::string out;
     222           0 :         if (styled) {
     223           0 :                 Json::StyledWriter writer;
     224           0 :                 out = writer.write(root);
     225             :         } else {
     226           0 :                 Json::FastWriter writer;
     227           0 :                 out = writer.write(root);
     228             :         }
     229           0 :         lua_pushlstring(L, out.c_str(), out.size());
     230           0 :         return 1;
     231             : }
     232             : 
     233             : // get_dig_params(groups, tool_capabilities[, time_from_last_punch])
     234           0 : int ModApiUtil::l_get_dig_params(lua_State *L)
     235             : {
     236           0 :         NO_MAP_LOCK_REQUIRED;
     237           0 :         std::map<std::string, int> groups;
     238           0 :         read_groups(L, 1, groups);
     239           0 :         ToolCapabilities tp = read_tool_capabilities(L, 2);
     240           0 :         if(lua_isnoneornil(L, 3))
     241           0 :                 push_dig_params(L, getDigParams(groups, &tp));
     242             :         else
     243           0 :                 push_dig_params(L, getDigParams(groups, &tp,
     244           0 :                                         luaL_checknumber(L, 3)));
     245           0 :         return 1;
     246             : }
     247             : 
     248             : // get_hit_params(groups, tool_capabilities[, time_from_last_punch])
     249           0 : int ModApiUtil::l_get_hit_params(lua_State *L)
     250             : {
     251           0 :         NO_MAP_LOCK_REQUIRED;
     252           0 :         std::map<std::string, int> groups;
     253           0 :         read_groups(L, 1, groups);
     254           0 :         ToolCapabilities tp = read_tool_capabilities(L, 2);
     255           0 :         if(lua_isnoneornil(L, 3))
     256           0 :                 push_hit_params(L, getHitParams(groups, &tp));
     257             :         else
     258           0 :                 push_hit_params(L, getHitParams(groups, &tp,
     259           0 :                                         luaL_checknumber(L, 3)));
     260           0 :         return 1;
     261             : }
     262             : 
     263             : // get_password_hash(name, raw_password)
     264           0 : int ModApiUtil::l_get_password_hash(lua_State *L)
     265             : {
     266           0 :         NO_MAP_LOCK_REQUIRED;
     267           0 :         std::string name = luaL_checkstring(L, 1);
     268           0 :         std::string raw_password = luaL_checkstring(L, 2);
     269           0 :         std::string hash = translatePassword(name, raw_password);
     270           0 :         lua_pushstring(L, hash.c_str());
     271           0 :         return 1;
     272             : }
     273             : 
     274             : // is_yes(arg)
     275           4 : int ModApiUtil::l_is_yes(lua_State *L)
     276             : {
     277           8 :         NO_MAP_LOCK_REQUIRED;
     278             : 
     279           4 :         lua_getglobal(L, "tostring"); // function to be called
     280           4 :         lua_pushvalue(L, 1); // 1st argument
     281           4 :         lua_call(L, 1, 1); // execute function
     282           8 :         std::string str(lua_tostring(L, -1)); // get result
     283           4 :         lua_pop(L, 1);
     284             : 
     285           4 :         bool yes = is_yes(str);
     286           4 :         lua_pushboolean(L, yes);
     287           8 :         return 1;
     288             : }
     289             : 
     290           6 : int ModApiUtil::l_get_builtin_path(lua_State *L)
     291             : {
     292          12 :         std::string path = porting::path_share + DIR_DELIM + "builtin";
     293           6 :         lua_pushstring(L, path.c_str());
     294          12 :         return 1;
     295             : }
     296             : 
     297             : // compress(data, method, level)
     298           0 : int ModApiUtil::l_compress(lua_State *L)
     299             : {
     300             :         size_t size;
     301           0 :         const char *data = luaL_checklstring(L, 1, &size);
     302             : 
     303           0 :         int level = -1;
     304           0 :         if (!lua_isnone(L, 3) && !lua_isnil(L, 3))
     305           0 :                 level = luaL_checknumber(L, 3);
     306             : 
     307           0 :         std::ostringstream os;
     308           0 :         compressZlib(std::string(data, size), os, level);
     309             : 
     310           0 :         std::string out = os.str();
     311             : 
     312           0 :         lua_pushlstring(L, out.data(), out.size());
     313           0 :         return 1;
     314             : }
     315             : 
     316             : // decompress(data, method)
     317           0 : int ModApiUtil::l_decompress(lua_State *L)
     318             : {
     319             :         size_t size;
     320           0 :         const char *data = luaL_checklstring(L, 1, &size);
     321             : 
     322           0 :         std::istringstream is(std::string(data, size));
     323           0 :         std::ostringstream os;
     324           0 :         decompressZlib(is, os);
     325             : 
     326           0 :         std::string out = os.str();
     327             : 
     328           0 :         lua_pushlstring(L, out.data(), out.size());
     329           0 :         return 1;
     330             : }
     331             : 
     332             : // mkdir(path)
     333           0 : int ModApiUtil::l_mkdir(lua_State *L)
     334             : {
     335           0 :         NO_MAP_LOCK_REQUIRED;
     336           0 :         const char *path = luaL_checkstring(L, 1);
     337           0 :         CHECK_SECURE_PATH_OPTIONAL(L, path);
     338           0 :         lua_pushboolean(L, fs::CreateAllDirs(path));
     339           0 :         return 1;
     340             : }
     341             : 
     342             : // get_dir_list(path, is_dir)
     343           0 : int ModApiUtil::l_get_dir_list(lua_State *L)
     344             : {
     345           0 :         NO_MAP_LOCK_REQUIRED;
     346           0 :         const char *path = luaL_checkstring(L, 1);
     347           0 :         short is_dir = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : -1;
     348             : 
     349           0 :         CHECK_SECURE_PATH_OPTIONAL(L, path);
     350             : 
     351           0 :         std::vector<fs::DirListNode> list = fs::GetDirListing(path);
     352             : 
     353           0 :         int index = 0;
     354           0 :         lua_newtable(L);
     355             : 
     356           0 :         for (size_t i = 0; i < list.size(); i++) {
     357           0 :                 if (is_dir == -1 || is_dir == list[i].dir) {
     358           0 :                         lua_pushstring(L, list[i].name.c_str());
     359           0 :                         lua_rawseti(L, -2, ++index);
     360             :                 }
     361             :         }
     362             : 
     363           0 :         return 1;
     364             : }
     365             : 
     366           0 : int ModApiUtil::l_request_insecure_environment(lua_State *L)
     367             : {
     368           0 :         NO_MAP_LOCK_REQUIRED;
     369           0 :         if (!ScriptApiSecurity::isSecure(L)) {
     370           0 :                 lua_getglobal(L, "_G");
     371           0 :                 return 1;
     372             :         }
     373           0 :         lua_getfield(L, LUA_REGISTRYINDEX, SCRIPT_MOD_NAME_FIELD);
     374           0 :         if (!lua_isstring(L, -1)) {
     375           0 :                 lua_pushnil(L);
     376           0 :                 return 1;
     377             :         }
     378           0 :         const char *mod_name = lua_tostring(L, -1);
     379           0 :         std::string trusted_mods = g_settings->get("secure.trusted_mods");
     380           0 :         std::vector<std::string> mod_list = str_split(trusted_mods, ',');
     381           0 :         if (std::find(mod_list.begin(), mod_list.end(), mod_name) == mod_list.end()) {
     382           0 :                 lua_pushnil(L);
     383           0 :                 return 1;
     384             :         }
     385           0 :         lua_getfield(L, LUA_REGISTRYINDEX, "globals_backup");
     386           0 :         return 1;
     387             : }
     388             : 
     389             : 
     390           1 : void ModApiUtil::Initialize(lua_State *L, int top)
     391             : {
     392           1 :         API_FCT(debug);
     393           1 :         API_FCT(log);
     394             : 
     395           1 :         API_FCT(setting_set);
     396           1 :         API_FCT(setting_get);
     397           1 :         API_FCT(setting_setbool);
     398           1 :         API_FCT(setting_getbool);
     399           1 :         API_FCT(setting_save);
     400             : 
     401           1 :         API_FCT(parse_json);
     402           1 :         API_FCT(write_json);
     403             : 
     404           1 :         API_FCT(get_dig_params);
     405           1 :         API_FCT(get_hit_params);
     406             : 
     407           1 :         API_FCT(get_password_hash);
     408             : 
     409           1 :         API_FCT(is_yes);
     410             : 
     411           1 :         API_FCT(get_builtin_path);
     412             : 
     413           1 :         API_FCT(compress);
     414           1 :         API_FCT(decompress);
     415             : 
     416           1 :         API_FCT(mkdir);
     417           1 :         API_FCT(get_dir_list);
     418             : 
     419           1 :         API_FCT(request_insecure_environment);
     420           1 : }
     421             : 
     422           1 : void ModApiUtil::InitializeAsync(AsyncEngine& engine)
     423             : {
     424           1 :         ASYNC_API_FCT(debug);
     425           1 :         ASYNC_API_FCT(log);
     426             : 
     427             :         //ASYNC_API_FCT(setting_set);
     428           1 :         ASYNC_API_FCT(setting_get);
     429             :         //ASYNC_API_FCT(setting_setbool);
     430           1 :         ASYNC_API_FCT(setting_getbool);
     431             :         //ASYNC_API_FCT(setting_save);
     432             : 
     433           1 :         ASYNC_API_FCT(parse_json);
     434           1 :         ASYNC_API_FCT(write_json);
     435             : 
     436           1 :         ASYNC_API_FCT(is_yes);
     437             : 
     438           1 :         ASYNC_API_FCT(get_builtin_path);
     439             : 
     440           1 :         ASYNC_API_FCT(compress);
     441           1 :         ASYNC_API_FCT(decompress);
     442             : 
     443           1 :         ASYNC_API_FCT(mkdir);
     444           1 :         ASYNC_API_FCT(get_dir_list);
     445           4 : }
     446             : 

Generated by: LCOV version 1.11