mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-20 01:24:18 +00:00
improved chat msg spam protection
This commit is contained in:
parent
75cdc0a769
commit
f0e09f50d9
|
@ -231,7 +231,7 @@ Messages = [
|
|||
NetMessage("Sv_Chat", [
|
||||
NetIntRange("m_Team", 'TEAM_SPECTATORS', 'TEAM_BLUE'),
|
||||
NetIntRange("m_ClientID", -1, 'MAX_CLIENTS-1'),
|
||||
NetString("m_pMessage"),
|
||||
NetStringStrict("m_pMessage"),
|
||||
]),
|
||||
|
||||
NetMessage("Sv_KillMsg", [
|
||||
|
@ -294,7 +294,7 @@ Messages = [
|
|||
### Client messages
|
||||
NetMessage("Cl_Say", [
|
||||
NetBool("m_Team"),
|
||||
NetString("m_pMessage"),
|
||||
NetStringStrict("m_pMessage"),
|
||||
]),
|
||||
|
||||
NetMessage("Cl_SetTeam", [
|
||||
|
|
|
@ -1829,6 +1829,27 @@ int str_toint(const char *str) { return atoi(str); }
|
|||
float str_tofloat(const char *str) { return atof(str); }
|
||||
|
||||
|
||||
char *str_utf8_skip_whitespaces(char *str)
|
||||
{
|
||||
char *str_old;
|
||||
int code;
|
||||
|
||||
while(*str)
|
||||
{
|
||||
str_old = str;
|
||||
code = str_utf8_decode(&str);
|
||||
|
||||
// check if unicode is not empty
|
||||
if(code > 0x20 && code != 0xA0 && code != 0x034F && (code < 0x2000 || code > 0x200F) && (code < 0x2028 || code > 0x202F) &&
|
||||
(code < 0x205F || code > 0x2064) && (code < 0x206A || code > 0x206F) && (code < 0xFE00 || code > 0xFE0F) &&
|
||||
code != 0xFEFF && (code < 0xFFF9 || code > 0xFFFC))
|
||||
{
|
||||
return str_old;
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static int str_utf8_isstart(char c)
|
||||
{
|
||||
|
|
|
@ -1213,6 +1213,7 @@ unsigned str_quickhash(const char *str);
|
|||
*/
|
||||
void gui_messagebox(const char *title, const char *message);
|
||||
|
||||
char *str_utf8_skip_whitespaces(char *str);
|
||||
|
||||
/*
|
||||
Function: str_utf8_rewind
|
||||
|
|
|
@ -136,7 +136,7 @@ const char *CUnpacker::GetString(int SanitizeType)
|
|||
str_sanitize(pPtr);
|
||||
else if(SanitizeType&SANITIZE_CC)
|
||||
str_sanitize_cc(pPtr);
|
||||
return SanitizeType&SKIP_START_WHITESPACES ? str_skip_whitespaces(pPtr) : pPtr;
|
||||
return SanitizeType&SKIP_START_WHITESPACES ? str_utf8_skip_whitespaces(pPtr) : pPtr;
|
||||
}
|
||||
|
||||
const unsigned char *CUnpacker::GetRaw(int Size)
|
||||
|
|
|
@ -282,6 +282,34 @@ void CChat::AddLine(int ClientID, int Team, const char *pLine)
|
|||
(m_pClient->m_Snap.m_LocalClientID != ClientID && g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[ClientID].m_Friend))))
|
||||
return;
|
||||
|
||||
// trim right and set maximum length to 128 utf8-characters
|
||||
int Length = 0;
|
||||
const char *pStr = pLine;
|
||||
const char *pEnd = 0;
|
||||
while(*pStr)
|
||||
{
|
||||
const char *pStrOld = pStr;
|
||||
int Code = str_utf8_decode(&pStr);
|
||||
|
||||
// check if unicode is not empty
|
||||
if(Code > 0x20 && Code != 0xA0 && Code != 0x034F && (Code < 0x2000 || Code > 0x200F) && (Code < 0x2028 || Code > 0x202F) &&
|
||||
(Code < 0x205F || Code > 0x2064) && (Code < 0x206A || Code > 0x206F) && (Code < 0xFE00 || Code > 0xFE0F) &&
|
||||
Code != 0xFEFF && (Code < 0xFFF9 || Code > 0xFFFC))
|
||||
{
|
||||
pEnd = 0;
|
||||
}
|
||||
else if(pEnd == 0)
|
||||
pEnd = pStrOld;
|
||||
|
||||
if(++Length >= 127)
|
||||
{
|
||||
*(const_cast<char *>(pStr)) = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(pEnd != 0)
|
||||
*(const_cast<char *>(pEnd)) = 0;
|
||||
|
||||
bool Highlighted = false;
|
||||
char *p = const_cast<char*>(pLine);
|
||||
while(*p)
|
||||
|
|
|
@ -243,7 +243,8 @@ int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrS
|
|||
for(int i = 0; i < m_NumInputEvents; i++)
|
||||
{
|
||||
Len = str_length(pStr);
|
||||
ReturnValue |= CLineInput::Manipulate(m_aInputEvents[i], pStr, StrSize, &Len, &s_AtIndex);
|
||||
int NumChars = Len;
|
||||
ReturnValue |= CLineInput::Manipulate(m_aInputEvents[i], pStr, StrSize, StrSize, &Len, &s_AtIndex, &NumChars);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ void CLineInput::Clear()
|
|||
mem_zero(m_Str, sizeof(m_Str));
|
||||
m_Len = 0;
|
||||
m_CursorPos = 0;
|
||||
m_NumChars = 0;
|
||||
}
|
||||
|
||||
void CLineInput::Set(const char *pString)
|
||||
|
@ -20,10 +21,18 @@ void CLineInput::Set(const char *pString)
|
|||
str_copy(m_Str, pString, sizeof(m_Str));
|
||||
m_Len = str_length(m_Str);
|
||||
m_CursorPos = m_Len;
|
||||
m_NumChars = 0;
|
||||
int Offset = 0;
|
||||
while(pString[Offset])
|
||||
{
|
||||
Offset = str_utf8_forward(pString, Offset);
|
||||
++m_NumChars;
|
||||
}
|
||||
}
|
||||
|
||||
bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *pStrLenPtr, int *pCursorPosPtr)
|
||||
bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int StrMaxChars, int *pStrLenPtr, int *pCursorPosPtr, int *pNumCharsPtr)
|
||||
{
|
||||
int NumChars = *pNumCharsPtr;
|
||||
int CursorPos = *pCursorPosPtr;
|
||||
int Len = *pStrLenPtr;
|
||||
bool Changes = false;
|
||||
|
@ -40,13 +49,15 @@ bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *p
|
|||
char Tmp[8];
|
||||
int CharSize = str_utf8_encode(Tmp, Code);
|
||||
|
||||
if (Len < StrMaxSize - CharSize && CursorPos < StrMaxSize - CharSize)
|
||||
if (Len < StrMaxSize - CharSize && CursorPos < StrMaxSize - CharSize && NumChars < StrMaxChars)
|
||||
{
|
||||
mem_move(pStr + CursorPos + CharSize, pStr + CursorPos, Len-CursorPos+1); // +1 == null term
|
||||
for(int i = 0; i < CharSize; i++)
|
||||
pStr[CursorPos+i] = Tmp[i];
|
||||
CursorPos += CharSize;
|
||||
Len += CharSize;
|
||||
if(CharSize > 0)
|
||||
++NumChars;
|
||||
Changes = true;
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +71,8 @@ bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *p
|
|||
mem_move(pStr+NewCursorPos, pStr+CursorPos, Len - NewCursorPos - CharSize + 1); // +1 == null term
|
||||
CursorPos = NewCursorPos;
|
||||
Len -= CharSize;
|
||||
if(CharSize > 0)
|
||||
--NumChars;
|
||||
Changes = true;
|
||||
}
|
||||
else if (k == KEY_DELETE && CursorPos < Len)
|
||||
|
@ -68,6 +81,8 @@ bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *p
|
|||
int CharSize = p-CursorPos;
|
||||
mem_move(pStr + CursorPos, pStr + CursorPos + CharSize, Len - CursorPos - CharSize + 1); // +1 == null term
|
||||
Len -= CharSize;
|
||||
if(CharSize > 0)
|
||||
--NumChars;
|
||||
Changes = true;
|
||||
}
|
||||
else if (k == KEY_LEFT && CursorPos > 0)
|
||||
|
@ -80,6 +95,7 @@ bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *p
|
|||
CursorPos = Len;
|
||||
}
|
||||
|
||||
*pNumCharsPtr = NumChars;
|
||||
*pCursorPosPtr = CursorPos;
|
||||
*pStrLenPtr = Len;
|
||||
|
||||
|
@ -88,5 +104,5 @@ bool CLineInput::Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *p
|
|||
|
||||
void CLineInput::ProcessInput(IInput::CEvent e)
|
||||
{
|
||||
Manipulate(e, m_Str, sizeof(m_Str), &m_Len, &m_CursorPos);
|
||||
Manipulate(e, m_Str, MAX_SIZE, MAX_CHARS, &m_Len, &m_CursorPos, &m_NumChars);
|
||||
}
|
||||
|
|
|
@ -8,11 +8,17 @@
|
|||
// line input helter
|
||||
class CLineInput
|
||||
{
|
||||
char m_Str[256];
|
||||
enum
|
||||
{
|
||||
MAX_SIZE=512,
|
||||
MAX_CHARS=MAX_SIZE/4,
|
||||
};
|
||||
char m_Str[MAX_SIZE];
|
||||
int m_Len;
|
||||
int m_CursorPos;
|
||||
int m_NumChars;
|
||||
public:
|
||||
static bool Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int *pStrLenPtr, int *pCursorPosPtr);
|
||||
static bool Manipulate(IInput::CEvent e, char *pStr, int StrMaxSize, int StrMaxChars, int *pStrLenPtr, int *pCursorPosPtr, int *pNumCharsPtr);
|
||||
|
||||
class CCallback
|
||||
{
|
||||
|
|
|
@ -277,7 +277,8 @@ int CEditor::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned Str
|
|||
for(int i = 0; i < Input()->NumEvents(); i++)
|
||||
{
|
||||
Len = str_length(pStr);
|
||||
ReturnValue |= CLineInput::Manipulate(Input()->GetEvent(i), pStr, StrSize, &Len, &s_AtIndex);
|
||||
int NumChars = Len;
|
||||
ReturnValue |= CLineInput::Manipulate(Input()->GetEvent(i), pStr, StrSize, StrSize, &Len, &s_AtIndex, &NumChars);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -612,26 +612,45 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
|
|||
{
|
||||
if(MsgID == NETMSGTYPE_CL_SAY)
|
||||
{
|
||||
CNetMsg_Cl_Say *pMsg = (CNetMsg_Cl_Say *)pRawMsg;
|
||||
int Team = pMsg->m_Team;
|
||||
if(Team)
|
||||
Team = pPlayer->GetTeam();
|
||||
else
|
||||
Team = CGameContext::CHAT_ALL;
|
||||
|
||||
if(g_Config.m_SvSpamprotection && pPlayer->m_LastChat && pPlayer->m_LastChat+Server()->TickSpeed() > Server()->Tick())
|
||||
return;
|
||||
|
||||
pPlayer->m_LastChat = Server()->Tick();
|
||||
CNetMsg_Cl_Say *pMsg = (CNetMsg_Cl_Say *)pRawMsg;
|
||||
int Team = pMsg->m_Team ? pPlayer->GetTeam() : CGameContext::CHAT_ALL;
|
||||
|
||||
// trim right and set maximum length to 128 utf8-characters
|
||||
int Length = 0;
|
||||
const char *p = pMsg->m_pMessage;
|
||||
const char *pEnd = 0;
|
||||
while(*p)
|
||||
{
|
||||
const char *pStrOld = p;
|
||||
int Code = str_utf8_decode(&p);
|
||||
|
||||
// check for invalid chars
|
||||
unsigned char *pMessage = (unsigned char *)pMsg->m_pMessage;
|
||||
while (*pMessage)
|
||||
{
|
||||
if(*pMessage < 32)
|
||||
*pMessage = ' ';
|
||||
pMessage++;
|
||||
}
|
||||
// check if unicode is not empty
|
||||
if(Code > 0x20 && Code != 0xA0 && Code != 0x034F && (Code < 0x2000 || Code > 0x200F) && (Code < 0x2028 || Code > 0x202F) &&
|
||||
(Code < 0x205F || Code > 0x2064) && (Code < 0x206A || Code > 0x206F) && (Code < 0xFE00 || Code > 0xFE0F) &&
|
||||
Code != 0xFEFF && (Code < 0xFFF9 || Code > 0xFFFC))
|
||||
{
|
||||
pEnd = 0;
|
||||
}
|
||||
else if(pEnd == 0)
|
||||
pEnd = pStrOld;
|
||||
|
||||
if(++Length >= 127)
|
||||
{
|
||||
*(const_cast<char *>(p)) = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(pEnd != 0)
|
||||
*(const_cast<char *>(pEnd)) = 0;
|
||||
|
||||
// drop empty and autocreated spam messages (more than 16 characters per second)
|
||||
if(Length == 0 || (g_Config.m_SvSpamprotection && pPlayer->m_LastChat && pPlayer->m_LastChat+Server()->TickSpeed()*((15+Length)/16) > Server()->Tick()))
|
||||
return;
|
||||
|
||||
pPlayer->m_LastChat = Server()->Tick();
|
||||
|
||||
SendChat(ClientID, Team, pMsg->m_pMessage);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue