mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Refactor name bans, move code to separate class CNameBans
Unify all code for name bans in new class `CNameBans` in the existing `name_ban.cpp/h` files. The previously global function `IsNameBanned` is now the member function `CNameBans::IsBanned`. The existing name ban tests are extended for the `CNameBans` class. Move `CNameBan` constructor definition to source file to avoid including `system.h` in the header file. Use `bool` instead of `int` for `m_IsSubstring`. Reorder `CNameBan` constructor arguments and remove unnecessary default value.
This commit is contained in:
parent
ecf2f594c6
commit
8156052cc1
|
@ -1,6 +1,92 @@
|
|||
#include "name_ban.h"
|
||||
|
||||
CNameBan *IsNameBanned(const char *pName, std::vector<CNameBan> &vNameBans)
|
||||
#include <base/system.h>
|
||||
|
||||
#include <engine/shared/config.h>
|
||||
|
||||
CNameBan::CNameBan(const char *pName, const char *pReason, int Distance, bool IsSubstring) :
|
||||
m_Distance(Distance), m_IsSubstring(IsSubstring)
|
||||
{
|
||||
str_copy(m_aName, pName);
|
||||
str_copy(m_aReason, pReason);
|
||||
m_SkeletonLength = str_utf8_to_skeleton(m_aName, m_aSkeleton, std::size(m_aSkeleton));
|
||||
}
|
||||
|
||||
void CNameBans::InitConsole(IConsole *pConsole)
|
||||
{
|
||||
m_pConsole = pConsole;
|
||||
|
||||
m_pConsole->Register("name_ban", "s[name] ?i[distance] ?i[is_substring] ?r[reason]", CFGFLAG_SERVER, ConNameBan, this, "Ban a certain nickname");
|
||||
m_pConsole->Register("name_unban", "s[name]", CFGFLAG_SERVER, ConNameUnban, this, "Unban a certain nickname");
|
||||
m_pConsole->Register("name_bans", "", CFGFLAG_SERVER, ConNameBans, this, "List all name bans");
|
||||
}
|
||||
|
||||
void CNameBans::Ban(const char *pName, const char *pReason, const int Distance, const bool IsSubstring)
|
||||
{
|
||||
for(auto &Ban : m_vNameBans)
|
||||
{
|
||||
if(str_comp(Ban.m_aName, pName) == 0)
|
||||
{
|
||||
if(m_pConsole)
|
||||
{
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "changed name='%s' distance=%d old_distance=%d is_substring=%d old_is_substring=%d reason='%s' old_reason='%s'", pName, Distance, Ban.m_Distance, IsSubstring, Ban.m_IsSubstring, pReason, Ban.m_aReason);
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "name_ban", aBuf);
|
||||
}
|
||||
str_copy(Ban.m_aReason, pReason);
|
||||
Ban.m_Distance = Distance;
|
||||
Ban.m_IsSubstring = IsSubstring;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_vNameBans.emplace_back(pName, pReason, Distance, IsSubstring);
|
||||
if(m_pConsole)
|
||||
{
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "added name='%s' distance=%d is_substring=%d reason='%s'", pName, Distance, IsSubstring, pReason);
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "name_ban", aBuf);
|
||||
}
|
||||
}
|
||||
|
||||
void CNameBans::Unban(const char *pName)
|
||||
{
|
||||
auto ToRemove = std::remove_if(m_vNameBans.begin(), m_vNameBans.end(), [pName](const CNameBan &Ban) { return str_comp(Ban.m_aName, pName) == 0; });
|
||||
if(ToRemove == m_vNameBans.end())
|
||||
{
|
||||
if(m_pConsole)
|
||||
{
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "name ban '%s' not found", pName);
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "name_ban", aBuf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_pConsole)
|
||||
{
|
||||
char aBuf[256];
|
||||
str_format(aBuf, sizeof(aBuf), "removed name='%s' distance=%d is_substring=%d reason='%s'", (*ToRemove).m_aName, (*ToRemove).m_Distance, (*ToRemove).m_IsSubstring, (*ToRemove).m_aReason);
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "name_ban", aBuf);
|
||||
}
|
||||
m_vNameBans.erase(ToRemove, m_vNameBans.end());
|
||||
}
|
||||
}
|
||||
|
||||
void CNameBans::Dump() const
|
||||
{
|
||||
if(!m_pConsole)
|
||||
return;
|
||||
|
||||
char aBuf[256];
|
||||
for(const auto &Ban : m_vNameBans)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "name='%s' distance=%d is_substring=%d reason='%s'", Ban.m_aName, Ban.m_Distance, Ban.m_IsSubstring, Ban.m_aReason);
|
||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "name_ban", aBuf);
|
||||
}
|
||||
}
|
||||
|
||||
const CNameBan *CNameBans::IsBanned(const char *pName) const
|
||||
{
|
||||
char aTrimmed[MAX_NAME_LENGTH];
|
||||
str_copy(aTrimmed, str_utf8_skip_whitespaces(pName));
|
||||
|
@ -10,12 +96,32 @@ CNameBan *IsNameBanned(const char *pName, std::vector<CNameBan> &vNameBans)
|
|||
int SkeletonLength = str_utf8_to_skeleton(aTrimmed, aSkeleton, std::size(aSkeleton));
|
||||
int aBuffer[MAX_NAME_SKELETON_LENGTH * 2 + 2];
|
||||
|
||||
CNameBan *pResult = nullptr;
|
||||
for(CNameBan &Ban : vNameBans)
|
||||
const CNameBan *pResult = nullptr;
|
||||
for(const CNameBan &Ban : m_vNameBans)
|
||||
{
|
||||
int Distance = str_utf32_dist_buffer(aSkeleton, SkeletonLength, Ban.m_aSkeleton, Ban.m_SkeletonLength, aBuffer, std::size(aBuffer));
|
||||
if(Distance <= Ban.m_Distance || (Ban.m_IsSubstring == 1 && str_utf8_find_nocase(pName, Ban.m_aName)))
|
||||
if(Distance <= Ban.m_Distance || (Ban.m_IsSubstring && str_utf8_find_nocase(pName, Ban.m_aName)))
|
||||
pResult = &Ban;
|
||||
}
|
||||
return pResult;
|
||||
}
|
||||
|
||||
void CNameBans::ConNameBan(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
const char *pName = pResult->GetString(0);
|
||||
const char *pReason = pResult->NumArguments() > 3 ? pResult->GetString(3) : "";
|
||||
const int Distance = pResult->NumArguments() > 1 ? pResult->GetInteger(1) : str_length(pName) / 3;
|
||||
const bool IsSubstring = pResult->NumArguments() > 2 ? pResult->GetInteger(2) != 0 : false;
|
||||
static_cast<CNameBans *>(pUser)->Ban(pName, pReason, Distance, IsSubstring);
|
||||
}
|
||||
|
||||
void CNameBans::ConNameUnban(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
const char *pName = pResult->GetString(0);
|
||||
static_cast<CNameBans *>(pUser)->Unban(pName);
|
||||
}
|
||||
|
||||
void CNameBans::ConNameBans(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
static_cast<CNameBans *>(pUser)->Dump();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef ENGINE_SERVER_NAME_BAN_H
|
||||
#define ENGINE_SERVER_NAME_BAN_H
|
||||
|
||||
#include <base/system.h>
|
||||
#include <engine/console.h>
|
||||
#include <engine/shared/protocol.h>
|
||||
|
||||
#include <vector>
|
||||
|
@ -15,22 +15,31 @@ enum
|
|||
class CNameBan
|
||||
{
|
||||
public:
|
||||
CNameBan() {}
|
||||
CNameBan(const char *pName, int Distance, int IsSubstring, const char *pReason = "") :
|
||||
m_Distance(Distance), m_IsSubstring(IsSubstring)
|
||||
{
|
||||
str_copy(m_aName, pName);
|
||||
m_SkeletonLength = str_utf8_to_skeleton(m_aName, m_aSkeleton, std::size(m_aSkeleton));
|
||||
str_copy(m_aReason, pReason);
|
||||
}
|
||||
CNameBan(const char *pName, const char *pReason, int Distance, bool IsSubstring);
|
||||
|
||||
char m_aName[MAX_NAME_LENGTH];
|
||||
char m_aReason[MAX_NAMEBAN_REASON_LENGTH];
|
||||
int m_aSkeleton[MAX_NAME_SKELETON_LENGTH];
|
||||
int m_SkeletonLength;
|
||||
int m_Distance;
|
||||
int m_IsSubstring;
|
||||
bool m_IsSubstring;
|
||||
};
|
||||
|
||||
CNameBan *IsNameBanned(const char *pName, std::vector<CNameBan> &vNameBans);
|
||||
class CNameBans
|
||||
{
|
||||
IConsole *m_pConsole = nullptr;
|
||||
std::vector<CNameBan> m_vNameBans;
|
||||
|
||||
static void ConNameBan(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConNameUnban(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConNameBans(IConsole::IResult *pResult, void *pUser);
|
||||
|
||||
public:
|
||||
void InitConsole(IConsole *pConsole);
|
||||
void Ban(const char *pName, const char *pReason, const int Distance, const bool IsSubstring);
|
||||
void Unban(const char *pName);
|
||||
void Dump() const;
|
||||
const CNameBan *IsBanned(const char *pName) const;
|
||||
};
|
||||
|
||||
#endif // ENGINE_SERVER_NAME_BAN_H
|
||||
|
|
|
@ -403,7 +403,7 @@ bool CServer::SetClientNameImpl(int ClientID, const char *pNameRequest, bool Set
|
|||
if(m_aClients[ClientID].m_State < CClient::STATE_READY)
|
||||
return false;
|
||||
|
||||
CNameBan *pBanned = IsNameBanned(pNameRequest, m_vNameBans);
|
||||
const CNameBan *pBanned = m_NameBans.IsBanned(pNameRequest);
|
||||
if(pBanned)
|
||||
{
|
||||
if(m_aClients[ClientID].m_State == CClient::STATE_READY && Set)
|
||||
|
@ -3352,63 +3352,6 @@ void CServer::ConAuthList(IConsole::IResult *pResult, void *pUser)
|
|||
pManager->ListKeys(ListKeysCallback, pThis);
|
||||
}
|
||||
|
||||
void CServer::ConNameBan(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
CServer *pThis = (CServer *)pUser;
|
||||
char aBuf[256];
|
||||
const char *pName = pResult->GetString(0);
|
||||
const char *pReason = pResult->NumArguments() > 3 ? pResult->GetString(3) : "";
|
||||
int Distance = pResult->NumArguments() > 1 ? pResult->GetInteger(1) : str_length(pName) / 3;
|
||||
int IsSubstring = pResult->NumArguments() > 2 ? pResult->GetInteger(2) : 0;
|
||||
|
||||
for(auto &Ban : pThis->m_vNameBans)
|
||||
{
|
||||
if(str_comp(Ban.m_aName, pName) == 0)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "changed name='%s' distance=%d old_distance=%d is_substring=%d old_is_substring=%d reason='%s' old_reason='%s'", pName, Distance, Ban.m_Distance, IsSubstring, Ban.m_IsSubstring, pReason, Ban.m_aReason);
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "name_ban", aBuf);
|
||||
Ban.m_Distance = Distance;
|
||||
Ban.m_IsSubstring = IsSubstring;
|
||||
str_copy(Ban.m_aReason, pReason);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pThis->m_vNameBans.emplace_back(pName, Distance, IsSubstring, pReason);
|
||||
str_format(aBuf, sizeof(aBuf), "added name='%s' distance=%d is_substring=%d reason='%s'", pName, Distance, IsSubstring, pReason);
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "name_ban", aBuf);
|
||||
}
|
||||
|
||||
void CServer::ConNameUnban(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
CServer *pThis = (CServer *)pUser;
|
||||
const char *pName = pResult->GetString(0);
|
||||
|
||||
for(size_t i = 0; i < pThis->m_vNameBans.size(); i++)
|
||||
{
|
||||
CNameBan *pBan = &pThis->m_vNameBans[i];
|
||||
if(str_comp(pBan->m_aName, pName) == 0)
|
||||
{
|
||||
char aBuf[128];
|
||||
str_format(aBuf, sizeof(aBuf), "removed name='%s' distance=%d is_substring=%d reason='%s'", pBan->m_aName, pBan->m_Distance, pBan->m_IsSubstring, pBan->m_aReason);
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "name_ban", aBuf);
|
||||
pThis->m_vNameBans.erase(pThis->m_vNameBans.begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CServer::ConNameBans(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
CServer *pThis = (CServer *)pUser;
|
||||
|
||||
for(auto &Ban : pThis->m_vNameBans)
|
||||
{
|
||||
char aBuf[128];
|
||||
str_format(aBuf, sizeof(aBuf), "name='%s' distance=%d is_substring=%d reason='%s'", Ban.m_aName, Ban.m_Distance, Ban.m_IsSubstring, Ban.m_aReason);
|
||||
pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "name_ban", aBuf);
|
||||
}
|
||||
}
|
||||
|
||||
void CServer::ConShutdown(IConsole::IResult *pResult, void *pUser)
|
||||
{
|
||||
CServer *pThis = static_cast<CServer *>(pUser);
|
||||
|
@ -3852,10 +3795,6 @@ void CServer::RegisterCommands()
|
|||
Console()->Register("auth_remove", "s[ident]", CFGFLAG_SERVER | CFGFLAG_NONTEEHISTORIC, ConAuthRemove, this, "Remove a rcon key");
|
||||
Console()->Register("auth_list", "", CFGFLAG_SERVER, ConAuthList, this, "List all rcon keys");
|
||||
|
||||
Console()->Register("name_ban", "s[name] ?i[distance] ?i[is_substring] ?r[reason]", CFGFLAG_SERVER, ConNameBan, this, "Ban a certain nickname");
|
||||
Console()->Register("name_unban", "s[name]", CFGFLAG_SERVER, ConNameUnban, this, "Unban a certain nickname");
|
||||
Console()->Register("name_bans", "", CFGFLAG_SERVER, ConNameBans, this, "List all name bans");
|
||||
|
||||
RustVersionRegister(*Console());
|
||||
|
||||
Console()->Chain("sv_name", ConchainSpecialInfoupdate, this);
|
||||
|
@ -3880,6 +3819,7 @@ void CServer::RegisterCommands()
|
|||
|
||||
// register console commands in sub parts
|
||||
m_ServerBan.InitServerBan(Console(), Storage(), this);
|
||||
m_NameBans.InitConsole(Console());
|
||||
m_pGameServer->OnConsoleInit();
|
||||
}
|
||||
|
||||
|
|
|
@ -282,7 +282,7 @@ public:
|
|||
|
||||
char m_aErrorShutdownReason[128];
|
||||
|
||||
std::vector<CNameBan> m_vNameBans;
|
||||
CNameBans m_NameBans;
|
||||
|
||||
size_t m_AnnouncementLastLine;
|
||||
std::vector<std::string> m_vAnnouncements;
|
||||
|
@ -429,10 +429,6 @@ public:
|
|||
static void ConAuthRemove(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConAuthList(IConsole::IResult *pResult, void *pUser);
|
||||
|
||||
static void ConNameBan(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConNameUnban(IConsole::IResult *pResult, void *pUser);
|
||||
static void ConNameBans(IConsole::IResult *pResult, void *pUser);
|
||||
|
||||
// console commands for sqlmasters
|
||||
static void ConAddSqlServer(IConsole::IResult *pResult, void *pUserData);
|
||||
static void ConDumpSqlServers(IConsole::IResult *pResult, void *pUserData);
|
||||
|
|
|
@ -4,29 +4,77 @@
|
|||
|
||||
TEST(NameBan, Empty)
|
||||
{
|
||||
std::vector<CNameBan> vBans;
|
||||
EXPECT_FALSE(IsNameBanned("", vBans));
|
||||
EXPECT_FALSE(IsNameBanned("abc", vBans));
|
||||
CNameBans Bans;
|
||||
EXPECT_FALSE(Bans.IsBanned(""));
|
||||
EXPECT_FALSE(Bans.IsBanned("abc"));
|
||||
}
|
||||
|
||||
TEST(NameBan, BanInfo)
|
||||
{
|
||||
CNameBans Bans;
|
||||
|
||||
Bans.Ban("abc", "old reason", 1, false);
|
||||
{
|
||||
const CNameBan *pOld = Bans.IsBanned("abc");
|
||||
ASSERT_TRUE(pOld);
|
||||
EXPECT_STREQ(pOld->m_aName, "abc");
|
||||
EXPECT_STREQ(pOld->m_aReason, "old reason");
|
||||
EXPECT_EQ(pOld->m_Distance, 1);
|
||||
EXPECT_EQ(pOld->m_IsSubstring, false);
|
||||
}
|
||||
|
||||
// Update existing name ban
|
||||
Bans.Ban("abc", "new reason", 2, true);
|
||||
{
|
||||
const CNameBan *pNew = Bans.IsBanned("abc");
|
||||
ASSERT_TRUE(pNew);
|
||||
EXPECT_STREQ(pNew->m_aName, "abc");
|
||||
EXPECT_STREQ(pNew->m_aReason, "new reason");
|
||||
EXPECT_EQ(pNew->m_Distance, 2);
|
||||
EXPECT_EQ(pNew->m_IsSubstring, true);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NameBan, Equality)
|
||||
{
|
||||
std::vector<CNameBan> vBans;
|
||||
vBans.emplace_back("abc", 0, 0);
|
||||
EXPECT_TRUE(IsNameBanned("abc", vBans));
|
||||
EXPECT_TRUE(IsNameBanned(" abc", vBans));
|
||||
EXPECT_TRUE(IsNameBanned("abc ", vBans));
|
||||
EXPECT_TRUE(IsNameBanned("abc foo", vBans)); // Maximum name length.
|
||||
EXPECT_TRUE(IsNameBanned("äbc", vBans)); // Confusables
|
||||
EXPECT_FALSE(IsNameBanned("def", vBans));
|
||||
EXPECT_FALSE(IsNameBanned("abcdef", vBans));
|
||||
CNameBans Bans;
|
||||
Bans.Ban("abc", "", 0, false);
|
||||
EXPECT_TRUE(Bans.IsBanned("abc"));
|
||||
EXPECT_TRUE(Bans.IsBanned(" abc"));
|
||||
EXPECT_TRUE(Bans.IsBanned("abc "));
|
||||
EXPECT_TRUE(Bans.IsBanned("abc foo")); // Maximum name length.
|
||||
EXPECT_TRUE(Bans.IsBanned("äbc")); // Confusables
|
||||
EXPECT_FALSE(Bans.IsBanned("def"));
|
||||
EXPECT_FALSE(Bans.IsBanned("abcdef"));
|
||||
}
|
||||
|
||||
TEST(NameBan, Substring)
|
||||
{
|
||||
std::vector<CNameBan> vBans;
|
||||
vBans.emplace_back("xyz", 0, 1);
|
||||
EXPECT_TRUE(IsNameBanned("abcxyz", vBans));
|
||||
EXPECT_TRUE(IsNameBanned("abcxyzdef", vBans));
|
||||
EXPECT_FALSE(IsNameBanned("abcdef", vBans));
|
||||
CNameBans Bans;
|
||||
Bans.Ban("xyz", "", 0, true);
|
||||
EXPECT_TRUE(Bans.IsBanned("abcxyz"));
|
||||
EXPECT_TRUE(Bans.IsBanned("abcxyzdef"));
|
||||
EXPECT_FALSE(Bans.IsBanned("abcdef"));
|
||||
}
|
||||
|
||||
TEST(NameBan, Unban)
|
||||
{
|
||||
CNameBans Bans;
|
||||
Bans.Ban("abc", "", 0, false);
|
||||
Bans.Ban("xyz", "", 0, false);
|
||||
EXPECT_TRUE(Bans.IsBanned("abc"));
|
||||
EXPECT_TRUE(Bans.IsBanned("xyz"));
|
||||
Bans.Unban("abc");
|
||||
EXPECT_FALSE(Bans.IsBanned("abc"));
|
||||
EXPECT_TRUE(Bans.IsBanned("xyz"));
|
||||
Bans.Unban("xyz");
|
||||
EXPECT_FALSE(Bans.IsBanned("abc"));
|
||||
EXPECT_FALSE(Bans.IsBanned("xyz"));
|
||||
}
|
||||
|
||||
TEST(NameBan, UnbanNotFound)
|
||||
{
|
||||
// Try to remove a name ban that does not exist
|
||||
CNameBans Bans;
|
||||
Bans.Unban("abc");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue