diff --git a/CMakeLists.txt b/CMakeLists.txt index 40a19ae90..cd8c385ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,9 @@ endif() set(CUSTOM_DOCDIR "" CACHE STRING "Directory to install documentation into") if(NOT CUSTOM_DOCDIR STREQUAL "") set(DOCDIR "${CUSTOM_DOCDIR}") + if(NOT RUN_IN_PLACE) + set(EXAMPLE_CONF_DIR ${DOCDIR}) + endif() message(STATUS "Using DOCDIR=${DOCDIR}") endif() diff --git a/builtin/game/falling.lua b/builtin/game/falling.lua index 5b5e806f5..6282f6558 100644 --- a/builtin/game/falling.lua +++ b/builtin/game/falling.lua @@ -6,42 +6,46 @@ core.register_entity(":__builtin:falling_node", { initial_properties = { - physical = true, - collide_with_objects = false, - collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5}, visual = "wielditem", + visual_size = {x = 0.667, y = 0.667}, textures = {}, - visual_size = {x=0.667, y=0.667}, + physical = true, + is_visible = false, + collide_with_objects = false, + collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, }, node = {}, set_node = function(self, node) self.node = node - local prop = { + self.object:set_properties({ is_visible = true, textures = {node.name}, - } - self.object:set_properties(prop) + }) end, get_staticdata = function(self) - return self.node.name + return core.serialize(self.node) end, on_activate = function(self, staticdata) - self.object:set_armor_groups({immortal=1}) - if staticdata then - self:set_node({name=staticdata}) + -- Set gravity + self.object:setacceleration({x = 0, y = -10, z = 0}) + self.object:set_armor_groups({immortal = 1}) + + local node = core.deserialize(staticdata) + if node then + self:set_node(node) + elseif staticdata ~= "" then + self:set_node({name = staticdata}) end end, on_step = function(self, dtime) - -- Set gravity - self.object:setacceleration({x=0, y=-10, z=0}) -- Turn to actual sand when collides to ground or just move local pos = self.object:getpos() - local bcp = {x=pos.x, y=pos.y-0.7, z=pos.z} -- Position of bottom center point + local bcp = {x = pos.x, y = pos.y - 0.7, z = pos.z} -- Position of bottom center point local bcn = core.get_node(bcp) local bcd = core.registered_nodes[bcn.name] -- Note: walkable is in the node definition, not in item groups @@ -52,7 +56,7 @@ core.register_entity(":__builtin:falling_node", { if bcd and bcd.leveled and bcn.name == self.node.name then local addlevel = self.node.level - if addlevel == nil or addlevel <= 0 then + if not addlevel or addlevel <= 0 then addlevel = bcd.leveled end if core.add_node_level(bcp, addlevel) == 0 then @@ -65,7 +69,7 @@ core.register_entity(":__builtin:falling_node", { core.remove_node(bcp) return end - local np = {x=bcp.x, y=bcp.y+1, z=bcp.z} + local np = {x = bcp.x, y = bcp.y + 1, z = bcp.z} -- Check what's here local n2 = core.get_node(np) -- If it's not air or liquid, remove node and replace it with @@ -76,15 +80,13 @@ core.register_entity(":__builtin:falling_node", { if core.registered_nodes[n2.name].buildable_to == false then -- Add dropped items local drops = core.get_node_drops(n2.name, "") - local _, dropped_item for _, dropped_item in ipairs(drops) do core.add_item(np, dropped_item) end end -- Run script hook - local _, callback for _, callback in ipairs(core.registered_on_dignodes) do - callback(np, n2, nil) + callback(np, n2) end end -- Create node and remove entity @@ -94,7 +96,7 @@ core.register_entity(":__builtin:falling_node", { return end local vel = self.object:getvelocity() - if vector.equals(vel, {x=0,y=0,z=0}) then + if vector.equals(vel, {x = 0, y = 0, z = 0}) then local npos = self.object:getpos() self.object:setpos(vector.round(npos)) end @@ -109,7 +111,7 @@ end function drop_attached_node(p) local nn = core.get_node(p).name core.remove_node(p) - for _,item in ipairs(core.get_node_drops(nn, "")) do + for _, item in ipairs(core.get_node_drops(nn, "")) do local pos = { x = p.x + math.random()/2 - 0.25, y = p.y + math.random()/2 - 0.25, @@ -121,25 +123,13 @@ end function check_attached_node(p, n) local def = core.registered_nodes[n.name] - local d = {x=0, y=0, z=0} + local d = {x = 0, y = 0, z = 0} if def.paramtype2 == "wallmounted" then - if n.param2 == 0 then - d.y = 1 - elseif n.param2 == 1 then - d.y = -1 - elseif n.param2 == 2 then - d.x = 1 - elseif n.param2 == 3 then - d.x = -1 - elseif n.param2 == 4 then - d.z = 1 - elseif n.param2 == 5 then - d.z = -1 - end + d = core.wallmounted_to_dir(n.param2) else d.y = -1 end - local p2 = {x=p.x+d.x, y=p.y+d.y, z=p.z+d.z} + local p2 = vector.add(p, d) local nn = core.get_node(p2).name local def2 = core.registered_nodes[nn] if def2 and not def2.walkable then @@ -155,7 +145,7 @@ end function nodeupdate_single(p, delay) local n = core.get_node(p) if core.get_item_group(n.name, "falling_node") ~= 0 then - local p_bottom = {x=p.x, y=p.y-1, z=p.z} + local p_bottom = {x = p.x, y = p.y - 1, z = p.z} local n_bottom = core.get_node(p_bottom) -- Note: walkable is in the node definition, not in item groups if core.registered_nodes[n_bottom.name] and @@ -166,7 +156,7 @@ function nodeupdate_single(p, delay) (not core.registered_nodes[n_bottom.name].walkable or core.registered_nodes[n_bottom.name].buildable_to) then if delay then - core.after(0.1, nodeupdate_single, {x=p.x, y=p.y, z=p.z}, false) + core.after(0.1, nodeupdate_single, p, false) else n.level = core.get_node_level(p) core.remove_node(p) @@ -186,14 +176,13 @@ end function nodeupdate(p, delay) -- Round p to prevent falling entities to get stuck - p.x = math.floor(p.x+0.5) - p.y = math.floor(p.y+0.5) - p.z = math.floor(p.z+0.5) + p = vector.round(p) - for x = -1,1 do - for y = -1,1 do - for z = -1,1 do - nodeupdate_single({x=p.x+x, y=p.y+y, z=p.z+z}, delay or not (x==0 and y==0 and z==0)) + for x = -1, 1 do + for y = -1, 1 do + for z = -1, 1 do + local d = vector.new(x, y, z) + nodeupdate_single(vector.add(p, d), delay or not (x == 0 and y == 0 and z == 0)) end end end diff --git a/builtin/mainmenu/common.lua b/builtin/mainmenu/common.lua index b44f3cacc..ec01388bd 100644 --- a/builtin/mainmenu/common.lua +++ b/builtin/mainmenu/common.lua @@ -22,9 +22,14 @@ menudata = {} -------------------------------------------------------------------------------- -- Local cached values -------------------------------------------------------------------------------- -local min_supp_proto = core.get_min_supp_proto() -local max_supp_proto = core.get_max_supp_proto() +local min_supp_proto +local max_supp_proto +function common_update_cached_supp_proto() + min_supp_proto = core.get_min_supp_proto() + max_supp_proto = core.get_max_supp_proto() +end +common_update_cached_supp_proto() -------------------------------------------------------------------------------- -- Menu helper functions -------------------------------------------------------------------------------- @@ -105,7 +110,7 @@ function render_favorite(spec,render_details) end local details = "" - local grey_out = not is_server_protocol_compat(spec.proto_max, spec.proto_min) + local grey_out = not is_server_protocol_compat(spec.proto_min, spec.proto_max) if spec.clients ~= nil and spec.clients_max ~= nil then local clients_color = '' diff --git a/builtin/mainmenu/tab_multiplayer.lua b/builtin/mainmenu/tab_multiplayer.lua index 6b131b8f4..e2f3fee47 100644 --- a/builtin/mainmenu/tab_multiplayer.lua +++ b/builtin/mainmenu/tab_multiplayer.lua @@ -24,6 +24,10 @@ local function get_formspec(tabview, name, tabdata) minetest.set_background("background",minetest.formspec_escape(mm_texture.basetexturedir)..'background.jpg') --minetest.set_background("header",minetest.formspec_escape(mm_texture.basetexturedir)..'header.png') + -- Update the cached supported proto info, + -- it may have changed after a change by the settings menu. + common_update_cached_supp_proto() + local render_details = core.is_yes(core.setting_getbool("public_serverlist")) local retval = diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index fc95f15ae..81554bf21 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -232,6 +232,12 @@ address (Server address) string # Note that the port field in the main menu overrides this setting. remote_port (Remote port) int 30000 1 65535 +# Whether to support older servers before protocol version 25. +# Enable if you want to connect to 0.4.12 servers and before. +# Servers starting with 0.4.13 will work, 0.4.12-dev servers may work. +# Disabling this option will protect your password better. +send_pre_v25_init (Support older servers) bool true + # Save the map received by the client on disk. enable_local_map_saving (Saving map received from server) bool false @@ -788,6 +794,15 @@ sqlite_synchronous (Synchronous SQLite) enum 2 0,1,2 # Length of a server tick and the interval at which objects are generally updated over network. dedicated_server_step (Dedicated server step) float 0.1 +# Time in between active block management cycles +active_block_mgmt_interval (Active Block Management interval) float 2.0 + +# Length of time between ABM execution cycles +abm_interval (Active Block Modifier interval) float 1.0 + +# Length of time between NodeTimer execution cycles +nodetimer_interval (NodeTimer interval) float 1.0 + # If enabled, invalid world data won't cause the server to shut down. # Only enable this if you know what you are doing. ignore_world_load_errors (Ignore world errors) bool false diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 2a93b83c8..1463c659b 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1688,16 +1688,15 @@ or string form, a ColorString (defined above): `colorspec = "green"` Spatial Vectors --------------- - -* `vector.new([x[, y, z]])`: returns a vector. - * `x` is a table or the `x` position. - +--------------- +* `vector.new(a[, b, c])`: returns a vector: + * A copy of `a` if `a` is a vector. + * `{x = a, y = b, z = c}`, if all `a, b, c` are defined * `vector.direction(p1, p2)`: returns a vector * `vector.distance(p1, p2)`: returns a number * `vector.length(v)`: returns a number * `vector.normalize(v)`: returns a vector -* `vector.round(v)`: returns a vector +* `vector.round(v)`: returns a vector, each dimension rounded to floor * `vector.apply(v, func)`: returns a vector * `vector.equals(v1, v2)`: returns a boolean @@ -1709,7 +1708,7 @@ For the following functions `x` can be either a vector or a number: * `vector.divide(v, x)`: returns a scaled vector or Schur quotient Helper functions ------------------ +---------------- * `dump2(obj, name="_", dumped={})` * Return object serialized as a string, handles reference loops * `dump(obj, dumped={})` diff --git a/multicraft.conf.example b/multicraft.conf.example index 6d62440bf..bc1791c00 100644 --- a/multicraft.conf.example +++ b/multicraft.conf.example @@ -242,6 +242,13 @@ # type: int min: 1 max: 65535 # remote_port = 30000 +# Whether to support older servers before protocol version 25. +# Enable if you want to connect to 0.4.12 servers and before. +# Servers starting with 0.4.13 will work, 0.4.12-dev servers may work. +# Disabling this option will protect your password better. +# type: bool +# send_pre_v25_init = true + # Save the map received by the client on disk. # type: bool # enable_local_map_saving = false @@ -972,6 +979,18 @@ # type: float # dedicated_server_step = 0.1 +# Length of time between Active Block Management execution cycles +# type: float +# active_block_mgmt_interval = 2.0 + +# Length of time between ABM execution cycles +# type: float +# abm_interval = 1.0 + +# Length of time between NodeTimer execution cycles +# type: float +# nodetimer_interval = 1.0 + # If enabled, invalid world data won't cause the server to shut down. # Only enable this if you know what you are doing. # type: bool diff --git a/src/ban.cpp b/src/ban.cpp index feb692e6d..f85477e22 100644 --- a/src/ban.cpp +++ b/src/ban.cpp @@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "threading/mutex_auto_lock.h" #include #include -#include "strfnd.h" +#include "util/strfnd.h" #include "util/string.h" #include "log.h" #include "filesys.h" diff --git a/src/chat.cpp b/src/chat.cpp index 6d441b389..454090b1f 100644 --- a/src/chat.cpp +++ b/src/chat.cpp @@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "chat.h" #include "debug.h" -#include "strfnd.h" +#include "util/strfnd.h" #include #include #include "util/string.h" @@ -679,9 +679,12 @@ ChatBackend::~ChatBackend() void ChatBackend::addMessage(std::wstring name, std::wstring text) { + name = removeChatEscapes(name); + text = removeChatEscapes(text); + // Note: A message may consist of multiple lines, for example the MOTD. WStrfnd fnd(text); - while (!fnd.atend()) + while (!fnd.at_end()) { std::wstring line = fnd.next(L"\n"); m_console_buffer.addLine(name, line); diff --git a/src/client.cpp b/src/client.cpp index e9d7ea68b..67c16c929 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -386,25 +386,30 @@ void Client::step(float dtime) Player *myplayer = m_env.getLocalPlayer(); FATAL_ERROR_IF(myplayer == NULL, "Local player not found in environment."); - // Send TOSERVER_INIT_LEGACY - // [0] u16 TOSERVER_INIT_LEGACY - // [2] u8 SER_FMT_VER_HIGHEST_READ - // [3] u8[20] player_name - // [23] u8[28] password (new in some version) - // [51] u16 minimum supported network protocol version (added sometime) - // [53] u16 maximum supported network protocol version (added later than the previous one) + u16 proto_version_min = g_settings->getFlag("send_pre_v25_init") ? + CLIENT_PROTOCOL_VERSION_MIN_LEGACY : CLIENT_PROTOCOL_VERSION_MIN; - char pName[PLAYERNAME_SIZE]; - char pPassword[PASSWORD_SIZE]; - memset(pName, 0, PLAYERNAME_SIZE * sizeof(char)); - memset(pPassword, 0, PASSWORD_SIZE * sizeof(char)); + if (proto_version_min < 25) { + // Send TOSERVER_INIT_LEGACY + // [0] u16 TOSERVER_INIT_LEGACY + // [2] u8 SER_FMT_VER_HIGHEST_READ + // [3] u8[20] player_name + // [23] u8[28] password (new in some version) + // [51] u16 minimum supported network protocol version (added sometime) + // [53] u16 maximum supported network protocol version (added later than the previous one) - std::string hashed_password = translatePassword(myplayer->getName(), m_password); - snprintf(pName, PLAYERNAME_SIZE, "%s", myplayer->getName()); - snprintf(pPassword, PASSWORD_SIZE, "%s", hashed_password.c_str()); + char pName[PLAYERNAME_SIZE]; + char pPassword[PASSWORD_SIZE]; + memset(pName, 0, PLAYERNAME_SIZE * sizeof(char)); + memset(pPassword, 0, PASSWORD_SIZE * sizeof(char)); - sendLegacyInit(pName, pPassword); - if (LATEST_PROTOCOL_VERSION >= 25) + std::string hashed_password = translate_password(myplayer->getName(), m_password); + snprintf(pName, PLAYERNAME_SIZE, "%s", myplayer->getName()); + snprintf(pPassword, PASSWORD_SIZE, "%s", hashed_password.c_str()); + + sendLegacyInit(pName, pPassword); + } + if (CLIENT_PROTOCOL_VERSION_MAX >= 25) sendInit(myplayer->getName()); } @@ -1003,10 +1008,13 @@ void Client::sendLegacyInit(const char* playerName, const char* playerPassword) NetworkPacket pkt(TOSERVER_INIT_LEGACY, 1 + PLAYERNAME_SIZE + PASSWORD_SIZE + 2 + 2); + u16 proto_version_min = g_settings->getFlag("send_pre_v25_init") ? + CLIENT_PROTOCOL_VERSION_MIN_LEGACY : CLIENT_PROTOCOL_VERSION_MIN; + pkt << (u8) SER_FMT_VER_HIGHEST_READ; pkt.putRawString(playerName,PLAYERNAME_SIZE); pkt.putRawString(playerPassword, PASSWORD_SIZE); - pkt << (u16) CLIENT_PROTOCOL_VERSION_MIN << (u16) CLIENT_PROTOCOL_VERSION_MAX; + pkt << (u16) proto_version_min << (u16) CLIENT_PROTOCOL_VERSION_MAX; Send(&pkt); } @@ -1017,8 +1025,12 @@ void Client::sendInit(const std::string &playerName) // we don't support network compression yet u16 supp_comp_modes = NETPROTO_COMPRESSION_NONE; + + u16 proto_version_min = g_settings->getFlag("send_pre_v25_init") ? + CLIENT_PROTOCOL_VERSION_MIN_LEGACY : CLIENT_PROTOCOL_VERSION_MIN; + pkt << (u8) SER_FMT_VER_HIGHEST_READ << (u16) supp_comp_modes; - pkt << (u16) CLIENT_PROTOCOL_VERSION_MIN << (u16) CLIENT_PROTOCOL_VERSION_MAX; + pkt << (u16) proto_version_min << (u16) CLIENT_PROTOCOL_VERSION_MAX; pkt << playerName; Send(&pkt); @@ -1031,18 +1043,14 @@ void Client::startAuth(AuthMechanism chosen_auth_mechanism) switch (chosen_auth_mechanism) { case AUTH_MECHANISM_FIRST_SRP: { // send srp verifier to server + std::string verifier; + std::string salt; + generate_srp_verifier_and_salt(getPlayerName(), m_password, + &verifier, &salt); + NetworkPacket resp_pkt(TOSERVER_FIRST_SRP, 0); - char *salt, *bytes_v; - std::size_t len_salt, len_v; - salt = NULL; - getSRPVerifier(getPlayerName(), m_password, - &salt, &len_salt, &bytes_v, &len_v); - resp_pkt - << std::string((char*)salt, len_salt) - << std::string((char*)bytes_v, len_v) - << (u8)((m_password == "") ? 1 : 0); - free(salt); - free(bytes_v); + resp_pkt << salt << verifier << (u8)((m_password == "") ? 1 : 0); + Send(&resp_pkt); break; } @@ -1051,7 +1059,7 @@ void Client::startAuth(AuthMechanism chosen_auth_mechanism) u8 based_on = 1; if (chosen_auth_mechanism == AUTH_MECHANISM_LEGACY_PASSWORD) { - m_password = translatePassword(getPlayerName(), m_password); + m_password = translate_password(getPlayerName(), m_password); based_on = 0; } @@ -1197,8 +1205,8 @@ void Client::sendChangePassword(const std::string &oldpassword, m_new_password = newpassword; startAuth(choseAuthMech(m_sudo_auth_methods)); } else { - std::string oldpwd = translatePassword(playername, oldpassword); - std::string newpwd = translatePassword(playername, newpassword); + std::string oldpwd = translate_password(playername, oldpassword); + std::string newpwd = translate_password(playername, newpassword); NetworkPacket pkt(TOSERVER_PASSWORD_LEGACY, 2 * PASSWORD_SIZE); diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index 43ceac977..29360907a 100644 --- a/src/client/clientlauncher.cpp +++ b/src/client/clientlauncher.cpp @@ -201,6 +201,9 @@ bool ClientLauncher::run(GameParams &game_params, const Settings &cmd_args) bool game_has_run = launch_game(error_message, reconnect_requested, game_params, cmd_args); + // Reset the reconnect_requested flag + reconnect_requested = false; + // If skip_main_menu, we only want to startup once if (skip_main_menu && !first_loop) break; @@ -336,6 +339,7 @@ bool ClientLauncher::launch_game(std::string &error_message, MainMenuData menudata; menudata.address = address; menudata.name = playername; + menudata.password = password; menudata.port = itos(game_params.socket_port); menudata.script_data.errormessage = error_message; menudata.script_data.reconnect_requested = reconnect_requested; diff --git a/src/client/tile.cpp b/src/client/tile.cpp index 6d43ea524..8c757d1dd 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -31,7 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mesh.h" #include "log.h" #include "gamedef.h" -#include "strfnd.h" +#include "util/strfnd.h" #include "util/string.h" // for parseColorString() #include "imagefilters.h" #include "guiscalingfilter.h" @@ -1246,7 +1246,7 @@ bool TextureSource::generateImagePart(std::string part_of_name, baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); baseimg->fill(video::SColor(0,0,0,0)); } - while (sf.atend() == false) { + while (sf.at_end() == false) { u32 x = stoi(sf.next(",")); u32 y = stoi(sf.next("=")); std::string filename = sf.next(":"); diff --git a/src/craftdef.cpp b/src/craftdef.cpp index b67eec863..5019a66ff 100644 --- a/src/craftdef.cpp +++ b/src/craftdef.cpp @@ -29,7 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/serialize.h" #include "util/string.h" #include "util/numeric.h" -#include "strfnd.h" +#include "util/strfnd.h" #include "exceptions.h" inline bool isGroupRecipeStr(const std::string &rec_name) @@ -90,7 +90,7 @@ static bool inputItemMatchesRecipe(const std::string &inp_name, all_groups_match = false; break; } - } while (!f.atend()); + } while (!f.at_end()); if (all_groups_match) return true; } diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index d6a40a5df..98c2d643f 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -185,6 +185,8 @@ void set_default_settings(Settings *settings) settings->setDefault("minimap_shape_round", "true"); settings->setDefault("minimap_double_scan_height", "false"); + settings->setDefault("send_pre_v25_init", "true"); + settings->setDefault("curl_timeout", "5000"); settings->setDefault("curl_parallel_limit", "8"); settings->setDefault("curl_file_download_timeout", "300000"); @@ -279,6 +281,9 @@ void set_default_settings(Settings *settings) settings->setDefault("sqlite_synchronous", "2"); settings->setDefault("full_block_send_enable_min_time_from_building", "2.0"); settings->setDefault("dedicated_server_step", "0.1"); + settings->setDefault("active_block_mgmt_interval", "2.0"); + settings->setDefault("abm_interval", "1.0"); + settings->setDefault("nodetimer_interval", "1.0"); settings->setDefault("ignore_world_load_errors", "false"); settings->setDefault("remote_media", ""); settings->setDefault("debug_log_level", "action"); diff --git a/src/environment.cpp b/src/environment.cpp index 3031b6319..736a89caf 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -59,6 +59,9 @@ Environment::Environment(): m_day_night_ratio_override(0.0f) { m_cache_enable_shaders = g_settings->getBool("enable_shaders"); + m_cache_active_block_mgmt_interval = g_settings->getFloat("active_block_mgmt_interval"); + m_cache_abm_interval = g_settings->getFloat("abm_interval"); + m_cache_nodetimer_interval = g_settings->getFloat("nodetimer_interval"); } Environment::~Environment() @@ -1322,9 +1325,8 @@ void ServerEnvironment::step(float dtime) /* Manage active block list */ - if(m_active_blocks_management_interval.step(dtime, 2.0)) - { - ScopeProfiler sp(g_profiler, "SEnv: manage act. block list avg /2s", SPT_AVG); + if (m_active_blocks_management_interval.step(dtime, m_cache_active_block_mgmt_interval)) { + ScopeProfiler sp(g_profiler, "SEnv: manage act. block list avg per interval", SPT_AVG); /* Get player block positions */ @@ -1399,12 +1401,10 @@ void ServerEnvironment::step(float dtime) /* Mess around in active blocks */ - const float abm_interval = 1.0; - if(m_active_blocks_nodemetadata_interval.step(dtime, 1.0)) - { - ScopeProfiler sp(g_profiler, "SEnv: mess in act. blocks avg /1s", SPT_AVG); + if (m_active_blocks_nodemetadata_interval.step(dtime, m_cache_nodetimer_interval)) { + ScopeProfiler sp(g_profiler, "SEnv: mess in act. blocks avg per interval", SPT_AVG); - float dtime = 1.0; + float dtime = m_cache_nodetimer_interval; // Initialize handling of ActiveBlockModifiers ABMHandler abmhandler(m_abms, abm_interval, this, true); @@ -1453,6 +1453,52 @@ void ServerEnvironment::step(float dtime) } } +<<<<<<< HEAD +======= + if (m_active_block_modifier_interval.step(dtime, m_cache_abm_interval)) + do{ // breakable + if(m_active_block_interval_overload_skip > 0){ + ScopeProfiler sp(g_profiler, "SEnv: ABM overload skips"); + m_active_block_interval_overload_skip--; + break; + } + ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg per interval", SPT_AVG); + TimeTaker timer("modify in active blocks per interval"); + + // Initialize handling of ActiveBlockModifiers + ABMHandler abmhandler(m_abms, m_cache_abm_interval, this, true); + + for(std::set::iterator + i = m_active_blocks.m_list.begin(); + i != m_active_blocks.m_list.end(); ++i) + { + v3s16 p = *i; + + /*infostream<<"Server: Block ("<getBlockNoCreateNoEx(p); + if(block == NULL) + continue; + + // Set current time as timestamp + block->setTimestampNoChangedFlag(m_game_time); + + /* Handle ActiveBlockModifiers */ + abmhandler.apply(block); + } + + u32 time_ms = timer.stop(true); + u32 max_time_ms = 200; + if(time_ms > max_time_ms){ + warningstream<<"active block modifiers took " + <>>>>>> upstream1/master /* Step script environment (run global on_step()) */ diff --git a/src/environment.h b/src/environment.h index 8cb51fef8..17d8b7273 100644 --- a/src/environment.h +++ b/src/environment.h @@ -136,6 +136,9 @@ protected: * a later release. */ bool m_cache_enable_shaders; + float m_cache_active_block_mgmt_interval; + float m_cache_abm_interval; + float m_cache_nodetimer_interval; private: Mutex m_time_lock; diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 64ec218da..e9e231743 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "constants.h" #include "gamedef.h" #include "keycode.h" -#include "strfnd.h" +#include "util/strfnd.h" #include #include #include diff --git a/src/inventory.cpp b/src/inventory.cpp index e59234f65..3646b96df 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "log.h" #include "itemdef.h" -#include "strfnd.h" +#include "util/strfnd.h" #include "content_mapnode.h" // For loading legacy MaterialItems #include "nameidmapping.h" // For loading legacy MaterialItems #include "util/serialize.h" @@ -218,7 +218,7 @@ void ItemStack::deSerialize(std::istream &is, IItemDefManager *itemdef) Strfnd fnd(all); fnd.next("\""); // If didn't skip to end, we have ""s - if(!fnd.atend()){ + if(!fnd.at_end()){ name = fnd.next("\""); } else { // No luck, just read a word then fnd.start(all); @@ -246,7 +246,7 @@ void ItemStack::deSerialize(std::istream &is, IItemDefManager *itemdef) Strfnd fnd(all); fnd.next("\""); // If didn't skip to end, we have ""s - if(!fnd.atend()){ + if(!fnd.at_end()){ name = fnd.next("\""); } else { // No luck, just read a word then fnd.start(all); diff --git a/src/inventorymanager.cpp b/src/inventorymanager.cpp index aa8854ece..658b1375b 100644 --- a/src/inventorymanager.cpp +++ b/src/inventorymanager.cpp @@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "craftdef.h" #include "rollback_interface.h" -#include "strfnd.h" +#include "util/strfnd.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index 0a6d0e5d7..5184418f9 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -912,6 +912,9 @@ void MapgenV7::generateCaves(s16 max_stone_y) } } + if (node_min.Y >= water_level) + return; + PseudoRandom ps(blockseed + 21343); u32 bruises_count = ps.range(0, 2); for (u32 i = 0; i < bruises_count; i++) { diff --git a/src/mods.cpp b/src/mods.cpp index e604c742d..ba6261344 100644 --- a/src/mods.cpp +++ b/src/mods.cpp @@ -21,11 +21,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "mods.h" #include "filesys.h" -#include "strfnd.h" +#include "util/strfnd.h" #include "log.h" #include "subgame.h" #include "settings.h" -#include "strfnd.h" +#include "util/strfnd.h" #include "convert_json.h" #include "exceptions.h" diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 36a3e32ad..ff765a6a4 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "nodedef.h" #include "serialization.h" #include "server.h" -#include "strfnd.h" +#include "util/strfnd.h" #include "network/clientopcodes.h" #include "util/serialize.h" #include "util/srp.h" @@ -641,7 +641,7 @@ void Client::handleCommand_AnnounceMedia(NetworkPacket* pkt) *pkt >> str; Strfnd sf(str); - while(!sf.atend()) { + while(!sf.at_end()) { std::string baseurl = trim(sf.next(",")); if (baseurl != "") m_media_downloader->addRemoteServer(baseurl); diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 2c5058511..6fdd7e951 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -145,7 +145,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #define SERVER_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION // Client's supported network protocol range -#define CLIENT_PROTOCOL_VERSION_MIN 13 +// The minimal version depends on whether +// send_pre_v25_init is enabled or not +#define CLIENT_PROTOCOL_VERSION_MIN 25 +#define CLIENT_PROTOCOL_VERSION_MIN_LEGACY 13 #define CLIENT_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION // Constant that differentiates the protocol from random data and other protocols diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index b11de0fe2..7a7482fcc 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -261,9 +261,9 @@ void Server::handleCommand_Init(NetworkPacket* pkt) auth_mechs |= AUTH_MECHANISM_FIRST_SRP; } else { // Take care of default passwords. - client->enc_pwd = getSRPVerifier(playerName, default_password); + client->enc_pwd = get_encoded_srp_verifier(playerName, default_password); auth_mechs |= AUTH_MECHANISM_SRP; - // Create auth, but only on successful login + // Allocate player in db, but only on successful login. client->create_player_on_auth_success = true; } } @@ -549,7 +549,7 @@ void Server::handleCommand_Init_Legacy(NetworkPacket* pkt) std::string raw_default_password = g_settings->get("default_password"); std::string initial_password = - translatePassword(playername, raw_default_password); + translate_password(playername, raw_default_password); // If default_password is empty, allow any initial password if (raw_default_password.length() == 0) @@ -1831,7 +1831,7 @@ void Server::handleCommand_FirstSrp(NetworkPacket* pkt) std::string initial_ver_key; - initial_ver_key = encodeSRPVerifier(verification_key, salt); + initial_ver_key = encode_srp_verifier(verification_key, salt); m_script->createAuth(playername, initial_ver_key); acceptAuth(pkt->getPeerId(), false); @@ -1843,7 +1843,7 @@ void Server::handleCommand_FirstSrp(NetworkPacket* pkt) return; } m_clients.event(pkt->getPeerId(), CSE_SudoLeave); - std::string pw_db_field = encodeSRPVerifier(verification_key, salt); + std::string pw_db_field = encode_srp_verifier(verification_key, salt); bool success = m_script->setPassword(playername, pw_db_field); if (success) { actionstream << playername << " changes password" << std::endl; @@ -1917,22 +1917,14 @@ void Server::handleCommand_SrpBytesA(NetworkPacket* pkt) client->chosen_mech = chosen; - std::string bytes_s; - std::string bytes_v; + std::string salt; + std::string verifier; if (based_on == 0) { - char *p_bytes_s = 0; - size_t len_s = 0; - char *p_bytes_v = 0; - size_t len_v = 0; - getSRPVerifier(client->getName(), client->enc_pwd, - &p_bytes_s, &len_s, - &p_bytes_v, &len_v); - bytes_s = std::string(p_bytes_s, len_s); - bytes_v = std::string(p_bytes_v, len_v); - free(p_bytes_s); - free(p_bytes_v); - } else if (!decodeSRPVerifier(client->enc_pwd, &bytes_s, &bytes_v)) { + + generate_srp_verifier_and_salt(client->getName(), client->enc_pwd, + &verifier, &salt); + } else if (!decode_srp_verifier_and_salt(client->enc_pwd, &verifier, &salt)) { // Non-base64 errors should have been catched in the init handler actionstream << "Server: User " << client->getName() << " tried to log in, but srp verifier field" @@ -1946,8 +1938,8 @@ void Server::handleCommand_SrpBytesA(NetworkPacket* pkt) client->auth_data = srp_verifier_new(SRP_SHA256, SRP_NG_2048, client->getName().c_str(), - (const unsigned char *) bytes_s.c_str(), bytes_s.size(), - (const unsigned char *) bytes_v.c_str(), bytes_v.size(), + (const unsigned char *) salt.c_str(), salt.size(), + (const unsigned char *) verifier.c_str(), verifier.size(), (const unsigned char *) bytes_A.c_str(), bytes_A.size(), NULL, 0, (unsigned char **) &bytes_B, &len_B, NULL, NULL); @@ -1966,7 +1958,7 @@ void Server::handleCommand_SrpBytesA(NetworkPacket* pkt) } NetworkPacket resp_pkt(TOCLIENT_SRP_BYTES_S_B, 0, pkt->getPeerId()); - resp_pkt << bytes_s << std::string(bytes_B, len_B); + resp_pkt << salt << std::string(bytes_B, len_B); Send(&resp_pkt); } diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 232a8533f..66aed716a 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -1095,7 +1095,9 @@ int ModApiMainMenu::l_get_screen_info(lua_State *L) /******************************************************************************/ int ModApiMainMenu::l_get_min_supp_proto(lua_State *L) { - lua_pushinteger(L, CLIENT_PROTOCOL_VERSION_MIN); + u16 proto_version_min = g_settings->getFlag("send_pre_v25_init") ? + CLIENT_PROTOCOL_VERSION_MIN_LEGACY : CLIENT_PROTOCOL_VERSION_MIN; + lua_pushinteger(L, proto_version_min); return 1; } diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp index 9301a07ed..e394f52aa 100644 --- a/src/script/lua_api/l_util.cpp +++ b/src/script/lua_api/l_util.cpp @@ -251,7 +251,7 @@ int ModApiUtil::l_get_password_hash(lua_State *L) NO_MAP_LOCK_REQUIRED; std::string name = luaL_checkstring(L, 1); std::string raw_password = luaL_checkstring(L, 2); - std::string hash = translatePassword(name, raw_password); + std::string hash = translate_password(name, raw_password); lua_pushstring(L, hash.c_str()); return 1; } diff --git a/src/serverlist.cpp b/src/serverlist.cpp index 1e05c89b1..09d03cdcd 100644 --- a/src/serverlist.cpp +++ b/src/serverlist.cpp @@ -69,8 +69,12 @@ std::vector getLocal() std::vector getOnline() { std::ostringstream geturl; + + u16 proto_version_min = g_settings->getFlag("send_pre_v25_init") ? + CLIENT_PROTOCOL_VERSION_MIN_LEGACY : CLIENT_PROTOCOL_VERSION_MIN; + geturl << g_settings->get("serverlist_url") << - "/list?proto_version_min=" << CLIENT_PROTOCOL_VERSION_MIN << + "/list?proto_version_min=" << proto_version_min << "&proto_version_max=" << CLIENT_PROTOCOL_VERSION_MAX; Json::Value root = fetchJsonValue(geturl.str(), NULL); diff --git a/src/settings.cpp b/src/settings.cpp index 6736fceb4..7cf5e1569 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes_bloated.h" #include "exceptions.h" #include "threading/mutex_auto_lock.h" -#include "strfnd.h" +#include "util/strfnd.h" #include #include #include diff --git a/src/settings_translation_file.cpp b/src/settings_translation_file.cpp index f115bc011..77fd6c682 100644 --- a/src/settings_translation_file.cpp +++ b/src/settings_translation_file.cpp @@ -98,6 +98,8 @@ fake_function() { gettext("Address to connect to.\nLeave this blank to start a local server.\nNote that the address field in the main menu overrides this setting."); gettext("Remote port"); gettext("Port to connect to (UDP).\nNote that the port field in the main menu overrides this setting."); + gettext("Support older servers"); + gettext("Whether to support older servers before protocol version 25.\nEnable if you want to connect to 0.4.12 servers and before.\nServers starting with 0.4.13 will work, 0.4.12-dev servers may work.\nDisabling this option will protect your password better."); gettext("Saving map received from server"); gettext("Save the map received by the client on disk."); gettext("Connect to external media server"); @@ -407,6 +409,12 @@ fake_function() { gettext("See http://www.sqlite.org/pragma.html#pragma_synchronous"); gettext("Dedicated server step"); gettext("Length of a server tick and the interval at which objects are generally updated over network."); + gettext("Active Block Management interval"); + gettext("Time in between active block management cycles"); + gettext("ABM modifier interval"); + gettext("Length of time between ABM execution cycles"); + gettext("NodeTimer interval"); + gettext("Length of time between NodeTimer execution cycles"); gettext("Ignore world errors"); gettext("If enabled, invalid world data won't cause the server to shut down.\nOnly enable this if you know what you are doing."); gettext("Liquid loop max"); diff --git a/src/shader.cpp b/src/shader.cpp index 7bbecef51..c08e24e51 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -35,7 +35,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "EShaderTypes.h" #include "log.h" #include "gamedef.h" -#include "strfnd.h" // trim() #include "client/tile.h" /* diff --git a/src/strfnd.h b/src/strfnd.h deleted file mode 100644 index 8b44bda71..000000000 --- a/src/strfnd.h +++ /dev/null @@ -1,176 +0,0 @@ -/* -Minetest -Copyright (C) 2013 celeron55, Perttu Ahola - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 3.0 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef STRFND_HEADER -#define STRFND_HEADER - -#include - -class Strfnd{ - std::string tek; - unsigned int p; -public: - void start(std::string niinq){ - tek = niinq; - p=0; - } - unsigned int where(){ - return p; - } - void to(unsigned int i){ - p = i; - } - std::string what(){ - return tek; - } - std::string next(std::string plop){ - //std::cout<<"tek=\""<=tek.size()"<= tek.size()) - return ""; - - realp = p; - do { - n = tek.find(plop, p); - if (n == std::string::npos || plop == "") - n = tek.length(); - p = n + plop.length(); - } while (n > 0 && tek[n - 1] == '\\'); - - return tek.substr(realp, n - realp); - } - - void skip_over(std::string chars){ - while(p < tek.size()){ - bool is = false; - for(unsigned int i=0; i=tek.size()) return true; - return false; - } - Strfnd(std::string s){ - start(s); - } -}; - -class WStrfnd{ - std::wstring tek; - unsigned int p; -public: - void start(std::wstring niinq){ - tek = niinq; - p=0; - } - unsigned int where(){ - return p; - } - void to(unsigned int i){ - p = i; - } - std::wstring what(){ - return tek; - } - std::wstring next(std::wstring plop){ - //std::cout<<"tek=\""<=tek.size()"<= tek.size()) - return L""; - - realp = p; - do { - n = tek.find(plop, p); - if (n == std::wstring::npos || plop == L"") - n = tek.length(); - p = n + plop.length(); - } while (n > 0 && tek[n - 1] == '\\'); - - return tek.substr(realp, n - realp); - } - - bool atend(){ - if(p>=tek.size()) return true; - return false; - } - WStrfnd(std::wstring s){ - start(s); - } -}; - -#endif - diff --git a/src/subgame.cpp b/src/subgame.cpp index 0388a4ce3..0253191f2 100644 --- a/src/subgame.cpp +++ b/src/subgame.cpp @@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include "settings.h" #include "log.h" -#include "strfnd.h" +#include "util/strfnd.h" #include "defaultsettings.h" // for override_default_settings #include "mapgen.h" // for MapgenParams #include "util/string.h" @@ -79,7 +79,7 @@ SubgameSpec findSubgame(const std::string &id) Strfnd search_paths(getSubgamePathEnv()); - while (!search_paths.atend()) { + while (!search_paths.at_end()) { std::string path = search_paths.next(PATH_DELIM); find_paths.push_back(GameFindPath( path + DIR_DELIM + id, false)); @@ -153,7 +153,7 @@ std::set getAvailableGameIds() Strfnd search_paths(getSubgamePathEnv()); - while (!search_paths.atend()) + while (!search_paths.at_end()) gamespaths.insert(search_paths.next(PATH_DELIM)); for (std::set::const_iterator i = gamespaths.begin(); @@ -230,7 +230,7 @@ std::vector getAvailableWorlds() Strfnd search_paths(getWorldPathEnv()); - while (!search_paths.atend()) + while (!search_paths.at_end()) worldspaths.insert(search_paths.next(PATH_DELIM)); worldspaths.insert(porting::path_user + DIR_DELIM + "worlds"); diff --git a/src/util/auth.cpp b/src/util/auth.cpp index c474a0cda..fce993644 100644 --- a/src/util/auth.cpp +++ b/src/util/auth.cpp @@ -1,6 +1,6 @@ /* Minetest -Copyright (C) 2015 est31 +Copyright (C) 2015, 2016 est31 This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -31,7 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc., // their password. (Exception : if the password field is // blank, we send a blank password - this is for backwards // compatibility with password-less players). -std::string translatePassword(const std::string &name, +std::string translate_password(const std::string &name, const std::string &password) { if (password.length() == 0) @@ -46,7 +46,11 @@ std::string translatePassword(const std::string &name, return pwd; } -void getSRPVerifier(const std::string &name, +// Call lower level SRP code to generate a verifier with the +// given pointers. Contains the preparations, call parameters +// and error checking common to all srp verifier generation code. +// See docs of srp_create_salted_verification_key for more info. +static inline void gen_srp_v(const std::string &name, const std::string &password, char **salt, size_t *salt_len, char **bytes_v, size_t *len_v) { @@ -58,72 +62,76 @@ void getSRPVerifier(const std::string &name, FATAL_ERROR_IF(res != SRP_OK, "Couldn't create salted SRP verifier"); } -// Get a db-ready SRP verifier -// If the salt param is NULL, one is automatically generated. -// Please free() it afterwards. You shouldn't use it for other purposes, -// as you will need the contents of salt_len too. -inline static std::string getSRPVerifier(const std::string &name, - const std::string &password, char ** salt, size_t salt_len) -{ - char * bytes_v = NULL; - size_t len_v; - getSRPVerifier(name, password, salt, &salt_len, - &bytes_v, &len_v); - assert(*salt); // usually, srp_create_salted_verification_key promises us to return SRP_ERR when *salt == NULL - std::string ret_val = encodeSRPVerifier(std::string(bytes_v, len_v), - std::string(*salt, salt_len)); - free(bytes_v); - return ret_val; -} - -// Get a db-ready SRP verifier -std::string getSRPVerifier(const std::string &name, - const std::string &password) -{ - char * salt = NULL; - std::string ret_val = getSRPVerifier(name, - password, &salt, 0); - free(salt); - return ret_val; -} - -// Get a db-ready SRP verifier -std::string getSRPVerifier(const std::string &name, +/// Creates a verification key with given salt and password. +std::string generate_srp_verifier(const std::string &name, const std::string &password, const std::string &salt) { - // The implementation won't change the salt if its set, - // therefore we can cast. - char *salt_cstr = (char *)salt.c_str(); - return getSRPVerifier(name, password, - &salt_cstr, salt.size()); + size_t salt_len = salt.size(); + // The API promises us that the salt doesn't + // get modified if &salt_ptr isn't NULL. + char *salt_ptr = (char *)salt.c_str(); + + char *bytes_v = NULL; + size_t verifier_len = 0; + gen_srp_v(name, password, &salt_ptr, &salt_len, &bytes_v, &verifier_len); + std::string verifier = std::string(bytes_v, verifier_len); + free(bytes_v); + return verifier; } -// Make a SRP verifier db-ready -std::string encodeSRPVerifier(const std::string &verifier, +/// Creates a verification key and salt with given password. +void generate_srp_verifier_and_salt(const std::string &name, + const std::string &password, std::string *verifier, + std::string *salt) +{ + char *bytes_v = NULL; + size_t verifier_len; + char *salt_ptr = NULL; + size_t salt_len; + gen_srp_v(name, password, &salt_ptr, &salt_len, &bytes_v, &verifier_len); + *verifier = std::string(bytes_v, verifier_len); + *salt = std::string(salt_ptr, salt_len); + free(bytes_v); + free(salt_ptr); +} + +/// Gets an SRP verifier, generating a salt, +/// and encodes it as DB-ready string. +std::string get_encoded_srp_verifier(const std::string &name, + const std::string &password) +{ + std::string verifier; + std::string salt; + generate_srp_verifier_and_salt(name, password, &verifier, &salt); + return encode_srp_verifier(verifier, salt); +} + +/// Converts the passed SRP verifier into a DB-ready format. +std::string encode_srp_verifier(const std::string &verifier, const std::string &salt) { std::ostringstream ret_str; ret_str << "#1#" - << base64_encode((unsigned char*) salt.c_str(), salt.size()) << "#" - << base64_encode((unsigned char*) verifier.c_str(), verifier.size()); + << base64_encode((unsigned char *)salt.c_str(), salt.size()) << "#" + << base64_encode((unsigned char *)verifier.c_str(), verifier.size()); return ret_str.str(); } -bool decodeSRPVerifier(const std::string &enc_pwd, - std::string *salt, std::string *bytes_v) +/// Reads the DB-formatted SRP verifier and gets the verifier +/// and salt components. +bool decode_srp_verifier_and_salt(const std::string &encoded, + std::string *verifier, std::string *salt) { - std::vector pwd_components = str_split(enc_pwd, '#'); + std::vector components = str_split(encoded, '#'); - if ((pwd_components.size() != 4) - || (pwd_components[1] != "1") // 1 means srp - || !base64_is_valid(pwd_components[2]) - || !base64_is_valid(pwd_components[3])) + if ((components.size() != 4) + || (components[1] != "1") // 1 means srp + || !base64_is_valid(components[2]) + || !base64_is_valid(components[3])) return false; - std::string salt_str = base64_decode(pwd_components[2]); - std::string bytes_v_str = base64_decode(pwd_components[3]); - *salt = salt_str; - *bytes_v = bytes_v_str; + *salt = base64_decode(components[2]); + *verifier = base64_decode(components[3]); return true; } diff --git a/src/util/auth.h b/src/util/auth.h index 04972e867..47105ee9c 100644 --- a/src/util/auth.h +++ b/src/util/auth.h @@ -1,6 +1,6 @@ /* Minetest -Copyright (C) 2015 est31 +Copyright (C) 2015, 2016 est31 This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -20,18 +20,31 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef AUTH_H #define AUTH_H -std::string translatePassword(const std::string &name, +/// Gets the base64 encoded legacy password db entry. +std::string translate_password(const std::string &name, const std::string &password); -void getSRPVerifier(const std::string &name, - const std::string &password, char **salt, size_t *salt_len, - char **bytes_v, size_t *len_v); -std::string getSRPVerifier(const std::string &name, - const std::string &password); -std::string getSRPVerifier(const std::string &name, + +/// Creates a verification key with given salt and password. +std::string generate_srp_verifier(const std::string &name, const std::string &password, const std::string &salt); -std::string encodeSRPVerifier(const std::string &verifier, + +/// Creates a verification key and salt with given password. +void generate_srp_verifier_and_salt(const std::string &name, + const std::string &password, std::string *verifier, + std::string *salt); + +/// Gets an SRP verifier, generating a salt, +/// and encodes it as DB-ready string. +std::string get_encoded_srp_verifier(const std::string &name, + const std::string &password); + +/// Converts the passed SRP verifier into a DB-ready format. +std::string encode_srp_verifier(const std::string &verifier, const std::string &salt); -bool decodeSRPVerifier(const std::string &enc_pwd, + +/// Reads the DB-formatted SRP verifier and gets the verifier +/// and salt components. +bool decode_srp_verifier_and_salt(const std::string &encoded, std::string *salt, std::string *bytes_v); -#endif \ No newline at end of file +#endif diff --git a/src/util/strfnd.h b/src/util/strfnd.h new file mode 100644 index 000000000..a7cd2badb --- /dev/null +++ b/src/util/strfnd.h @@ -0,0 +1,82 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef STRFND_HEADER +#define STRFND_HEADER + +#include + +template +class BasicStrfnd { + typedef std::basic_string String; + String str; + size_t pos; +public: + BasicStrfnd(const String &s) : str(s), pos(0) {} + void start(const String &s) { str = s; pos = 0; } + size_t where() { return pos; } + void to(size_t i) { pos = i; } + bool at_end() { return pos >= str.size(); } + String what() { return str; } + + String next(const String &sep) + { + if (pos >= str.size()) + return String(); + + size_t n; + if (sep.empty() || (n = str.find(sep, pos)) == String::npos) { + n = str.size(); + } + String ret = str.substr(pos, n - pos); + pos = n + sep.size(); + return ret; + } + + // Returns substr up to the next occurence of sep that isn't escaped with esc ('\\') + String next_esc(const String &sep, T esc=static_cast('\\')) + { + if (pos >= str.size()) + return String(); + + size_t n, old_p = pos; + do { + if (sep.empty() || (n = str.find(sep, pos)) == String::npos) { + pos = n = str.size(); + break; + } + pos = n + sep.length(); + } while (n > 0 && str[n - 1] == esc); + + return str.substr(old_p, n - old_p); + } + + void skip_over(const String &chars) + { + size_t p = str.find_first_not_of(chars, pos); + if (p != String::npos) + pos = p; + } +}; + +typedef BasicStrfnd Strfnd; +typedef BasicStrfnd WStrfnd; + +#endif + diff --git a/src/util/string.h b/src/util/string.h index 49aeb5207..d28a386c9 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -386,6 +386,13 @@ inline void str_replace(std::string &str, const std::string &pattern, } } +/** + * Remove all chat escape sequences in \p s. + * + * @param s The string in which to remove escape sequences. + * @return \p s, with escape sequences removed. + */ +std::wstring removeChatEscapes(const std::wstring &s); /** * Replace all occurrences of the character \p from in \p str with \p to. diff --git a/util/travis/script.sh b/util/travis/script.sh index 5be747e51..870954ebb 100755 --- a/util/travis/script.sh +++ b/util/travis/script.sh @@ -2,10 +2,8 @@ if [[ $PLATFORM == "Unix" ]]; then mkdir -p travisbuild - cd travisbuild - CMAKE_FLAGS='-DCMAKE_BUILD_TYPE=Debug \ - -DRUN_IN_PLACE=TRUE \ - -DENABLE_GETTEXT=TRUE' + cd travisbuild || exit 1 + CMAKE_FLAGS='' # Clang builds with FreeType fail on Travis if [[ $CC == "clang" ]]; then CMAKE_FLAGS+=' -DENABLE_FREETYPE=FALSE' @@ -13,7 +11,10 @@ if [[ $PLATFORM == "Unix" ]]; then if [[ $TRAVIS_OS_NAME == "osx" ]]; then CMAKE_FLAGS+=' -DCUSTOM_GETTEXT_PATH=/usr/local/opt/gettext' fi - cmake $CMAKE_FLAGS .. + cmake -DCMAKE_BUILD_TYPE=Debug \ + -DRUN_IN_PLACE=TRUE \ + -DENABLE_GETTEXT=TRUE \ + $CMAKE_FLAGS .. make -j2 echo "Running unit tests." ../bin/minetest --run-unittests && exit 0 @@ -34,9 +35,9 @@ elif [[ $PLATFORM == Win* ]]; then export EXISTING_MINETEST_DIR=$OLDDIR export NO_MINETEST_GAME=1 if [[ $PLATFORM == "Win32" ]]; then - $OLDDIR/util/buildbot/buildwin32.sh travisbuild && exit 0 + "$OLDDIR/util/buildbot/buildwin32.sh" travisbuild && exit 0 elif [[ $PLATFORM == "Win64" ]]; then - $OLDDIR/util/buildbot/buildwin64.sh travisbuild && exit 0 + "$OLDDIR/util/buildbot/buildwin64.sh" travisbuild && exit 0 fi else echo "Unknown platform \"${PLATFORM}\"."