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(); } } } }
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; }
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; }
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; }
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(); }
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); }
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); }
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; }
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; }
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); }