예제 #1
0
static cell_t CanUserTarget(IPluginContext *pContext, const cell_t *params)
{
	int client = params[1];
	int target = params[2];

	if (client == 0)
	{
		return 1;
	}

	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
	if (!pPlayer)
	{
		return pContext->ThrowNativeError("Client index %d is invalid", client);
	} else if (!pPlayer->IsConnected()) {
		return pContext->ThrowNativeError("Client %d is not connected", client);
	}

	CPlayer *pTarget = g_Players.GetPlayerByIndex(target);
	if (!pTarget)
	{
		return pContext->ThrowNativeError("Client index %d is invalid", target);
	} else if (!pTarget->IsConnected()) {
		return pContext->ThrowNativeError("Client %d is not connected", target);
	}

	return g_Admins.CanAdminTarget(pPlayer->GetAdminId(), pTarget->GetAdminId()) ? 1 : 0;
}
void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
{
	cell_t res;
	int client = engine->IndexOfEdict(pEntity);
	CPlayer *pPlayer = &m_Players[client];

	if (!pPlayer->IsConnected())
	{
		return;
	}

	m_clinfochanged->PushCell(engine->IndexOfEdict(pEntity));
	m_clinfochanged->Execute(&res, NULL);

	IPlayerInfo *info = pPlayer->GetPlayerInfo();
	const char *new_name = info ? info->GetName() : engine->GetClientConVarValue(client, "name");
	const char *old_name = pPlayer->m_Name.c_str();

	if (strcmp(old_name, new_name) != 0)
	{
		AdminId id = g_Admins.FindAdminByIdentity("name", new_name);
		if (id != INVALID_ADMIN_ID && pPlayer->GetAdminId() != id)
		{
			if (!CheckSetAdminName(client, pPlayer, id))
			{
				pPlayer->Kick("Your name is reserved by SourceMod; set your password to use it.");
				RETURN_META(MRES_IGNORED);
			}
		} else if ((id = g_Admins.FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) {
			if (id == pPlayer->GetAdminId())
			{
				/* This player is changing their name; force them to drop admin privileges! */
				pPlayer->SetAdminId(INVALID_ADMIN_ID, false);
			}
		}
		pPlayer->SetName(new_name);
	}
	
	if (m_PassInfoVar.size() > 0)
	{
		/* Try for a password change */
		const char *old_pass = pPlayer->m_LastPassword.c_str();
		const char *new_pass = engine->GetClientConVarValue(client, m_PassInfoVar.c_str());
		if (strcmp(old_pass, new_pass) != 0)
		{
			pPlayer->m_LastPassword.assign(new_pass);
			if (pPlayer->IsInGame() && pPlayer->IsAuthorized())
			{
				/* If there is already an admin id assigned, this will just bail out. */
				pPlayer->DoBasicAdminChecks();
			}
		}
	}
}
예제 #3
0
static cell_t RemoveUserFlags(IPluginContext *pContext, const cell_t *params)
{
	int client = params[1];
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
	if (!pPlayer)
	{
		return pContext->ThrowNativeError("Client index %d is invalid", client);
	}
	if (!pPlayer->IsConnected())
	{
		return pContext->ThrowNativeError("Client %d is not connected", client);
	}
	
	AdminId id;
	if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
	{
		return 0;
	}

	cell_t *addr;
	for (int i=2; i<=params[0]; i++)
	{
		pContext->LocalToPhysAddr(params[i], &addr);
		g_Admins.SetAdminFlag(id, (AdminFlag)*addr, false);
	}

	return 1;
}
예제 #4
0
static cell_t RunAdminCacheChecks(IPluginContext *pContext, const cell_t *params)
{
	int client = params[1];

	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
	if (!pPlayer)
	{
		return pContext->ThrowNativeError("Client index %d is invalid", client);
	}
	else if (!pPlayer->IsInGame())
	{
		return pContext->ThrowNativeError("Client %d is not in game", client);
	}
	else if (!pPlayer->IsAuthorized())
	{
		return pContext->ThrowNativeError("Client %d is not authorized", client);
	}

	AdminId id = pPlayer->GetAdminId();
	pPlayer->DoBasicAdminChecks();

	return (id != pPlayer->GetAdminId()) ? 1 : 0;
}
예제 #5
0
bool ConCmdManager::CheckCommandAccess(int client, const char *cmd, FlagBits cmdflags)
{
	if (cmdflags == 0 || client == 0)
	{
		return true;
	}

	/* If running listen server, then client 1 is the server host and should have 'root' access */
	if (client == 1 && !engine->IsDedicatedServer())
	{
		return true;
	}

	CPlayer *player = g_Players.GetPlayerByIndex(client);
	if (!player 
		|| player->GetEdict() == NULL
		|| player->IsFakeClient())
	{
		return false;
	}

	AdminId adm = player->GetAdminId();
	if (adm != INVALID_ADMIN_ID)
	{
		FlagBits bits = g_Admins.GetAdminFlags(adm, Access_Effective);

		/* root knows all, WHOA */
		if ((bits & ADMFLAG_ROOT) == ADMFLAG_ROOT)
		{
			return true;
		}

		/* Check for overrides
		 * :TODO: is it worth optimizing this?
		 */
		unsigned int groups = g_Admins.GetAdminGroupCount(adm);
		GroupId gid;
		OverrideRule rule;
		bool override = false;
		for (unsigned int i=0; i<groups; i++)
		{
			gid = g_Admins.GetAdminGroup(adm, i, NULL);
			/* First get group-level override */
			override = g_Admins.GetGroupCommandOverride(gid, cmd, Override_CommandGroup, &rule);
			/* Now get the specific command override */
			if (g_Admins.GetGroupCommandOverride(gid, cmd, Override_Command, &rule))
			{
				override = true;
			}
예제 #6
0
static cell_t GetUserAdmin(IPluginContext *pContext, const cell_t *params)
{
	int client = params[1];
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
	if (!pPlayer)
	{
		return pContext->ThrowNativeError("Client index %d is invalid", client);
	}
	if (!pPlayer->IsConnected())
	{
		return pContext->ThrowNativeError("Client %d is not connected", client);
	}

	return pPlayer->GetAdminId();
}
예제 #7
0
static cell_t GetUserFlagBits(IPluginContext *pContext, const cell_t *params)
{
	int client = params[1];
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
	if (!pPlayer)
	{
		return pContext->ThrowNativeError("Client index %d is invalid", client);
	}
	if (!pPlayer->IsConnected())
	{
		return pContext->ThrowNativeError("Client %d is not connected", client);
	}

	AdminId id;
	if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
	{
		return 0;
	}

	return g_Admins.GetAdminFlags(id, Access_Effective);
}
예제 #8
0
void ChatTriggers::OnSayCommand_Pre(const CCommandContext &context, const CCommand &command)
{
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void ChatTriggers::OnSayCommand_Pre(const CCommand &command)
{
#else
void ChatTriggers::OnSayCommand_Pre()
{
	CCommand command;
#endif
	int client = g_ConCmds.GetCommandClient();
	m_bIsChatTrigger = false;
	m_bWasFloodedMessage = false;
	m_bPluginIgnored = true;

	const char *args = command.ArgS();

	if (!args)
	{
		RETURN_META(MRES_IGNORED);
	}

	/* Save these off for post hook as the command data returned from the engine in older engine versions 
	 * can be NULL, despite the data still being there and valid. */
	m_Arg0Backup = command.Arg(0);
	size_t len = strlen(args);

#if SOURCE_ENGINE == SE_EPISODEONE
	if (m_bIsINS)
	{
		if (strcmp(m_Arg0Backup, "say2") == 0 && len >= 4)
		{
			args += 4;
			len -= 4;
		}

		if (len == 0)
		{
			RETURN_META(MRES_SUPERCEDE);
		}
	}
#endif

	/* The first pair of quotes are stripped from client say commands, but not console ones.
	 * We do not want the forwards to differ from what is displayed.
	 * So only strip the first pair of quotes from client say commands. */
	bool is_quoted = false;

	if (
#if SOURCE_ENGINE == SE_EPISODEONE
		!m_bIsINS && 
#endif
		client != 0 && args[0] == '"' && args[len-1] == '"')
	{
		/* The server normally won't display empty say commands, but in this case it does.
		 * I don't think it's desired so let's block it. */
		if (len <= 2)
		{
			RETURN_META(MRES_SUPERCEDE);
		}

		args++;
		len--;
		is_quoted = true;
	}

	/* Some? engines strip the last quote when printing the string to chat.
	 * This results in having a double-quoted message passed to the OnClientSayCommand ("message") forward,
	 * but losing the last quote in the OnClientSayCommand_Post ("message) forward.
	 * To compensate this, we copy the args into our own buffer where the engine won't mess with
	 * and strip the quotes. */
	delete [] m_ArgSBackup;
	m_ArgSBackup = new char[CCommand::MaxCommandLength()+1];
	memcpy(m_ArgSBackup, args, len+1);

	/* Strip the quotes from the argument */
	if (is_quoted)
	{
		if (m_ArgSBackup[len-1] == '"')
		{
			m_ArgSBackup[--len] = '\0';
		}
	}

	/* The server console cannot do this */
	if (client == 0)
	{
		if (CallOnClientSayCommand(client) >= Pl_Handled)
		{
			RETURN_META(MRES_SUPERCEDE);
		}

		RETURN_META(MRES_IGNORED);
	}

	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);

	/* We guarantee the client is connected */
	if (!pPlayer || !pPlayer->IsConnected())
	{
		RETURN_META(MRES_IGNORED);
	}

	/* Check if we need to block this message from being sent */
	if (ClientIsFlooding(client))
	{
		char buffer[128];

		if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "Flooding the server", &client))
			UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!");

		/* :TODO: we should probably kick people who spam too much. */

		char fullbuffer[192];
		UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s", buffer);
		g_HL2.TextMsg(client, HUD_PRINTTALK, fullbuffer);

		m_bWasFloodedMessage = true;

		RETURN_META(MRES_SUPERCEDE);
	}

	bool is_trigger = false;
	bool is_silent = false;

	/* Check for either trigger */
	if (m_PubTriggerSize && strncmp(m_ArgSBackup, m_PubTrigger, m_PubTriggerSize) == 0)
	{
		is_trigger = true;
		args = &m_ArgSBackup[m_PubTriggerSize];
	} 
	else if (m_PrivTriggerSize && strncmp(m_ArgSBackup, m_PrivTrigger, m_PrivTriggerSize) == 0) 
	{
		is_trigger = true;
		is_silent = true;
		args = &m_ArgSBackup[m_PrivTriggerSize];
	}

	/**
	 * Test if this is actually a command!
	 */
	if (is_trigger && PreProcessTrigger(PEntityOfEntIndex(client), args))
	{
		m_bIsChatTrigger = true;

		/**
		 * We'll execute it in post.
		 */
		m_bWillProcessInPost = true;
	}

	if (is_silent && (m_bIsChatTrigger || (g_bSupressSilentFails && pPlayer->GetAdminId() != INVALID_ADMIN_ID)))
	{
		RETURN_META(MRES_SUPERCEDE);
	}

	if (CallOnClientSayCommand(client) >= Pl_Handled)
	{
		RETURN_META(MRES_SUPERCEDE);
	}

	/* Otherwise, let the command continue */
	RETURN_META(MRES_IGNORED);
}
예제 #9
0
static cell_t FormatActivitySource(IPluginContext *pContext, const cell_t *params)
{
	int value;
	int client;
	int target;
	CPlayer *pTarget;
	AdminId aidTarget;
	const char *identity[2] = {"Console", "ADMIN"};

	client = params[1];
	target = params[2];

	if ((pTarget = g_Players.GetPlayerByIndex(target)) == NULL)
	{
		return pContext->ThrowNativeError("Invalid client index %d", target);
	}
	if (!pTarget->IsConnected())
	{
		return pContext->ThrowNativeError("Client %d not connected", target);
	}

	value = sm_show_activity.GetInt();

	if (client != 0)
	{
		CPlayer *pPlayer;

		if ((pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
		{
			return pContext->ThrowNativeError("Invalid client index %d", client);
		}
		if (!pPlayer->IsConnected())
		{
			return pContext->ThrowNativeError("Client %d not connected", client);
		}

		identity[0] = pPlayer->GetName();

		AdminId id = pPlayer->GetAdminId();
		if (id == INVALID_ADMIN_ID
			|| !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
		{
			identity[1] = "PLAYER";
		}
	}

	int mode = 1;
	bool bShowActivity = false;

	if ((aidTarget = pTarget->GetAdminId()) == INVALID_ADMIN_ID
		|| !g_Admins.GetAdminFlag(aidTarget, Admin_Generic, Access_Effective))
	{
		/* Treat this as a normal user */
		if ((value & 1) || (value & 2))
		{
			if ((value & 2) || (target == client))
			{
				mode = 0;
			}
			bShowActivity = true;
		}
	}
	else
	{
		/* Treat this as an admin user */
		bool is_root = g_Admins.GetAdminFlag(aidTarget, Admin_Root, Access_Effective);
		if ((value & 4) 
			|| (value & 8)
			|| ((value & 16) && is_root))
		{
			if ((value & 8) || ((value & 16) && is_root) || (target == client))
			{
				mode = 0;
			}
			bShowActivity = true;
		}
	}

	/* Otherwise, send it back to the script. */
	pContext->StringToLocalUTF8(params[3], params[4], identity[mode], NULL);

	return bShowActivity ? 1 : 0;
}
예제 #10
0
static cell_t _ShowActivity2(IPluginContext *pContext,
							 const cell_t *params,
							 const char *tag,
							 cell_t fmt_param)
{
	char message[255];
	char buffer[255];
	int value = sm_show_activity.GetInt();
	unsigned int replyto = g_ChatTriggers.GetReplyTo();
	int client = params[1];

	const char *name = "Console";
	const char *sign = "ADMIN";
	if (client != 0)
	{
		CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
		if (!pPlayer || !pPlayer->IsConnected())
		{
			return pContext->ThrowNativeError("Client index %d is invalid", client);
		}
		name = pPlayer->GetName();
		AdminId id = pPlayer->GetAdminId();
		if (id == INVALID_ADMIN_ID
			|| !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
		{
			sign = "PLAYER";
		}

		g_SourceMod.SetGlobalTarget(client);
		g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);

		if (pContext->GetLastNativeError() != SP_ERROR_NONE)
		{
			return 0;
		}

		/* We don't display directly to the console because the chat text 
		 * simply gets added to the console, so we don't want it to print 
		 * twice.
		 */
		if (replyto == SM_REPLY_CONSOLE)
		{
#if 0
			UTIL_Format(message, sizeof(message), "%s%s\n", tag, buffer);
			engine->ClientPrintf(pPlayer->GetEdict(), message);
#endif
			UTIL_Format(message, sizeof(message), "%s%s", tag, buffer);
			g_HL2.TextMsg(client, HUD_PRINTTALK, message);
		}
		else
		{
			UTIL_Format(message, sizeof(message), "%s%s", tag, buffer);
			g_HL2.TextMsg(client, HUD_PRINTTALK, message);
		}
	}
	else
	{
		g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
		g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);

		if (pContext->GetLastNativeError() != SP_ERROR_NONE)
		{
			return 0;
		}

		UTIL_Format(message, sizeof(message), "%s%s\n", tag, buffer);
		META_CONPRINT(message);
	}

	if (!value)
	{
		return 1;
	}

	int maxClients = g_Players.GetMaxClients();
	for (int i=1; i<=maxClients; i++)
	{
		CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
		if (!pPlayer->IsInGame() 
			|| pPlayer->IsFakeClient()
			|| i == client)
		{
			continue;
		}
		AdminId id = pPlayer->GetAdminId();
		g_SourceMod.SetGlobalTarget(i);
		if (id == INVALID_ADMIN_ID
			|| !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
		{
			/* Treat this as a normal user */
			if ((value & 1) || (value & 2))
			{
				const char *newsign = sign;
				if ((value & 2))
				{
					newsign = name;
				}
				g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);

				if (pContext->GetLastNativeError() != SP_ERROR_NONE)
				{
					return 0;
				}

				UTIL_Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
				g_HL2.TextMsg(i, HUD_PRINTTALK, message);
			}
		}
		else
		{
			/* Treat this as an admin user */
			bool is_root = g_Admins.GetAdminFlag(id, Admin_Root, Access_Effective);
			if ((value & 4) 
				|| (value & 8)
				|| ((value & 16) && is_root))
			{
				const char *newsign = sign;
				if ((value & 8) || ((value & 16) && is_root))
				{
					newsign = name;
				}
				g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);

				if (pContext->GetLastNativeError() != SP_ERROR_NONE)
				{
					return 0;
				}

				UTIL_Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
				g_HL2.TextMsg(i, HUD_PRINTTALK, message);
			}
		}
	}

	return 1;
}
예제 #11
0
void ChatTriggers::OnSayCommand_Pre(const CCommand &command)
{
#else
void ChatTriggers::OnSayCommand_Pre()
{
	CCommand command;
#endif
	int client;
	CPlayer *pPlayer;
	
	client = g_ConCmds.GetCommandClient();
	m_bIsChatTrigger = false;
	m_bWasFloodedMessage = false;

	/* The server console cannot do this */
	if (client == 0 || (pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
	{
		RETURN_META(MRES_IGNORED);
	}

	/* We guarantee the client is connected */
	if (!pPlayer->IsConnected())
	{
		RETURN_META(MRES_IGNORED);
	}

	const char *args = command.ArgS();
	
	if (!args)
	{
		RETURN_META(MRES_IGNORED);
	}

	/* Check if we need to block this message from being sent */
	if (ClientIsFlooding(client))
	{
		char buffer[128];

		/* :TODO: log an error? */
		if (g_Translator.CoreTransEx(g_pFloodPhrases, 
			client, 
			buffer, 
			sizeof(buffer),
			"Flooding the server",
			NULL,
			NULL)
			!= Trans_Okay)
		{
			UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!");
		}

		/* :TODO: we should probably kick people who spam too much. */

		char fullbuffer[192];
		UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s", buffer);
		g_HL2.TextMsg(client, HUD_PRINTTALK, fullbuffer);

		m_bWasFloodedMessage = true;

		RETURN_META(MRES_SUPERCEDE);
	}

	/* Handle quoted string sets */
	bool is_quoted = false;
	if (args[0] == '"')
	{
		args++;
		is_quoted = true;
	}

	bool is_trigger = false;
	bool is_silent = false;

	/* Check for either trigger */
	if (m_PubTriggerSize && strncmp(args, m_PubTrigger, m_PubTriggerSize) == 0)
	{
		is_trigger = true;
		args = &args[m_PubTriggerSize];
	} 
	else if (m_PrivTriggerSize && strncmp(args, m_PrivTrigger, m_PrivTriggerSize) == 0) 
	{
		is_trigger = true;
		is_silent = true;
		args = &args[m_PrivTriggerSize];
	}

	if (!is_trigger)
	{
		RETURN_META(MRES_IGNORED);
	}

	/**
	 * Test if this is actually a command!
	 */
	if (!PreProcessTrigger(engine->PEntityOfEntIndex(client), args, is_quoted))
	{
		CPlayer *pPlayer;
		if (is_silent 
			&& g_bSupressSilentFails 
			&& client != 0
			&& (pPlayer = g_Players.GetPlayerByIndex(client)) != NULL
			&& pPlayer->GetAdminId() != INVALID_ADMIN_ID)
		{
			RETURN_META(MRES_SUPERCEDE);
		}
		RETURN_META(MRES_IGNORED);
	}

	m_bIsChatTrigger = true;

	/**
	 * We'll execute it in post.
	 */
	m_bWillProcessInPost = true;
	m_bTriggerWasSilent = is_silent;

	/* If we're silent, block */
	if (is_silent)
	{
		RETURN_META(MRES_SUPERCEDE);
	}

	/* Otherwise, let the command continue */
	RETURN_META(MRES_IGNORED);
}