core/PlayerManager.cpp
changeset 1161 b122ca4464ec
parent 1160 7d8b449edd60
child 1162 7c42828c9c0f
     1.1 --- a/core/PlayerManager.cpp	Tue Jul 24 17:05:46 2007 +0000
     1.2 +++ b/core/PlayerManager.cpp	Tue Jul 24 20:11:47 2007 +0000
     1.3 @@ -21,6 +21,9 @@
     1.4  #include "MenuStyle_Radio.h"
     1.5  #include "sm_stringutil.h"
     1.6  #include "CoreConfig.h"
     1.7 +#include <inetchannel.h>
     1.8 +#include <iclient.h>
     1.9 +#include "TimerSys.h"
    1.10  
    1.11  PlayerManager g_Players;
    1.12  bool g_OnMapStarted = false;
    1.13 @@ -32,6 +35,25 @@
    1.14  SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *);
    1.15  SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int);
    1.16  
    1.17 +class KickPlayerTimer : public ITimedEvent
    1.18 +{
    1.19 +public:
    1.20 +	ResultType OnTimer(ITimer *pTimer, void *pData)
    1.21 +	{
    1.22 +		int userid = (int)pData;
    1.23 +		int client = g_Players.GetClientOfUserId(userid);
    1.24 +		if (client)
    1.25 +		{
    1.26 +			CPlayer *player = g_Players.GetPlayerByIndex(client);
    1.27 +			player->Kick("Your name is reserved by SourceMod; set your password to use it.");
    1.28 +		}
    1.29 +		return Pl_Stop;
    1.30 +	}
    1.31 +	void OnTimerEnd(ITimer *pTimer, void *pData)
    1.32 +	{
    1.33 +	}
    1.34 +} s_KickPlayerTimer;
    1.35 +
    1.36  PlayerManager::PlayerManager()
    1.37  {
    1.38  	m_AuthQueue = NULL;
    1.39 @@ -159,6 +181,31 @@
    1.40  	return true;
    1.41  }
    1.42  
    1.43 +bool PlayerManager::CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id)
    1.44 +{
    1.45 +	const char *password = g_Admins.GetAdminPassword(id);
    1.46 +	if (password == NULL)
    1.47 +	{
    1.48 +		return false;
    1.49 +	}
    1.50 +
    1.51 +	if (m_PassInfoVar.size() < 1)
    1.52 +	{
    1.53 +		return false;
    1.54 +	}
    1.55 +
    1.56 +	/* Whoa... the user needs a password! */
    1.57 +	const char *given = engine->GetClientConVarValue(index, m_PassInfoVar.c_str());
    1.58 +	if (!given || strcmp(given, password) != 0)
    1.59 +	{
    1.60 +		return false;
    1.61 +	}
    1.62 +
    1.63 +	pPlayer->SetAdminId(id, false);
    1.64 +
    1.65 +	return true;
    1.66 +}
    1.67 +
    1.68  void PlayerManager::RunAuthChecks()
    1.69  {
    1.70  	CPlayer *pPlayer;
    1.71 @@ -172,24 +219,13 @@
    1.72  			&& (strcmp(authstr, "STEAM_ID_PENDING") != 0))
    1.73  		{
    1.74  			/* Set authorization */
    1.75 -			pPlayer->m_AuthID.assign(authstr);
    1.76 -			pPlayer->m_IsAuthorized = true;
    1.77 +			pPlayer->Authorize(authstr);
    1.78  
    1.79  			/* Mark as removed from queue */
    1.80  			unsigned int client = m_AuthQueue[i];
    1.81  			m_AuthQueue[i] = 0;
    1.82  			removed++;
    1.83  
    1.84 -			/* Do admin lookups */
    1.85 -			if (pPlayer->GetAdminId() == INVALID_ADMIN_ID)
    1.86 -			{
    1.87 -				AdminId id = g_Admins.FindAdminByIdentity("steam", authstr);
    1.88 -				if (id != INVALID_ADMIN_ID)
    1.89 -				{
    1.90 -					CheckSetAdmin(client, pPlayer, id);
    1.91 -				}
    1.92 -			}
    1.93 -
    1.94  			/* Send to extensions */
    1.95  			List<IClientListener *>::iterator iter;
    1.96  			IClientListener *pListener;
    1.97 @@ -211,6 +247,11 @@
    1.98  				m_clauth->PushString(authstr);
    1.99  				m_clauth->Execute(NULL);
   1.100  			}
   1.101 +
   1.102 +			if (pPlayer->IsConnected())
   1.103 +			{
   1.104 +				pPlayer->Authorize_Post();
   1.105 +			}
   1.106  		}
   1.107  	}
   1.108  
   1.109 @@ -303,23 +344,6 @@
   1.110  		}
   1.111  	}
   1.112  
   1.113 -	if (pPlayer->IsConnected())
   1.114 -	{
   1.115 -		/* Do an ip based lookup */
   1.116 -		char ip[24], *ptr;
   1.117 -		strncopy(ip, pszAddress, sizeof(ip));
   1.118 -		if ((ptr = strchr(ip, ':')) != NULL)
   1.119 -		{
   1.120 -			*ptr = '\0';
   1.121 -		}
   1.122 -		
   1.123 -		AdminId id = g_Admins.FindAdminByIdentity("ip", ip);
   1.124 -		if (id != INVALID_ADMIN_ID)
   1.125 -		{
   1.126 -			CheckSetAdmin(client, pPlayer, id);
   1.127 -		}
   1.128 -	}
   1.129 -
   1.130  	return true;
   1.131  }
   1.132  
   1.133 @@ -370,6 +394,15 @@
   1.134  			m_clauth->PushCell(client);
   1.135  			m_clauth->PushString(authid);
   1.136  			m_clauth->Execute(NULL);
   1.137 +			if (!pPlayer->IsConnected())
   1.138 +			{
   1.139 +				return;
   1.140 +			}
   1.141 +		}
   1.142 +		pPlayer->Authorize_Post();
   1.143 +		if (!pPlayer->IsConnected())
   1.144 +		{
   1.145 +			return;
   1.146  		}
   1.147  	}
   1.148  
   1.149 @@ -524,7 +557,46 @@
   1.150  
   1.151  	m_clinfochanged->PushCell(engine->IndexOfEdict(pEntity));
   1.152  	m_clinfochanged->Execute(&res, NULL);
   1.153 -	m_Players[client].SetName(engine->GetClientConVarValue(client, "name"));
   1.154 +
   1.155 +	IPlayerInfo *info = m_Players[client].GetPlayerInfo();
   1.156 +	const char *new_name = info ? info->GetName() : engine->GetClientConVarValue(client, "name");
   1.157 +	const char *old_name = m_Players[client].m_Name.c_str();
   1.158 +
   1.159 +	if (strcmp(old_name, new_name) != 0)
   1.160 +	{
   1.161 +		AdminId id = g_Admins.FindAdminByIdentity("name", new_name);
   1.162 +		if (id != INVALID_ADMIN_ID && m_Players[client].GetAdminId() != id)
   1.163 +		{
   1.164 +			if (!CheckSetAdminName(client, &m_Players[client], id))
   1.165 +			{
   1.166 +				m_Players[client].Kick("Your name is reserved by SourceMod; set your password to use it.");
   1.167 +				RETURN_META(MRES_IGNORED);
   1.168 +			}
   1.169 +		} else if ((id = g_Admins.FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) {
   1.170 +			if (id == m_Players[client].GetAdminId())
   1.171 +			{
   1.172 +				/* This player is changing their name; force them to drop admin privileges! */
   1.173 +				m_Players[client].SetAdminId(INVALID_ADMIN_ID, false);
   1.174 +			}
   1.175 +		}
   1.176 +		m_Players[client].SetName(new_name);
   1.177 +	}
   1.178 +	
   1.179 +	if (m_PassInfoVar.size() > 0)
   1.180 +	{
   1.181 +		/* Try for a password change */
   1.182 +		const char *old_pass = m_Players[client].m_LastPassword.c_str();
   1.183 +		const char *new_pass = engine->GetClientConVarValue(client, m_PassInfoVar.c_str());
   1.184 +		if (strcmp(old_pass, new_pass) != 0)
   1.185 +		{
   1.186 +			m_Players[client].m_LastPassword.assign(new_pass);
   1.187 +			if (m_Players[client].IsInGame() && m_Players[client].IsAuthorized())
   1.188 +			{
   1.189 +				/* If there is already an admin id assigned, this will just bail out. */
   1.190 +				m_Players[client].DoBasicAdminChecks();
   1.191 +			}
   1.192 +		}
   1.193 +	}
   1.194  }
   1.195  
   1.196  int PlayerManager::GetMaxClients()
   1.197 @@ -631,6 +703,10 @@
   1.198  	}
   1.199  }
   1.200  
   1.201 +const char *PlayerManager::GetPassInfoVar()
   1.202 +{
   1.203 +	return m_PassInfoVar.c_str();
   1.204 +}
   1.205  
   1.206  /*******************
   1.207   *** PLAYER CODE ***
   1.208 @@ -645,6 +721,7 @@
   1.209  	m_Admin = INVALID_ADMIN_ID;
   1.210  	m_TempAdmin = false;
   1.211  	m_Info = NULL;
   1.212 +	m_LastPassword.clear();
   1.213  }
   1.214  
   1.215  void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
   1.216 @@ -653,15 +730,48 @@
   1.217  	m_Name.assign(name);
   1.218  	m_Ip.assign(ip);
   1.219  	m_pEdict = pEntity;
   1.220 +
   1.221 +	char ip2[24], *ptr;
   1.222 +	strncopy(ip2, ip, sizeof(ip2));
   1.223 +	if ((ptr = strchr(ip2, ':')) != NULL)
   1.224 +	{
   1.225 +		*ptr = '\0';
   1.226 +	}
   1.227 +	m_IpNoPort.assign(ip2);
   1.228  }
   1.229  
   1.230  void CPlayer::Connect()
   1.231  {
   1.232 +	if (m_IsInGame)
   1.233 +	{
   1.234 +		return;
   1.235 +	}
   1.236 +
   1.237  	m_IsInGame = true;
   1.238 +
   1.239 +	const char *var = g_Players.GetPassInfoVar();
   1.240 +	int client = engine->IndexOfEdict(m_pEdict);
   1.241 +	if (var[0] != '\0')
   1.242 +	{
   1.243 +		const char *pass = engine->GetClientConVarValue(client, var);
   1.244 +		m_LastPassword.assign(pass ? pass : "");
   1.245 +	} else {
   1.246 +		m_LastPassword.assign("");
   1.247 +	}
   1.248 +
   1.249 +	if (m_IsAuthorized)
   1.250 +	{
   1.251 +		DoBasicAdminChecks();
   1.252 +	}
   1.253  }
   1.254  
   1.255  void CPlayer::Authorize(const char *steamid)
   1.256  {
   1.257 +	if (m_IsAuthorized)
   1.258 +	{
   1.259 +		return;
   1.260 +	}
   1.261 +
   1.262  	m_IsAuthorized = true;
   1.263  	m_AuthID.assign(steamid);
   1.264  }
   1.265 @@ -759,3 +869,59 @@
   1.266  		m_TempAdmin = false;
   1.267  	}
   1.268  }
   1.269 +
   1.270 +void CPlayer::Kick(const char *str)
   1.271 +{
   1.272 +	int client = engine->IndexOfEdict(m_pEdict);
   1.273 +	INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(client));
   1.274 +	IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
   1.275 +	pClient->Disconnect("%s", str);
   1.276 +}
   1.277 +
   1.278 +void CPlayer::Authorize_Post()
   1.279 +{
   1.280 +	if (m_IsInGame)
   1.281 +	{
   1.282 +		DoBasicAdminChecks();
   1.283 +	}
   1.284 +}
   1.285 +
   1.286 +void CPlayer::DoBasicAdminChecks()
   1.287 +{
   1.288 +	if (GetAdminId() != INVALID_ADMIN_ID)
   1.289 +	{
   1.290 +		return;
   1.291 +	}
   1.292 +
   1.293 +	/* First check the name */
   1.294 +	AdminId id;
   1.295 +	int client = engine->IndexOfEdict(m_pEdict);
   1.296 +
   1.297 +	if ((id = g_Admins.FindAdminByIdentity("name", GetName())) != INVALID_ADMIN_ID)
   1.298 +	{
   1.299 +		if (!g_Players.CheckSetAdminName(client, this, id))
   1.300 +		{
   1.301 +			int userid = engine->GetPlayerUserId(m_pEdict);
   1.302 +			g_Timers.CreateTimer(&s_KickPlayerTimer, 0.1f, (void *)userid, 0);
   1.303 +		}
   1.304 +		return;
   1.305 +	}
   1.306 +	
   1.307 +	/* Check IP */
   1.308 +	if ((id = g_Admins.FindAdminByIdentity("ip", m_IpNoPort.c_str())) != INVALID_ADMIN_ID)
   1.309 +	{
   1.310 +		if (g_Players.CheckSetAdmin(client, this, id))
   1.311 +		{
   1.312 +			return;
   1.313 +		}
   1.314 +	}
   1.315 +
   1.316 +	/* Check IP address */
   1.317 +	if ((id = g_Admins.FindAdminByIdentity("steam", m_AuthID.c_str())) != INVALID_ADMIN_ID)
   1.318 +	{
   1.319 +		if (g_Players.CheckSetAdmin(client, this, id))
   1.320 +		{
   1.321 +			return;
   1.322 +		}
   1.323 +	}
   1.324 +}