Add minetest.is_valid_player_name utility
Some checks are pending
android / build (push) Waiting to run
cpp_lint / clang_tidy (push) Waiting to run
linux / gcc_7 (push) Waiting to run
linux / gcc_14 (push) Waiting to run
linux / clang_7 (push) Waiting to run
linux / clang_18 (push) Waiting to run
linux / clang_11 (PROMETHEUS=1) (push) Waiting to run
lua_lint / Compile and run multiplayer tests (push) Waiting to run
lua_lint / Builtin Luacheck and Unit Tests (push) Waiting to run
lua_api_deploy / build (push) Waiting to run
macos / build (push) Waiting to run
windows / MinGW cross-compiler (${{ matrix.bits }}-bit) (64) (push) Waiting to run
windows / MinGW cross-compiler (${{ matrix.bits }}-bit) (32) (push) Waiting to run
windows / VS 2019 ${{ matrix.config.arch }}-${{ matrix.type }} (map[arch:x64 generator:-G'Visual Studio 16 2019' -A x64 vcpkg_triplet:x64-windows], portable) (push) Waiting to run
windows / VS 2019 ${{ matrix.config.arch }}-${{ matrix.type }} (map[arch:x86 generator:-G'Visual Studio 16 2019' -A Win32 vcpkg_triplet:x86-windows], portable) (push) Waiting to run

This commit is contained in:
Lars Mueller 2024-08-13 02:50:36 +02:00 committed by sfan5
parent 44db47e64a
commit d3ca269c79
7 changed files with 32 additions and 15 deletions

View File

@ -7097,6 +7097,8 @@ Misc.
* `minetest.is_player(obj)`: boolean, whether `obj` is a player * `minetest.is_player(obj)`: boolean, whether `obj` is a player
* `minetest.player_exists(name)`: boolean, whether player exists * `minetest.player_exists(name)`: boolean, whether player exists
(regardless of online status) (regardless of online status)
* `minetest.is_valid_player_name(name)`: boolean, whether the given name
could be used as a player name (regardless of whether said player exists).
* `minetest.hud_replace_builtin(name, hud_definition)` * `minetest.hud_replace_builtin(name, hud_definition)`
* Replaces definition of a builtin hud element * Replaces definition of a builtin hud element
* `name`: `"breath"`, `"health"` or `"minimap"` * `name`: `"breath"`, `"health"` or `"minimap"`
@ -7989,9 +7991,9 @@ child will follow movement and rotation of that bone.
* `set_observers(observers)`: sets observers (players this object is sent to) * `set_observers(observers)`: sets observers (players this object is sent to)
* If `observers` is `nil`, the object's observers are "unmanaged": * If `observers` is `nil`, the object's observers are "unmanaged":
The object is sent to all players as governed by server settings. This is the default. The object is sent to all players as governed by server settings. This is the default.
* `observers` is a "set" of player names: `{[player name] = true, [other player name] = true, ...}` * `observers` is a "set" of player names: `{name1 = true, name2 = true, ...}`
* A set is a table where the keys are the elements of the set (in this case, player names) * A set is a table where the keys are the elements of the set
and the values are all `true`. (in this case, *valid* player names) and the values are all `true`.
* Attachments: The *effective observers* of an object are made up of * Attachments: The *effective observers* of an object are made up of
all players who can observe the object *and* are also effective observers all players who can observe the object *and* are also effective observers
of its parent object (if there is one). of its parent object (if there is one).

View File

@ -1095,13 +1095,9 @@ static bool run_dedicated_server(const GameParams &game_params, const Settings &
if (cmd_args.exists("terminal")) { if (cmd_args.exists("terminal")) {
#if USE_CURSES #if USE_CURSES
bool name_ok = true;
std::string admin_nick = g_settings->get("name"); std::string admin_nick = g_settings->get("name");
name_ok = name_ok && !admin_nick.empty(); if (!is_valid_player_name(admin_nick)) {
name_ok = name_ok && string_allowed(admin_nick, PLAYERNAME_ALLOWED_CHARS);
if (!name_ok) {
if (admin_nick.empty()) { if (admin_nick.empty()) {
errorstream << "No name given for admin. " errorstream << "No name given for admin. "
<< "Please check your minetest.conf that it " << "Please check your minetest.conf that it "
@ -1110,7 +1106,8 @@ static bool run_dedicated_server(const GameParams &game_params, const Settings &
} else { } else {
errorstream << "Name for admin '" errorstream << "Name for admin '"
<< admin_nick << "' is not valid. " << admin_nick << "' is not valid. "
<< "Please check that it only contains allowed characters. " << "Please check that it only contains allowed characters "
<< "and that it is at most 20 characters long. "
<< "Valid characters are: " << PLAYERNAME_ALLOWED_CHARS_USER_EXPL << "Valid characters are: " << PLAYERNAME_ALLOWED_CHARS_USER_EXPL
<< std::endl; << std::endl;
} }

View File

@ -30,6 +30,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "porting.h" // strlcpy #include "porting.h" // strlcpy
bool is_valid_player_name(std::string_view name) {
return !name.empty() && name.size() <= PLAYERNAME_SIZE && string_allowed(name, PLAYERNAME_ALLOWED_CHARS);
}
Player::Player(const std::string &name, IItemDefManager *idef): Player::Player(const std::string &name, IItemDefManager *idef):
inventory(idef) inventory(idef)
{ {

View File

@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "constants.h" #include "constants.h"
#include "network/networkprotocol.h" #include "network/networkprotocol.h"
#include "util/basic_macros.h" #include "util/basic_macros.h"
#include "util/string.h"
#include <list> #include <list>
#include <mutex> #include <mutex>
#include <functional> #include <functional>
@ -35,6 +36,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define PLAYERNAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" #define PLAYERNAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
#define PLAYERNAME_ALLOWED_CHARS_USER_EXPL "'a' to 'z', 'A' to 'Z', '0' to '9', '-', '_'" #define PLAYERNAME_ALLOWED_CHARS_USER_EXPL "'a' to 'z', 'A' to 'Z', '0' to '9', '-', '_'"
bool is_valid_player_name(std::string_view name);
struct PlayerFovSpec struct PlayerFovSpec
{ {
f32 fov; f32 fov;

View File

@ -859,12 +859,8 @@ int ObjectRef::l_set_observers(lua_State *L)
lua_pushnil(L); lua_pushnil(L);
while (lua_next(L, 2) != 0) { while (lua_next(L, 2) != 0) {
std::string name = readParam<std::string>(L, -2); std::string name = readParam<std::string>(L, -2);
if (name.empty()) if (!is_valid_player_name(name))
throw LuaError("Observer name is empty"); throw LuaError("Observer name is not a valid player name");
if (name.size() > PLAYERNAME_SIZE)
throw LuaError("Observer name is too long");
if (!string_allowed(name, PLAYERNAME_ALLOWED_CHARS))
throw LuaError("Observer name contains invalid characters");
if (!lua_toboolean(L, -1)) // falsy value? if (!lua_toboolean(L, -1)) // falsy value?
throw LuaError("Values in the `observers` table need to be true"); throw LuaError("Values in the `observers` table need to be true");
observer_names.insert(std::move(name)); observer_names.insert(std::move(name));

View File

@ -44,6 +44,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/sha1.h" #include "util/sha1.h"
#include "my_sha256.h" #include "my_sha256.h"
#include "util/png.h" #include "util/png.h"
#include "player.h"
#include <cstdio> #include <cstdio>
// only available in zstd 1.3.5+ // only available in zstd 1.3.5+
@ -674,6 +675,16 @@ int ModApiUtil::l_urlencode(lua_State *L)
return 1; return 1;
} }
// is_valid_player_name(name)
int ModApiUtil::l_is_valid_player_name(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
auto s = readParam<std::string_view>(L, 1);
lua_pushboolean(L, is_valid_player_name(s));
return 1;
}
void ModApiUtil::Initialize(lua_State *L, int top) void ModApiUtil::Initialize(lua_State *L, int top)
{ {
API_FCT(log); API_FCT(log);
@ -722,6 +733,7 @@ void ModApiUtil::Initialize(lua_State *L, int top)
API_FCT(set_last_run_mod); API_FCT(set_last_run_mod);
API_FCT(urlencode); API_FCT(urlencode);
API_FCT(is_valid_player_name);
LuaSettings::create(L, g_settings, g_settings_path); LuaSettings::create(L, g_settings, g_settings_path);
lua_setfield(L, top, "settings"); lua_setfield(L, top, "settings");

View File

@ -134,6 +134,9 @@ private:
// urlencode(value) // urlencode(value)
static int l_urlencode(lua_State *L); static int l_urlencode(lua_State *L);
// is_valid_player_name(name)
static int l_is_valid_player_name(lua_State *L);
public: public:
static void Initialize(lua_State *L, int top); static void Initialize(lua_State *L, int top);
static void InitializeAsync(lua_State *L, int top); static void InitializeAsync(lua_State *L, int top);