3095: Disallow player name changes when the player is muted r=def- a=heinrich5991



Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
This commit is contained in:
bors[bot] 2020-10-20 15:56:16 +00:00 committed by GitHub
commit 2709afb007
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 46 deletions

View file

@ -190,6 +190,7 @@ public:
virtual void GetMapInfo(char *pMapName, int MapNameSize, int *pMapSize, SHA256_DIGEST *pSha256, int *pMapCrc) = 0;
virtual bool WouldClientNameChange(int ClientID, const char *pNameRequest) = 0;
virtual void SetClientName(int ClientID, char const *pName) = 0;
virtual void SetClientClan(int ClientID, char const *pClan) = 0;
virtual void SetClientCountry(int ClientID, int Country) = 0;

View file

@ -329,82 +329,96 @@ CServer::CServer() :
Init();
}
int CServer::TrySetClientName(int ClientID, const char *pName)
bool CServer::IsClientNameAvailable(int ClientID, const char *pNameRequest)
{
char aTrimmedName[64];
// trim the name
str_copy(aTrimmedName, str_utf8_skip_whitespaces(pName), sizeof(aTrimmedName));
str_utf8_trim_right(aTrimmedName);
// check for empty names
if(!aTrimmedName[0])
return -1;
if(!pNameRequest[0])
return false;
// check for names starting with /, as they can be abused to make people
// write chat commands
if(aTrimmedName[0] == '/')
return -1;
if(pNameRequest[0] == '/')
return false;
// make sure that two clients don't have the same name
for(int i = 0; i < MAX_CLIENTS; i++)
{
if(i != ClientID && m_aClients[i].m_State >= CClient::STATE_READY)
{
if(str_utf8_comp_confusable(aTrimmedName, m_aClients[i].m_aName) == 0)
return -1;
if(str_utf8_comp_confusable(pNameRequest, m_aClients[i].m_aName) == 0)
return false;
}
}
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "'%s' -> '%s'", pName, aTrimmedName);
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf);
pName = aTrimmedName;
// set the client name
str_copy(m_aClients[ClientID].m_aName, pName, MAX_NAME_LENGTH);
return 0;
return true;
}
void CServer::SetClientName(int ClientID, const char *pName)
bool CServer::SetClientNameImpl(int ClientID, const char *pNameRequest, bool Set)
{
if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY)
return;
dbg_assert(0 <= ClientID && ClientID < MAX_CLIENTS, "invalid client id");
if(m_aClients[ClientID].m_State < CClient::STATE_READY)
return false;
if(!pName)
return;
CNameBan *pBanned = IsNameBanned(pName, m_aNameBans.base_ptr(), m_aNameBans.size());
if(pBanned)
if(Set)
{
if(m_aClients[ClientID].m_State == CClient::STATE_READY)
CNameBan *pBanned = IsNameBanned(pNameRequest, m_aNameBans.base_ptr(), m_aNameBans.size());
if(pBanned)
{
char aBuf[256];
if(pBanned->m_aReason[0])
if(m_aClients[ClientID].m_State == CClient::STATE_READY)
{
str_format(aBuf, sizeof(aBuf), "Kicked (your name is banned: %s)", pBanned->m_aReason);
char aBuf[256];
if(pBanned->m_aReason[0])
{
str_format(aBuf, sizeof(aBuf), "Kicked (your name is banned: %s)", pBanned->m_aReason);
}
else
{
str_copy(aBuf, "Kicked (your name is banned)", sizeof(aBuf));
}
Kick(ClientID, aBuf);
}
else
{
str_copy(aBuf, "Kicked (your name is banned)", sizeof(aBuf));
}
Kick(ClientID, aBuf);
return true;
}
return;
}
// trim the name
char aTrimmedName[MAX_NAME_LENGTH];
str_copy(aTrimmedName, str_utf8_skip_whitespaces(pNameRequest), sizeof(aTrimmedName));
str_utf8_trim_right(aTrimmedName);
char aNameTry[MAX_NAME_LENGTH];
str_copy(aNameTry, pName, sizeof(aNameTry));
if(TrySetClientName(ClientID, aNameTry))
str_copy(aNameTry, aTrimmedName, sizeof(aNameTry));
if(!IsClientNameAvailable(ClientID, aNameTry))
{
// auto rename
for(int i = 1;; i++)
{
str_format(aNameTry, sizeof(aNameTry), "(%d)%s", i, pName);
if(TrySetClientName(ClientID, aNameTry) == 0)
str_format(aNameTry, sizeof(aNameTry), "(%d)%s", i, aTrimmedName);
if(IsClientNameAvailable(ClientID, aNameTry))
break;
}
}
bool Changed = str_comp(m_aClients[ClientID].m_aName, aNameTry) != 0;
if(Set)
{
// set the client name
str_copy(m_aClients[ClientID].m_aName, aNameTry, MAX_NAME_LENGTH);
}
return Changed;
}
bool CServer::WouldClientNameChange(int ClientID, const char *pNameRequest)
{
return SetClientNameImpl(ClientID, pNameRequest, false);
}
void CServer::SetClientName(int ClientID, const char *pName)
{
SetClientNameImpl(ClientID, pName, true);
}
void CServer::SetClientClan(int ClientID, const char *pClan)

View file

@ -258,8 +258,10 @@ public:
CServer();
int TrySetClientName(int ClientID, const char *pName);
bool IsClientNameAvailable(int ClientID, const char *pNameRequest);
bool SetClientNameImpl(int ClientID, const char *pNameRequest, bool Set);
virtual bool WouldClientNameChange(int ClientID, const char *pNameRequest);
virtual void SetClientName(int ClientID, const char *pName);
virtual void SetClientClan(int ClientID, char const *pClan);
virtual void SetClientCountry(int ClientID, int Country);

View file

@ -2173,9 +2173,10 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
// set infos
char aOldName[MAX_NAME_LENGTH];
str_copy(aOldName, Server()->ClientName(ClientID), sizeof(aOldName));
Server()->SetClientName(ClientID, pMsg->m_pName);
if(str_comp(aOldName, Server()->ClientName(ClientID)) != 0)
if(Server()->WouldClientNameChange(ClientID, pMsg->m_pName) && !ProcessSpamProtection(ClientID))
{
Server()->SetClientName(ClientID, pMsg->m_pName);
char aChatText[256];
str_format(aChatText, sizeof(aChatText), "'%s' changed name to '%s'", aOldName, Server()->ClientName(ClientID));
SendChat(-1, CGameContext::CHAT_ALL, aChatText);