Rewrite(Core/BanManager): Rewrite Ban system (#1576)

* Added ban manager
* Delete ban functions in world class
* Separate ban account to (ban account, ban ip, ban character)
* Support world announce
This commit is contained in:
Kargatum
2019-03-25 10:00:17 +07:00
committed by GitHub
parent a9c4c14ef2
commit 1f4f318705
12 changed files with 473 additions and 220 deletions
+1 -174
View File
@@ -1242,6 +1242,7 @@ void World::LoadConfigSettings(bool reload)
m_bool_configs[CONFIG_NO_RESET_TALENT_COST] = sConfigMgr->GetBoolDefault("NoResetTalentsCost", false);
m_bool_configs[CONFIG_SHOW_KICK_IN_WORLD] = sConfigMgr->GetBoolDefault("ShowKickInWorld", false);
m_bool_configs[CONFIG_SHOW_BAN_IN_WORLD] = sConfigMgr->GetBoolDefault("ShowBanInWorld", false);
m_int_configs[CONFIG_INTERVAL_LOG_UPDATE] = sConfigMgr->GetIntDefault("RecordUpdateTimeDiffInterval", 60000);
m_int_configs[CONFIG_MIN_LOG_UPDATE] = sConfigMgr->GetIntDefault("MinRecordUpdateTimeDiff", 100);
m_int_configs[CONFIG_NUMTHREADS] = sConfigMgr->GetIntDefault("MapUpdate.Threads", 1);
@@ -2440,180 +2441,6 @@ void World::KickAllLess(AccountTypes sec)
itr->second->KickPlayer("KickAllLess");
}
/// Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban
BanReturn World::BanAccount(BanMode mode, std::string const& nameOrIP, std::string const& duration, std::string const& reason, std::string const& author)
{
uint32 duration_secs = TimeStringToSecs(duration);
PreparedQueryResult resultAccounts = PreparedQueryResult(NULL); //used for kicking
PreparedStatement* stmt = NULL;
///- Update the database with ban information
switch (mode)
{
case BAN_IP:
// No SQL injection with prepared statements
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_BY_IP);
stmt->setString(0, nameOrIP);
resultAccounts = LoginDatabase.Query(stmt);
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_IP_BANNED);
stmt->setString(0, nameOrIP);
stmt->setUInt32(1, duration_secs);
stmt->setString(2, author);
stmt->setString(3, reason);
LoginDatabase.Execute(stmt);
break;
case BAN_ACCOUNT:
// No SQL injection with prepared statements
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME);
stmt->setString(0, nameOrIP);
resultAccounts = LoginDatabase.Query(stmt);
break;
case BAN_CHARACTER:
// No SQL injection with prepared statements
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_BY_NAME);
stmt->setString(0, nameOrIP);
resultAccounts = CharacterDatabase.Query(stmt);
break;
default:
return BAN_SYNTAX_ERROR;
}
if (!resultAccounts)
{
if (mode == BAN_IP)
return BAN_SUCCESS; // ip correctly banned but nobody affected (yet)
else
return BAN_NOTFOUND; // Nobody to ban
}
///- Disconnect all affected players (for IP it can be several)
SQLTransaction trans = LoginDatabase.BeginTransaction();
do
{
Field* fieldsAccount = resultAccounts->Fetch();
uint32 account = fieldsAccount[0].GetUInt32();
if (mode != BAN_IP)
{
// pussywizard: check existing ban to prevent overriding by a shorter one! >_>
PreparedStatement* stmtx = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_BANNED);
stmtx->setUInt32(0, account);
PreparedQueryResult banresultx = LoginDatabase.Query(stmtx);
if (banresultx && ((*banresultx)[0].GetUInt32() == (*banresultx)[1].GetUInt32() || ((*banresultx)[1].GetUInt32() > time(NULL)+duration_secs && duration_secs)))
return BAN_LONGER_EXISTS;
// make sure there is only one active ban
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_NOT_BANNED);
stmt->setUInt32(0, account);
trans->Append(stmt);
// No SQL injection with prepared statements
stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_BANNED);
stmt->setUInt32(0, account);
stmt->setUInt32(1, duration_secs);
stmt->setString(2, author);
stmt->setString(3, reason);
trans->Append(stmt);
}
if (WorldSession* sess = FindSession(account))
if (sess->GetPlayerName() != author)
sess->KickPlayer("FindSession(account)->GetPlayerName() != author");
if (WorldSession* sess = FindOfflineSession(account))
if (sess->GetPlayerName() != author)
sess->KickPlayer("FindOfflineSession(account)->GetPlayerName() != author");
} while (resultAccounts->NextRow());
LoginDatabase.CommitTransaction(trans);
return BAN_SUCCESS;
}
/// Remove a ban from an account or IP address
bool World::RemoveBanAccount(BanMode mode, std::string const& nameOrIP)
{
PreparedStatement* stmt = NULL;
if (mode == BAN_IP)
{
stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_IP_NOT_BANNED);
stmt->setString(0, nameOrIP);
LoginDatabase.Execute(stmt);
}
else
{
uint32 account = 0;
if (mode == BAN_ACCOUNT)
account = AccountMgr::GetId(nameOrIP);
else if (mode == BAN_CHARACTER)
account = sObjectMgr->GetPlayerAccountIdByPlayerName(nameOrIP);
if (!account)
return false;
//NO SQL injection as account is uint32
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_NOT_BANNED);
stmt->setUInt32(0, account);
LoginDatabase.Execute(stmt);
}
return true;
}
/// Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban
BanReturn World::BanCharacter(std::string const& name, std::string const& duration, std::string const& reason, std::string const& author)
{
Player* pBanned = ObjectAccessor::FindPlayerByName(name, false);
uint32 guid = 0;
uint32 duration_secs = TimeStringToSecs(duration);
/// Pick a player to ban if not online
if (!pBanned)
{
guid = sWorld->GetGlobalPlayerGUID(name);
if (!guid)
return BAN_NOTFOUND;
}
else
guid = pBanned->GetGUIDLow();
// make sure there is only one active ban
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHARACTER_BAN);
stmt->setUInt32(0, guid);
CharacterDatabase.Execute(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_BAN);
stmt->setUInt32(0, guid);
stmt->setUInt32(1, duration_secs);
stmt->setString(2, author);
stmt->setString(3, reason);
CharacterDatabase.Execute(stmt);
if (pBanned)
pBanned->GetSession()->KickPlayer("Ban");
return BAN_SUCCESS;
}
/// Remove a ban from a character
bool World::RemoveBanCharacter(std::string const& name)
{
Player* pBanned = ObjectAccessor::FindPlayerByName(name, false);
uint32 guid = 0;
/// Pick a player to ban if not online
if (!pBanned)
guid = sWorld->GetGlobalPlayerGUID(name);
else
guid = pBanned->GetGUIDLow();
if (!guid)
return false;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHARACTER_BAN);
stmt->setUInt32(0, guid);
CharacterDatabase.Execute(stmt);
return true;
}
/// Update the game time
void World::_UpdateGameTime()
{
+1 -4
View File
@@ -136,6 +136,7 @@ enum WorldBoolConfigs
CONFIG_PVP_TOKEN_ENABLE,
CONFIG_NO_RESET_TALENT_COST,
CONFIG_SHOW_KICK_IN_WORLD,
CONFIG_SHOW_BAN_IN_WORLD,
CONFIG_CHATLOG_CHANNEL,
CONFIG_CHATLOG_WHISPER,
CONFIG_CHATLOG_SYSCHAN,
@@ -726,10 +727,6 @@ class World
void KickAll();
void KickAllLess(AccountTypes sec);
BanReturn BanAccount(BanMode mode, std::string const& nameOrIP, std::string const& duration, std::string const& reason, std::string const& author);
bool RemoveBanAccount(BanMode mode, std::string const& nameOrIP);
BanReturn BanCharacter(std::string const& name, std::string const& duration, std::string const& reason, std::string const& author);
bool RemoveBanCharacter(std::string const& name);
// for max speed access
static float GetMaxVisibleDistanceOnContinents() { return m_MaxVisibleDistanceOnContinents; }