]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/script/lua_api/l_settings.cpp
Merge branch 'master' of https://github.com/minetest/minetest
[dragonfireclient.git] / src / script / lua_api / l_settings.cpp
index 141ac61d1c766f5f03b4c3ea65701790dbc2db62..3f3fda56e6b8ab6e70705601de9274018937cb0a 100644 (file)
@@ -20,17 +20,56 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "lua_api/l_settings.h"
 #include "lua_api/l_internal.h"
 #include "cpp_api/s_security.h"
+#include "threading/mutex_auto_lock.h"
+#include "util/string.h" // FlagDesc
 #include "settings.h"
 #include "noise.h"
 #include "log.h"
 
 
-#define SET_SECURITY_CHECK(L, name) \
-       if (o->m_settings == g_settings && ScriptApiSecurity::isSecure(L) && \
-                       name.compare(0, 7, "secure.") == 0) { \
-               throw LuaError("Attempt to set secure setting."); \
+/* This protects the following from being set:
+ * 'secure.*' settings
+ * some security-relevant settings
+ *   (better solution pending)
+ * some mapgen settings
+ *   (not security-criticial, just to avoid messing up user configs)
+ */
+#define CHECK_SETTING_SECURITY(L, name) \
+       if (o->m_settings == g_settings) { \
+               if (checkSettingSecurity(L, name) == -1) \
+                       return 0; \
        }
 
+static inline int checkSettingSecurity(lua_State* L, const std::string &name)
+{
+       if (ScriptApiSecurity::isSecure(L) && name.compare(0, 7, "secure.") == 0)
+               throw LuaError("Attempted to set secure setting.");
+
+       bool is_mainmenu = false;
+#ifndef SERVER
+       is_mainmenu = ModApiBase::getGuiEngine(L) != nullptr;
+#endif
+       if (!is_mainmenu && (name == "mg_name" || name == "mg_flags")) {
+               errorstream << "Tried to set global setting " << name << ", ignoring. "
+                       "minetest.set_mapgen_setting() should be used instead." << std::endl;
+               infostream << script_get_backtrace(L) << std::endl;
+               return -1;
+       }
+
+       const char *disallowed[] = {
+               "main_menu_script", "shader_path", "texture_path", "screenshot_path",
+               "serverlist_file", "serverlist_url", "map-dir", "contentdb_url",
+       };
+       if (!is_mainmenu) {
+               for (const char *name2 : disallowed) {
+                       if (name == name2)
+                               throw LuaError("Attempted to set disallowed setting.");
+               }
+       }
+
+       return 0;
+}
+
 LuaSettings::LuaSettings(Settings *settings, const std::string &filename) :
        m_settings(settings),
        m_filename(filename)
@@ -100,7 +139,11 @@ int LuaSettings::l_get_bool(lua_State* L)
                bool value = o->m_settings->getBool(key);
                lua_pushboolean(L, value);
        } else {
-               lua_pushnil(L);
+               // Push default value
+               if (lua_isboolean(L, 3))
+                       lua_pushboolean(L, readParam<bool>(L, 3));
+               else
+                       lua_pushnil(L);
        }
 
        return 1;
@@ -124,6 +167,30 @@ int LuaSettings::l_get_np_group(lua_State *L)
        return 1;
 }
 
+// get_flags(self, key) -> table or nil
+int LuaSettings::l_get_flags(lua_State *L)
+{
+       NO_MAP_LOCK_REQUIRED;
+       LuaSettings *o = checkobject(L, 1);
+       std::string key = std::string(luaL_checkstring(L, 2));
+
+       u32 flags = 0;
+       auto flagdesc = o->m_settings->getFlagDescFallback(key);
+       if (o->m_settings->getFlagStrNoEx(key, flags, flagdesc)) {
+               lua_newtable(L);
+               int table = lua_gettop(L);
+               for (size_t i = 0; flagdesc[i].name; ++i) {
+                       lua_pushboolean(L, flags & flagdesc[i].flag);
+                       lua_setfield(L, table, flagdesc[i].name);
+               }
+               lua_pushvalue(L, table);
+       } else {
+               lua_pushnil(L);
+       }
+
+       return 1;
+}
+
 // set(self, key, value)
 int LuaSettings::l_set(lua_State* L)
 {
@@ -133,7 +200,7 @@ int LuaSettings::l_set(lua_State* L)
        std::string key = std::string(luaL_checkstring(L, 2));
        const char* value = luaL_checkstring(L, 3);
 
-       SET_SECURITY_CHECK(L, key);
+       CHECK_SETTING_SECURITY(L, key);
 
        if (!o->m_settings->set(key, value))
                throw LuaError("Invalid sequence found in setting parameters");
@@ -148,16 +215,16 @@ int LuaSettings::l_set_bool(lua_State* L)
        LuaSettings* o = checkobject(L, 1);
 
        std::string key = std::string(luaL_checkstring(L, 2));
-       bool value = lua_toboolean(L, 3);
+       bool value = readParam<bool>(L, 3);
 
-       SET_SECURITY_CHECK(L, key);
+       CHECK_SETTING_SECURITY(L, key);
 
        o->m_settings->setBool(key, value);
 
-       return 1;
+       return 0;
 }
 
-// set(self, key, value)
+// set_np_group(self, key, value)
 int LuaSettings::l_set_np_group(lua_State *L)
 {
        NO_MAP_LOCK_REQUIRED;
@@ -167,9 +234,9 @@ int LuaSettings::l_set_np_group(lua_State *L)
        NoiseParams value;
        read_noiseparams(L, 3, &value);
 
-       SET_SECURITY_CHECK(L, key);
+       CHECK_SETTING_SECURITY(L, key);
 
-       o->m_settings->setNoiseParams(key, value, false);
+       o->m_settings->setNoiseParams(key, value);
 
        return 0;
 }
@@ -182,7 +249,7 @@ int LuaSettings::l_remove(lua_State* L)
 
        std::string key = std::string(luaL_checkstring(L, 2));
 
-       SET_SECURITY_CHECK(L, key);
+       CHECK_SETTING_SECURITY(L, key);
 
        bool success = o->m_settings->remove(key);
        lua_pushboolean(L, success);
@@ -225,20 +292,36 @@ int LuaSettings::l_write(lua_State* L)
        return 1;
 }
 
-// to_table(self) -> {[key1]=value1,...}
-int LuaSettings::l_to_table(lua_State* L)
+static void push_settings_table(lua_State *L, const Settings *settings)
 {
-       NO_MAP_LOCK_REQUIRED;
-       LuaSettings* o = checkobject(L, 1);
-
-       std::vector<std::string> keys = o->m_settings->getNames();
-
+       std::vector<std::string> keys = settings->getNames();
        lua_newtable(L);
        for (const std::string &key : keys) {
-               lua_pushstring(L, o->m_settings->get(key).c_str());
+               std::string value;
+               Settings *group = nullptr;
+
+               if (settings->getNoEx(key, value)) {
+                       lua_pushstring(L, value.c_str());
+               } else if (settings->getGroupNoEx(key, group)) {
+                       // Recursively push tables
+                       push_settings_table(L, group);
+               } else {
+                       // Impossible case (multithreading) due to MutexAutoLock
+                       continue;
+               }
+
                lua_setfield(L, -2, key.c_str());
        }
+}
+
+// to_table(self) -> {[key1]=value1,...}
+int LuaSettings::l_to_table(lua_State* L)
+{
+       NO_MAP_LOCK_REQUIRED;
+       LuaSettings* o = checkobject(L, 1);
 
+       MutexAutoLock(o->m_settings->m_mutex);
+       push_settings_table(L, o->m_settings);
        return 1;
 }
 
@@ -264,7 +347,7 @@ void LuaSettings::Register(lua_State* L)
 
        lua_pop(L, 1);  // drop metatable
 
-       luaL_openlib(L, 0, methods, 0);  // fill methodtable
+       luaL_register(L, nullptr, methods);  // fill methodtable
        lua_pop(L, 1);  // drop methodtable
 
        // Can be created from Lua (Settings(filename))
@@ -301,6 +384,7 @@ const luaL_Reg LuaSettings::methods[] = {
        luamethod(LuaSettings, get),
        luamethod(LuaSettings, get_bool),
        luamethod(LuaSettings, get_np_group),
+       luamethod(LuaSettings, get_flags),
        luamethod(LuaSettings, set),
        luamethod(LuaSettings, set_bool),
        luamethod(LuaSettings, set_np_group),