· 8 years ago · Apr 01, 2018, 01:20 AM
1// Compilation Settings
2//#define CTBAN_DEBUG
3
4#define PLUGIN_VERSION "2.0.43"
5
6#include <sourcemod>
7#include <clientprefs>
8#include <sdktools>
9#include <adminmenu>
10#include <cstrike>
11
12#tryinclude <hosties>
13#tryinclude <ctban>
14
15#if !defined _CTBan_Included_
16
17 // Common constant verifications
18 #if !defined INVALID_WEAPON
19 #define INVALID_WEAPON -1
20 #else
21 #assert INVALID_WEAPON == -1
22 #endif
23 #if !defined ZERO
24 #define ZERO 0
25 #else
26 #assert ZERO == 0
27 #endif
28 #if !defined ONE
29 #define ONE 1
30 #else
31 #assert ONE == 1
32 #endif
33 #if !defined TWO 2
34 #define TWO 2
35 #else
36 #assert TWO == 2
37 #endif
38 #if !defined THREE
39 #define THREE 3
40 #else
41 #assert THREE == 3
42 #endif
43 #if !defined FOUR
44 #define FOUR 4
45 #else
46 #assert FOUR == 4
47 #endif
48 #if !defined FIVE
49 #define FIVE 5
50 #else
51 #assert FIVE == 5
52 #endif
53 #if !defined SIX
54 #define SIX 6
55 #else
56 #assert SIX == 6
57 #endif
58 #if !defined SEVEN
59 #define SEVEN 7
60 #else
61 #assert SEVEN == 7
62 #endif
63
64 // General constants
65 #define VALUE_NOT_FOUND_IN_ARRAY -1
66 #define SUBSTRING_NOT_FOUND -1
67 #define RAGEBAN_ADMIN_LEVEL ADMFLAG_SLAY
68 #define CTBAN_ADMIN_LEVEL ADMFLAG_SLAY
69 #define UNCTBAN_ADMIN_LEVEL ADMFLAG_SLAY
70 #define FORCECT_ADMIN_LEVEL ADMFLAG_SLAY
71 #define UNFORCECT_ADMIN_LEVEL ADMFLAG_SLAY
72 #define JOINFAILREASON_ONECHANGE 0
73 #define MENUCHOICE_USERID 0
74 #define MENUCHOICE_TIME 1
75 #define CALLER_NATIVE -2
76 #define COOKIE_BANNED_STRING "1"
77 #define COOKIE_UNBANNED_STRING "0"
78 #define ARG_ZERO_GET_COMMAND_NAME 0
79 #define FORCECT_ARG_TARGET 1
80 #define UNFORCECT_ARG_TARGET 1
81 #define ISBANNED_ARG_TARGET 1
82 #define CTBAN_ARG_PLAYER 1
83 #define CTBAN_ARG_TIME 2
84 #define CTBAN_ARG_REASON 3
85 #define CTBAN_NO_REASON_GIVEN -1
86 #define CTBAN_PERM_BAN_LENGTH 0
87 #define RAGEBAN_ARG_CONSOLE_TARGET 1
88 #define UNCTBAN_ARG_TARGET 1
89 #define CHANGE_TIME_ARG_TARGET 1
90 #define CHANGE_TIME_ARG_TIME 2
91 #define JOINTEAM_ARG_TEAM_STRING 1
92 #define CLIENT_DISCONNECT_CB_FIELD_TIMELEFT 0
93 #define FIND_COOKIE_CB_FIELD_COOKIE_ID 0
94 #define CLIENT_AUTHED_CB_FIELD_TIMELEFT 0
95 #define ISBANNED_CB_FIELD_TIMESTAMP 0
96 #define ISBANNED_CB_FIELD_ADMINNAME 1
97 #define ISBANNED_CB_FIELD_REASON 2
98 #define ISBANNED_OFF_CB_FIELD_TIMESTAMP 0
99 #define ISBANNED_OFF_CB_FIELD_ADMINNAME 1
100 #define ISBANNED_OFF_CB_FIELD_REASON 2
101 #define ISBANNED_OFF_CB_FIELD_TIMELEFT 3
102 #define ISBANNED_OFF_CB_FIELD_PERPNAME 4
103 #define NATIVE_ISBANNED_CELL_CLIENT 1
104 #define NATIVE_GET_TIMELEFT_CELL_CLIENT 1
105 #define NATIVE_GET_OVERRIDE_CELL_CLIENT 1
106 #define NATIVE_GETBANINFO_CELL_CLIENT 1
107 #define NATIVE_GETBANINFO_OFF_STR_AUTHID 1
108 #define NATIVE_CTBAN_CELL_CLIENT 1
109 #define NATIVE_CTBAN_CELL_TIME 2
110 #define NATIVE_CTBAN_CELL_ADMIN 3
111 #define NATIVE_CTBAN_STR_REASON 4
112 #define NATIVE_CTBAN_OFF_STR_AUTHID 1
113 #define NATIVE_CHANGE_TIME_CELL_CLIENT 1
114 #define NATIVE_CHANGE_TIME_CELL_TIME 2
115 #define NATIVE_CHANGE_TIME_CELL_ADMIN 3
116 #define NATIVE_UNBAN_CELL_CLIENT 1
117 #define NATIVE_UNBAN_CELL_ADMIN 2
118 #define NATIVE_UNBAN_OFF_STR_AUTHID 1
119 #define NATIVE_FORCECT_CELL_CLIENT 1
120 #define NATIVE_FORCECT_CELL_ADMIN 2
121 #define NATIVE_UNFORCECT_CELL_CLIENT 1
122 #define NATIVE_UNFORCECT_CELL_ADMIN 2
123 #define NATIVE_MIN_AUTHID_LENGTH 3
124 #define FIELD_AUTHID_MAXLENGTH 22
125 #define FIELD_NAME_MAXLENGTH 32
126 #define FIELD_REASON_MAXLENGTH 200
127 #define QUERY_MAXLENGTH 350
128 #define COOKIE_INIT_CHECK_TIME 0.0
129 #define COOKIE_RESCAN_TIME 5.0
130 #define DELAY_ENFORCEMENT_TIME 1.8
131 #define AUTH_RESCAN_TIME 4.0
132 #define DECREMENT_TIMEBAN_INTERVAL 60.0
133 #define PLAY_COMMAND_STRING "play "
134 #define PLAY_COMMAND_STRING_LENGTH 5
135 #define CSGO_MAX_PAGE_MENU_ITEMS 6
136 #define CSS_MAX_PAGE_MENU_ITEMS 7
137 #define CTBAN_COMMAND "sm_ctban"
138 #define REMOVECTBAN_COMMAND "sm_removectban"
139 #define RAGEBAN_COMMAND "sm_rageban"
140 #define FORCECT_COMMAND "sm_forcect"
141 #define UNFORCECT_COMMAND "sm_unforcect"
142 #define MAX_UNBAN_CMD_LENGTH 16
143 #define MAX_TABLE_LENGTH 32
144 #define MAX_DEFAULT_TABLE_LENGTH 12
145 #define MAX_CHAT_BANNER_LENGTH 36
146 #define MAX_RESET_ARG_LENGTH 10
147 #define MAX_USERID_LENGTH 32
148 #define MAX_COOKIE_STR_LENGTH 7
149 #define MAX_JOINTEAM_ARG_LENGTH 5
150 #define MAX_TIME_ARG_LENGTH 32
151 #define MAX_TIME_INFO_STR_LENGTH 150
152 #define MAX_JOIN_BAN_MSG_LENGTH 100
153 #define MAX_ADMINFLAGS_LENGTH 27
154 #define MAX_REASON_MENU_CHOICE_LENGTH 10
155 #define MAX_MENU_INT_CHOICE_LENGTH 4
156 #define MAX_DATABASE_ID_LENGTH 7
157 #define CTBAN_ADMIN_IS_CONSOLE 0
158 #define CONSOLE_USER_NAME "Console"
159 #define CONSOLE_AUTHID "STEAM_0:1:1"
160 #define RAGEBAN_LOG_REASON "Rage ban"
161 #define OFFLINE_NAME_UNAVAILBLE "Unavailable"
162 #define REASON_OFFLINECTBAN "Offline AuthId Ban"
163 #define CALLER_DO_NOT_REPLY -1
164
165 // Pre-processor macros
166 #define MAX_SAFE_ESCAPE_QUERY(%1) (TWO*(%1)+ONE)
167
168#endif
169
170// SQL Queries
171#define CTBAN_QUERY_CP_FIND_COOKIE_ID "SELECT id FROM sm_cookies WHERE name = 'Banned_From_CT'"
172#define CTBAN_QUERY_CP_SELECT_BAN_COOKIE "SELECT value FROM sm_cookie_cache WHERE player = '%s' and cookie_id = '%i'"
173#define CTBAN_QUERY_CP_RESET_COOKIES "UPDATE sm_cookie_cache SET value = '' WHERE cookie_id = '%i'"
174
175#define CTBAN_QUERY_TIME_CREATE "CREATE TABLE IF NOT EXISTS %s (steamid VARCHAR(%d), ctbantime INT(16), PRIMARY KEY (steamid))"
176#define CTBAN_QUERY_TIME_SELECT_BANTIME "SELECT ctbantime FROM %s WHERE steamid = '%s'"
177#define CTBAN_QUERY_TIME_INSERT_SQLITE "INSERT OR REPLACE INTO %s (steamid, ctbantime) VALUES ('%s', %d)"
178#define CTBAN_QUERY_TIME_INSERT_MYSQL "INSERT INTO %s (steamid, ctbantime) VALUES ('%s', %d) ON DUPLICATE KEY UPDATE ctbantime=%d"
179#define CTBAN_QUERY_TIME_UPDATE "UPDATE %s SET ctbantime = %d WHERE steamid = '%s'"
180#define CTBAN_QUERY_TIME_DELETE "DELETE FROM %s WHERE steamid = '%s'"
181
182#define CTBAN_QUERY_LOG_CREATE "CREATE TABLE IF NOT EXISTS %s (ban_id INT UNSIGNED AUTO_INCREMENT, timestamp INT, perp_steamid VARCHAR(%d), perp_name VARCHAR(%d), admin_steamid VARCHAR(%d), admin_name VARCHAR(%d), bantime INT(16), timeleft INT(16), reason VARCHAR(%d), PRIMARY KEY (ban_id))"
183#define CTBAN_QUERY_LOG_INSERT "INSERT INTO %s (timestamp, perp_steamid, perp_name, admin_steamid, admin_name, bantime, timeleft, reason) VALUES (%d, '%s', '%s', '%s', '%s', %d, %d, '%s')"
184#define CTBAN_QUERY_LOG_ISBANNED "SELECT timestamp, admin_name, reason FROM %s WHERE perp_steamid = '%s' AND timeleft >= 0 ORDER BY timestamp DESC LIMIT 1"
185#define CTBAN_QUERY_LOG_ISBANNED_OFFLINE "SELECT timestamp, admin_name, reason, timeleft, perp_name FROM %s WHERE perp_steamid = '%s' AND timeleft >= 0 ORDER BY timestamp DESC LIMIT 1"
186#define CTBAN_QUERY_LOG_EXPIRE "UPDATE %s SET timeleft=-1 WHERE perp_steamid = '%s' and timeleft >= 0"
187#define CTBAN_QUERY_LOG_V1_CHECK "SELECT ban_id FROM %s LIMIT 1"
188#define CTBAN_QUERY_LOG_TO_V2_DROPKEY "ALTER TABLE %s DROP PRIMARY KEY"
189#define CTBAN_QUERY_LOG_TO_V2_ADD_BANID "ALTER TABLE %s ADD ban_id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT FIRST"
190#define CTBAN_QUERY_LOG_UPDATE "UPDATE %s SET timeleft = %d WHERE perp_steamid = '%s' AND timeleft >= 0"
191#define CTBAN_QUERY_LOG_TIME_TO_PERM_MYSQL "UPDATE %s SET (bantime, timeleft) VALUES (0, 0) WHERE perp_steamid = '%s' AND timeleft > 0"
192#define CTBAN_QUERY_LOG_TIME_TO_PERM_SQLITE "UPDATE %s SET bantime = 0, timeleft = 0 WHERE perp_steamid = '%s' AND timeleft > 0"
193#define CTBAN_QUERY_LOG_PERM_TO_TIME_MYSQL "UPDATE %s SET (bantime, timeleft) VALUES (%d, %d) WHERE perp_steamid = '%s' AND timeleft = 0 AND bantime = 0"
194#define CTBAN_QUERY_LOG_PERM_TO_TIME_SQLITE "UPDATE %s SET bantime = %d, timeleft = %d WHERE perp_steamid = '%s' AND timeleft = 0 AND bantime = 0"
195
196#pragma semicolon 1
197//#pragma newdecls required
198
199char g_sChatBanner[MAX_CHAT_BANNER_LENGTH];
200EngineVersion g_EngineVersion = Engine_Unknown;
201Handle g_CT_Cookie = INVALID_HANDLE;
202Handle zCookie = INVALID_HANDLE;
203Handle gH_TopMenu = INVALID_HANDLE;
204Handle gH_Cvar_SoundName = INVALID_HANDLE;
205char gS_SoundPath[PLATFORM_MAX_PATH];
206Handle gH_Cvar_JoinBanMessage = INVALID_HANDLE;
207Handle gH_Cvar_Database_Driver = INVALID_HANDLE;
208Handle gA_DNames = INVALID_HANDLE;
209Handle gA_DSteamIDs = INVALID_HANDLE;
210Handle gH_CP_DataBase = INVALID_HANDLE;
211Handle gH_BanDatabase = INVALID_HANDLE;
212Handle gH_Cvar_Table_Prefix = INVALID_HANDLE;
213int g_iCookieIndex;
214bool g_bAuthIdNativeExists = false;
215Handle gA_TimedBanLocalList = INVALID_HANDLE;
216int gA_LocalTimeRemaining[MAXPLAYERS+ONE];
217char g_sLogTableName[MAX_TABLE_LENGTH];
218char g_sTimesTableName[MAX_TABLE_LENGTH];
219Handle gH_Cvar_Force_Reason = INVALID_HANDLE;
220Handle gH_DArray_Reasons = INVALID_HANDLE;
221Handle gH_KV_BanLengths = INVALID_HANDLE;
222Handle gH_Cvar_CheckCTBans_Flags = INVALID_HANDLE;
223Handle gH_Cvar_IsBanned_Self = INVALID_HANDLE;
224Handle gH_Cvar_Respawn = INVALID_HANDLE;
225bool g_bA_Temp_CTBan_Override[MAXPLAYERS+ONE];
226bool g_bIgnoreOverrideResets;
227bool g_bRageBanArrayChanged;
228bool zban[MAXPLAYERS+ONE];
229
230Handle g_hFrwd_OnForceCT = INVALID_HANDLE;
231Handle g_hFrwd_OnUnforceCT = INVALID_HANDLE;
232Handle g_hFrwd_OnCTBan_Offline = INVALID_HANDLE;
233Handle g_hFrwd_OnUnCTBan_Offline = INVALID_HANDLE;
234Handle g_hFrwd_OnCTBan = INVALID_HANDLE;
235Handle g_hFrwd_OnUnCTBan = INVALID_HANDLE;
236Handle g_hFrwd_CTBanInfo = INVALID_HANDLE;
237Handle g_hFrwd_CTBanInfoOffline = INVALID_HANDLE;
238
239enum eCTBanMenuHandler
240{
241 e_RemoveCTBan=ZERO,
242 e_CTBanList=ONE,
243 e_ForceCT=TWO
244}
245
246enum eQueryCallback
247{
248 e_QueryLogTableTwo=ZERO
249}
250
251enum eDatabaseType
252{
253 e_Unknown=ZERO,
254 e_MySQL=ONE,
255 e_SQLite=TWO
256}
257
258eDatabaseType g_eDatabaseType = e_Unknown;
259
260public Plugin myinfo =
261{
262 name = "CT Ban",
263 author = "databomb",
264 description = "Allows admins to ban players from joining the CT team.",
265 version = PLUGIN_VERSION,
266 url = "https://forums.alliedmods.net/showthread.php?t=166080"
267};
268
269public APLRes AskPluginLoad2(Handle hMyself, bool bLate, char[] sError, int iErr_Max)
270{
271 g_EngineVersion = GetEngineVersion();
272
273 SetCTBanChatBanner(g_EngineVersion, g_sChatBanner);
274
275 RegPluginLibrary("ctban");
276
277 CreateForwards();
278 CreateNatives();
279
280 return APLRes_Success;
281}
282
283public void OnPluginStart()
284{
285 CreateConVar("sm_ctban_version", PLUGIN_VERSION, "CT Ban Version", FCVAR_SPONLY|FCVAR_DONTRECORD|FCVAR_REPLICATED|FCVAR_NOTIFY);
286 gH_Cvar_SoundName = CreateConVar("sm_ctban_soundfile", "buttons/button11.wav", "The name of the sound to play when an action is denied.", FCVAR_NONE);
287 gH_Cvar_JoinBanMessage = CreateConVar("sm_ctban_joinbanmsg", "Kivagy tiltva a CT csapatból.", "This text is appended to the time the user was last CT banned when they join T or Spectator teams.", FCVAR_NONE);
288 gH_Cvar_Table_Prefix = CreateConVar("sm_ctban_table_prefix", "", "Adds a prefix to the CT Bans table, leave this blank unless you have a need to add a prefix for multiple servers on one database.", FCVAR_NONE);
289 gH_Cvar_Database_Driver = CreateConVar("sm_ctban_database_driver", "ctbans", "Specifies the configuration driver to use from SourceMod's database.cfg", FCVAR_NONE);
290 gH_Cvar_Force_Reason = CreateConVar("sm_ctban_force_reason", "1", "Specifies whether to force admins to specify a reason when using CTBan command", FCVAR_NONE);
291 gH_Cvar_CheckCTBans_Flags = CreateConVar("sm_ctban_checkctbans_adminflags", "", "The admin flag(s) that may use !isbanned command on anyone. Blank allows all players access on anyone.", FCVAR_NONE);
292 gH_Cvar_IsBanned_Self = CreateConVar("sm_ctban_isbanned_selftarget", "1", "Specifies whether to allow non-admins to use !isbanned on themselves.", FCVAR_NONE);
293 gH_Cvar_Respawn = CreateConVar("sm_ctban_respawn", "0", "Specifies whether players are respawned after being team changed.", FCVAR_NONE);
294
295 AutoExecConfig(true, "ctban");
296
297 g_CT_Cookie = RegClientCookie("Banned_From_CT", "Tells if you are restricted from joining the CT team", CookieAccess_Protected);
298 zCookie = RegClientCookie("rootban", "Tells if you a root admin banned you", CookieAccess_Protected);
299
300 RegConsoleCmd("sm_isbanned", Command_IsBanned, "sm_isbanned <player> - Lets you know if a player is banned from CT team.");
301 RegConsoleCmd("sm_ctbanlist", Command_CTBanList, "sm_ctbanlist - Displays a list of active players who are CT Banned.");
302 RegConsoleCmd("sm_ctbans", Command_CTBanList, "sm_ctbans - Displays a list of active players who are CT Banned.");
303 RegConsoleCmd("sm_teambans", Command_CTBanList, "sm_teambans - Displays a list of active players who are CT Banned.");
304
305 RegAdminCmd(CTBAN_COMMAND, Command_CTBan, CTBAN_ADMIN_LEVEL, "sm_ctban <player> <time> <optional: reason> - Bans a player from being a CT.");
306 RegAdminCmd(REMOVECTBAN_COMMAND, Command_UnCTBan, UNCTBAN_ADMIN_LEVEL, "sm_removectban <player> - Unrestricts a player from being a CT.");
307 RegAdminCmd("sm_unctban", Command_UnCTBan, UNCTBAN_ADMIN_LEVEL, "sm_unctban <player> - Unrestricts a player from being a CT.");
308 RegAdminCmd(RAGEBAN_COMMAND, Command_RageBan, RAGEBAN_ADMIN_LEVEL, "sm_rageban <player> - Allows you to ban those who rage quit.");
309 RegAdminCmd("sm_ctban_offline", Command_Offline_CTBan, ADMFLAG_KICK, "sm_ctban_offline <steamid> - Allows admins to CT Ban players who have long left the server using their Steam Id.");
310 RegAdminCmd("sm_unctban_offline", Command_Offline_UnCTBan, ADMFLAG_KICK, "sm_unctban_offline <steamid> - Allows admins to remove CT Bans on players who have long left the server using their Steam Id.");
311 RegAdminCmd("sm_removectban_offline", Command_Offline_UnCTBan, ADMFLAG_KICK, "sm_unctban_offline <steamid> - Allows admins to remove CT Bans on players who have long left the server using their Steam Id.");
312 RegAdminCmd("sm_reset_ctban_cookies", Command_ResetCookies, ADMFLAG_ROOT, "sm_reset_ctban_cookies <'force'> - Allows the admin to reset all CTBan cookies to be unbanned.");
313 RegAdminCmd(FORCECT_COMMAND, Command_ForceCT, FORCECT_ADMIN_LEVEL, "sm_forcect <player> - Temporarily overrides CTBan status and swaps player to CT team.");
314 RegAdminCmd(UNFORCECT_COMMAND, Command_UnForceCT, UNFORCECT_ADMIN_LEVEL, "sm_unforcect <player> - Removes any temporary overrides and removes player from CT team.");
315 RegAdminCmd("sm_isbanned_offline", Command_Offline_IsBanned, ADMFLAG_SLAY, "sm_isbanned_offline <steamid> - Allows admins to get CT Ban information on offline players user their Steam Id.");
316 RegAdminCmd("sm_change_ctban_time", Command_Change_CTBan_Time, ADMFLAG_KICK, "sm_change_ctban_time <player> <time> - Allows the admin to change the time remaining for an existing CTBan.");
317
318 LoadTranslations("ctban.phrases");
319 LoadTranslations("common.phrases");
320 LoadTranslations("clientprefs.phrases");
321 LoadTranslations("core.phrases");
322
323 // create arrays for the rage bans
324 gA_DNames = CreateArray(MAX_TARGET_LENGTH);
325 gA_DSteamIDs = CreateArray(22);
326 g_iCookieIndex = ZERO;
327
328 // Hook this to block joins when player is banned
329 AddCommandListener(Command_CheckJoin, "jointeam");
330 // This is the only sane way to deal with CS:GO auto-assign and plugin conflicts as in CS:GO Team Limit Bypass
331 HookEvent("player_spawn", Event_PlayerSpawn, EventHookMode_Post);
332 // This will catch anyone that gets swapped manually
333 HookEvent("player_team", Event_PlayerTeam, EventHookMode_Post);
334
335 // create local array for timed bans
336 // block 0: client index
337 gA_TimedBanLocalList = CreateArray(2);
338 char sAuthID[FIELD_AUTHID_MAXLENGTH];
339 for (int iIndex = ONE; iIndex <= MaxClients; iIndex++)
340 {
341 gA_LocalTimeRemaining[iIndex] = ZERO;
342
343 // Check if we need to remove anyone from CT team immediately
344 if (IsClientInGame(iIndex))
345 {
346 if (GetClientTeam(iIndex) == CS_TEAM_CT && GetCTBanStatus(iIndex))
347 {
348 EnforceCTBan(iIndex);
349
350 // Gather the time component, if needed
351 if (IsClientAuthorized(iIndex))
352 {
353 GetClientAuthId(iIndex, AuthId_Steam2, sAuthID, sizeof(sAuthID));
354 OnClientAuthorized(iIndex, sAuthID);
355 }
356 }
357 }
358 }
359
360 // periodic timer to handle timed bans
361 CreateTimer(DECREMENT_TIMEBAN_INTERVAL, Timer_CheckTimedCTBans, _, TIMER_REPEAT);
362
363 // Account for late loading
364 Handle hTopMenu;
365 if (LibraryExists("adminmenu") && ((hTopMenu = GetAdminTopMenu()) != INVALID_HANDLE))
366 {
367 OnAdminMenuReady(hTopMenu);
368 }
369
370 gH_DArray_Reasons = CreateArray(FIELD_REASON_MAXLENGTH);
371
372 if (g_EngineVersion == Engine_CSGO)
373 {
374 HookEvent("jointeam_failed", Event_JoinTeamFailed, EventHookMode_Pre);
375 }
376
377 AddMultiTargetFilter("@ctban", Filter_CTBanned_Players, "CT Banned Players", false);
378 AddMultiTargetFilter("@!ctban", Filter_NotCTBanned_Players, "Players without a CT Ban", false);
379 AddMultiTargetFilter("@noctbans", Filter_NeverCTBanned_Players, "Players who have never had a CT Ban", false);
380}
381
382public bool Filter_CTBanned_Players(const char[] sPattern, Handle hClients)
383{
384 for (int iIndex = ONE; iIndex <= MaxClients; iIndex++)
385 {
386 if (IsClientInGame(iIndex))
387 {
388 if (GetCTBanStatus(iIndex))
389 {
390 PushArrayCell(hClients, iIndex);
391 }
392 }
393 }
394
395 return true;
396}
397
398public bool Filter_NotCTBanned_Players(const char[] sPattern, Handle hClients)
399{
400 for (int iIndex = ONE; iIndex <= MaxClients; iIndex++)
401 {
402 if (IsClientInGame(iIndex))
403 {
404 if (!GetCTBanStatus(iIndex))
405 {
406 PushArrayCell(hClients, iIndex);
407 }
408 }
409 }
410
411 return true;
412}
413
414public bool Filter_NeverCTBanned_Players(const char[] sPattern, Handle hClients)
415{
416 for (int iIndex = ONE; iIndex <= MaxClients; iIndex++)
417 {
418 if (IsClientInGame(iIndex))
419 {
420 if (AreClientCookiesCached(iIndex))
421 {
422 char sCookie[MAX_COOKIE_STR_LENGTH];
423 GetClientCookie(iIndex, g_CT_Cookie, sCookie, sizeof(sCookie));
424
425 if (!strlen(sCookie))
426 {
427 PushArrayCell(hClients, iIndex);
428 }
429 }
430 }
431 }
432
433 return true;
434}
435
436void CreateNatives()
437{
438 CreateNative("CTBan_IsClientBanned", Native_IsClientBanned);
439 CreateNative("CTBan_GetTimeRemaining", Native_GetTimeRemaining);
440 CreateNative("CTBan_GetOverrideStatus", Native_GetOverrideStatus);
441 CreateNative("CTBan_GetBanInfo", Native_GetBanInfo);
442 CreateNative("CTBan_GetBanInfo_Offline", Native_GetBanInfo_Offline);
443
444 CreateNative("CTBan_Client", Native_CTBan_Client);
445 CreateNative("CTBan_Client_Offline", Native_CTBan_Client_Offline);
446 CreateNative("CTBan_ChangeBanLength", Native_CTBan_ChangeBanLength);
447
448 CreateNative("CTBan_UnbanClient", Native_CTBan_UnbanClient);
449 CreateNative("CTBan_UnbanClient_Offline", Native_CTBan_UnbanClient_Offline);
450
451 CreateNative("CTBan_ForceCT", Native_CTBan_ForceCT);
452 CreateNative("CTBan_UnForceCT", Native_CTBan_UnForceCT);
453}
454
455void CreateForwards()
456{
457 g_hFrwd_OnForceCT = CreateGlobalForward("CTBan_OnForceCT", ET_Ignore, Param_Cell, Param_Cell);
458 g_hFrwd_OnUnforceCT = CreateGlobalForward("CTBan_OnUnforceCT", ET_Ignore, Param_Cell, Param_Cell);
459
460 g_hFrwd_OnCTBan = CreateGlobalForward("CTBan_OnClientBan", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_String);
461 g_hFrwd_OnCTBan_Offline = CreateGlobalForward("CTBan_OnClientBan_Offline", ET_Ignore, Param_String, Param_Cell);
462
463 g_hFrwd_OnUnCTBan = CreateGlobalForward("CTBan_OnClientUnban", ET_Ignore, Param_Cell, Param_Cell);
464 g_hFrwd_OnUnCTBan_Offline = CreateGlobalForward("CTBan_OnClientUnban_Offline", ET_Ignore, Param_String, Param_Cell);
465
466 g_hFrwd_CTBanInfo = CreateGlobalForward("CTBan_GetBanInfoReturn", ET_Ignore, Param_Cell, Param_Cell, Param_Cell, Param_Cell, Param_String, Param_String);
467 g_hFrwd_CTBanInfoOffline = CreateGlobalForward("CTBan_GetOfflineBanInfoReturn", ET_Ignore, Param_Cell, Param_String, Param_Cell, Param_Cell, Param_String, Param_String, Param_String);
468}
469
470public int Native_IsClientBanned(Handle hPlugin, int iParams)
471{
472 int iClient = GetNativeCell(NATIVE_ISBANNED_CELL_CLIENT);
473
474 if (iClient <= ZERO || iClient > MaxClients || !IsClientInGame(iClient))
475 {
476 ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is invalid!", iClient);
477 return ZERO;
478 }
479
480 return GetCTBanStatus(iClient);
481}
482
483public int Native_GetTimeRemaining(Handle hPlugin, int iParams)
484{
485 int iClient = GetNativeCell(NATIVE_GET_TIMELEFT_CELL_CLIENT);
486
487 if (iClient <= ZERO || iClient > MaxClients || !IsClientInGame(iClient))
488 {
489 ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is invalid!", iClient);
490 }
491
492 return gA_LocalTimeRemaining[iClient];
493}
494
495public int Native_GetOverrideStatus(Handle hPlugin, int iParams)
496{
497 int iClient = GetNativeCell(NATIVE_GET_OVERRIDE_CELL_CLIENT);
498
499 if (iClient <= ZERO || iClient > MaxClients || !IsClientInGame(iClient))
500 {
501 ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is invalid!", iClient);
502 return false;
503 }
504
505 return g_bA_Temp_CTBan_Override[iClient];
506}
507
508public int Native_GetBanInfo(Handle hPlugin, int iParams)
509{
510 int iClient = GetNativeCell(NATIVE_GETBANINFO_CELL_CLIENT);
511
512 if (iClient <= ZERO || iClient > MaxClients || !IsClientInGame(iClient))
513 {
514 ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is invalid!", iClient);
515 }
516
517 ProcessIsBannedTarget(iClient, CALLER_NATIVE);
518
519 return SP_ERROR_NONE;
520}
521
522public int Native_GetBanInfo_Offline(Handle hPlugin, int iParams)
523{
524 char sAuthId[FIELD_AUTHID_MAXLENGTH];
525 int iReturn = GetNativeString(NATIVE_GETBANINFO_OFF_STR_AUTHID, sAuthId, sizeof(sAuthId));
526
527 if (iReturn != SP_ERROR_NONE || strlen(sAuthId) < NATIVE_MIN_AUTHID_LENGTH)
528 {
529 ThrowNativeError(SP_ERROR_NATIVE, "Invalid Authid");
530 }
531
532 if (IsAuthIdConnected(sAuthId))
533 {
534 ThrowNativeError(SP_ERROR_NATIVE, "AuthID currently connected.");
535 }
536 else
537 {
538 ProcessIsBannedOffline(CALLER_NATIVE, sAuthId);
539 }
540
541 return SP_ERROR_NONE;
542}
543
544public int Native_CTBan_Client(Handle hPlugin, int iParams)
545{
546 int iClient = GetNativeCell(NATIVE_CTBAN_CELL_CLIENT);
547
548 if (iClient <= ZERO || iClient > MaxClients || !IsClientInGame(iClient))
549 {
550 ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is invalid!", iClient);
551 }
552
553 int iMinutes = GetNativeCell(NATIVE_CTBAN_CELL_TIME);
554
555 if (iMinutes < ZERO)
556 {
557 ThrowNativeError(SP_ERROR_NATIVE, "Invalid time specified (%d).", iMinutes);
558 }
559
560 int iAdmin = GetNativeCell(NATIVE_CTBAN_CELL_ADMIN);
561
562 if (iAdmin < ZERO || iAdmin > MaxClients || (iAdmin && !IsClientInGame(iAdmin)))
563 {
564 ThrowNativeError(SP_ERROR_NATIVE, "Admin (%d) is invalid!", iAdmin);
565 }
566
567 char sReason[FIELD_REASON_MAXLENGTH];
568 int iReturn = GetNativeString(NATIVE_CTBAN_STR_REASON, sReason, sizeof(sReason));
569
570 if (iReturn != SP_ERROR_NONE)
571 {
572 ThrowNativeError(SP_ERROR_NATIVE, "Invalid reason string");
573 }
574
575 if (!GetCTBanStatus(iClient))
576 {
577 PerformCTBan(iClient, iAdmin, iMinutes, _, sReason);
578 }
579 else
580 {
581 ThrowNativeError(SP_ERROR_NATIVE, g_sChatBanner, "Already CT Banned", iClient);
582 }
583
584 return SP_ERROR_NONE;
585}
586
587public int Native_CTBan_Client_Offline(Handle hPlugin, int iParams)
588{
589 if (!g_bAuthIdNativeExists)
590 {
591 ThrowNativeError(SP_ERROR_NATIVE, g_sChatBanner, "Feature Not Available");
592 }
593
594 char sAuthId[FIELD_AUTHID_MAXLENGTH];
595 int iReturn = GetNativeString(NATIVE_CTBAN_OFF_STR_AUTHID, sAuthId, sizeof(sAuthId));
596
597 if (iReturn != SP_ERROR_NONE || strlen(sAuthId) < NATIVE_MIN_AUTHID_LENGTH)
598 {
599 ThrowNativeError(SP_ERROR_NATIVE, "Invalid Authid");
600 }
601
602 if (IsAuthIdConnected(sAuthId))
603 {
604 ThrowNativeError(SP_ERROR_NATIVE, "AuthID currently connected.");
605 }
606 else
607 {
608 PerformOfflineCTBan(sAuthId, CALLER_NATIVE);
609 }
610
611 return SP_ERROR_NONE;
612}
613
614public int Native_CTBan_ChangeBanLength(Handle hPlugin, int iParams)
615{
616 int iClient = GetNativeCell(NATIVE_CHANGE_TIME_CELL_CLIENT);
617
618 if (iClient <= ZERO || iClient > MaxClients || !IsClientInGame(iClient))
619 {
620 ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is invalid!", iClient);
621 }
622
623 int iMinutes = GetNativeCell(NATIVE_CHANGE_TIME_CELL_TIME);
624
625 if (iMinutes < ZERO)
626 {
627 ThrowNativeError(SP_ERROR_NATIVE, "Invalid time specified (%d).", iMinutes);
628 }
629
630 int iAdmin = GetNativeCell(NATIVE_CHANGE_TIME_CELL_ADMIN);
631
632 if (iAdmin < ZERO || iAdmin > MaxClients || (iAdmin && !IsClientInGame(iAdmin)))
633 {
634 ThrowNativeError(SP_ERROR_NATIVE, "Admin (%d) is invalid!", iAdmin);
635 }
636
637 if (GetCTBanStatus(iClient))
638 {
639 // check if time is not changing
640 if (gA_LocalTimeRemaining[iClient] == iMinutes || (gA_LocalTimeRemaining[iClient] <= CTBAN_PERM_BAN_LENGTH && iMinutes == CTBAN_PERM_BAN_LENGTH))
641 {
642 ThrowNativeError(SP_ERROR_NATIVE, g_sChatBanner, "Invalid Amount");
643 }
644 else
645 {
646 PerformChangeCTBanTime(iClient, iAdmin, iMinutes);
647 }
648 }
649 else
650 {
651 ThrowNativeError(SP_ERROR_NATIVE, g_sChatBanner, "Not CT Banned", iClient);
652 }
653
654 return SP_ERROR_NONE;
655}
656
657public int Native_CTBan_UnbanClient(Handle hPlugin, int iParams)
658{
659 int iClient = GetNativeCell(NATIVE_UNBAN_CELL_CLIENT);
660
661 if (iClient <= ZERO || iClient > MaxClients || !IsClientInGame(iClient))
662 {
663 ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is invalid!", iClient);
664 }
665
666 int iAdmin = GetNativeCell(NATIVE_UNBAN_CELL_ADMIN);
667
668 if (iAdmin < ZERO || iAdmin > MaxClients || (iAdmin && !IsClientInGame(iAdmin)))
669 {
670 ThrowNativeError(SP_ERROR_NATIVE, "Admin (%d) is invalid!", iAdmin);
671 }
672
673 if (GetCTBanStatus(iClient))
674 {
675 // check if the cookies are ready
676 if (AreClientCookiesCached(iClient))
677 {
678 Remove_CTBan(iAdmin, iClient);
679 }
680 else
681 {
682 ThrowNativeError(SP_ERROR_NATIVE, g_sChatBanner, "Cookie Status Unavailable");
683 }
684 }
685 else
686 {
687 ThrowNativeError(SP_ERROR_NATIVE, g_sChatBanner, "Not CT Banned", iClient);
688 }
689
690 return SP_ERROR_NONE;
691}
692
693public int Native_CTBan_UnbanClient_Offline(Handle hPlugin, int iParams)
694{
695 if (!g_bAuthIdNativeExists)
696 {
697 ThrowNativeError(SP_ERROR_NATIVE, g_sChatBanner, "Feature Not Available");
698 }
699
700 char sAuthId[FIELD_AUTHID_MAXLENGTH];
701 int iReturn = GetNativeString(NATIVE_UNBAN_OFF_STR_AUTHID, sAuthId, sizeof(sAuthId));
702
703 if (iReturn != SP_ERROR_NONE || strlen(sAuthId) < NATIVE_MIN_AUTHID_LENGTH)
704 {
705 ThrowNativeError(SP_ERROR_NATIVE, "Invalid Authid");
706 }
707
708 if (IsAuthIdConnected(sAuthId))
709 {
710 ThrowNativeError(SP_ERROR_NATIVE, "AuthID currently connected.");
711 }
712 else
713 {
714 PerformOfflineUnCTBan(sAuthId, CALLER_NATIVE);
715 }
716
717 return SP_ERROR_NONE;
718}
719
720public int Native_CTBan_ForceCT(Handle hPlugin, int iParams)
721{
722 int iClient = GetNativeCell(NATIVE_FORCECT_CELL_CLIENT);
723
724 if (iClient <= ZERO || iClient > MaxClients || !IsClientInGame(iClient))
725 {
726 ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is invalid!", iClient);
727 }
728
729 int iAdmin = GetNativeCell(NATIVE_FORCECT_CELL_ADMIN);
730
731 if (iAdmin < ZERO || iAdmin > MaxClients || (iAdmin && !IsClientInGame(iAdmin)))
732 {
733 ThrowNativeError(SP_ERROR_NATIVE, "Admin (%d) is invalid!", iAdmin);
734 }
735
736 if (GetClientTeam(iClient) == CS_TEAM_CT)
737 {
738 ThrowNativeError(SP_ERROR_NATIVE, g_sChatBanner, "Unable to target");
739 }
740 else
741 {
742 ForceCTActions(iAdmin, iClient);
743 }
744
745 return SP_ERROR_NONE;
746}
747
748public int Native_CTBan_UnForceCT(Handle hPlugin, int iParams)
749{
750 int iClient = GetNativeCell(NATIVE_UNFORCECT_CELL_CLIENT);
751
752 if (iClient <= ZERO || iClient > MaxClients || !IsClientInGame(iClient))
753 {
754 ThrowNativeError(SP_ERROR_NATIVE, "Client (%d) is invalid!", iClient);
755 }
756
757 int iAdmin = GetNativeCell(NATIVE_UNFORCECT_CELL_ADMIN);
758
759 if (iAdmin < ZERO || iAdmin > MaxClients || (iAdmin && !IsClientInGame(iAdmin)))
760 {
761 ThrowNativeError(SP_ERROR_NATIVE, "Admin (%d) is invalid!", iAdmin);
762 }
763
764 UnForceCTActions(iAdmin, iClient, true);
765
766 return SP_ERROR_NONE;
767}
768
769public void OnAllPluginsLoaded()
770{
771 g_bAuthIdNativeExists = IsSetAuthIdNativePresent();
772}
773
774public Action Event_PlayerSpawn(Event hEvent, const char[] sName, bool bDontBroadcast)
775{
776 int iClient = GetClientOfUserId(GetEventInt(hEvent, "userid"));
777 int iBanStatus = GetCTBanStatus(iClient);
778 if ( !iBanStatus )
779 {
780 zban[iClient] = false;
781 }
782 if (IsClientInGame(iClient) && GetClientTeam(iClient) == CS_TEAM_CT)
783 {
784 if (!g_bA_Temp_CTBan_Override[iClient] && GetCTBanStatus(iClient))
785 {
786 #if defined CTBAN_DEBUG
787 LogMessage("%N spawned as CT but was CTBanned. Moving to Terrorist team.", iClient);
788 #endif
789
790 EnforceCTBan(iClient);
791 }
792 }
793
794 return Plugin_Continue;
795}
796
797public Action Event_PlayerTeam(Event hEvent, const char[] sName, bool bDontBroadcast)
798{
799 int iUserID = GetEventInt(hEvent, "userid");
800 int iClient = GetClientOfUserId(iUserID);
801 int iTeam = GetEventInt(hEvent, "team");
802 bool bDisconnected = GetEventBool(hEvent, "disconnect");
803
804 if (bDisconnected || !iClient || !IsClientInGame(iClient))
805 {
806 return Plugin_Continue;
807 }
808
809 if (iTeam == CS_TEAM_CT && GetCTBanStatus(iClient))
810 {
811 // if a CT banned player is on CT and did not get an override they will be swapped after they spawn
812 // BUT an admin likely did this and should get instruction to use !forcect
813 if (!g_bA_Temp_CTBan_Override[iClient])
814 {
815 // only admins need the message
816 for (int iIndex = ONE; iIndex <= MaxClients; iIndex++)
817 {
818 if (IsClientInGame(iIndex) && CheckCommandAccess(iIndex, "sm_chat", ADMFLAG_CHAT))
819 {
820 PrintToChat(iIndex, g_sChatBanner, "CTBanned Player On CT Team", iClient);
821 }
822 }
823 }
824
825 // if they are still alive then we should not even wait until the respawn
826 if (IsPlayerAlive(iClient))
827 {
828 CreateTimer(DELAY_ENFORCEMENT_TIME, Timer_DelayEnforcement, iUserID, TIMER_FLAG_NO_MAPCHANGE);
829 }
830 }
831
832 return Plugin_Continue;
833}
834
835public Action Timer_DelayEnforcement(Handle hTimer, any iUserID)
836{
837 int iClient = GetClientOfUserId(iUserID);
838
839 if (iClient && IsClientInGame(iClient) && GetClientTeam(iClient) == CS_TEAM_CT && GetCTBanStatus(iClient))
840 {
841 EnforceCTBan(iClient);
842 }
843}
844
845public Action Event_JoinTeamFailed(Handle hEvent, const char[] sName, bool bDontBroadcast)
846{
847 int iClient = GetClientOfUserId(GetEventInt(hEvent, "userid"));
848 if (iClient && IsClientInGame(iClient))
849 {
850 int iReason = GetEventInt(hEvent, "reason");
851
852 if (iReason == JOINFAILREASON_ONECHANGE)
853 {
854 // Check if client is banned and is blocked
855 if (GetCTBanStatus(iClient))
856 {
857 #if defined CTBAN_DEBUG
858 LogMessage("%N was unable to join a team due to limit. Forcing to Terrorist team.");
859 #endif
860
861 ChangeClientTeam(iClient, CS_TEAM_T);
862
863 return Plugin_Handled;
864 }
865 }
866 }
867
868 return Plugin_Continue;
869}
870
871// consider if someone does a 'retry' and clientprefs is accessinsg on its ClientConnectCallback and this is also trying to set a value
872public void OnClientAuthorized(int iClient, const char[] sAuthID)
873{
874 // check if the Steam ID is in the Rage Ban list
875 int iNeedle = FindStringInArray(gA_DSteamIDs, sAuthID);
876 if (iNeedle != VALUE_NOT_FOUND_IN_ARRAY)
877 {
878 g_bRageBanArrayChanged = true;
879
880 RemoveFromArray(gA_DNames, iNeedle);
881 RemoveFromArray(gA_DSteamIDs, iNeedle);
882 #if defined CTBAN_DEBUG
883 LogMessage("removed %N from Rage Bannable player list for re-connecting to the server", iClient);
884 #endif
885 }
886
887 // check if we have a database connection
888 if (gH_BanDatabase != INVALID_HANDLE)
889 {
890 // check if the Steam ID is in the Timed Ban list
891 char sQuery[QUERY_MAXLENGTH];
892 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_SELECT_BANTIME, g_sTimesTableName, sAuthID);
893 SQL_TQuery(gH_BanDatabase, DB_Callback_OnClientAuthed, sQuery, view_as<int>(iClient));
894 }
895 else
896 {
897 CreateTimer(AUTH_RESCAN_TIME, Timer_OnAuthCheckDatabase, iClient, TIMER_FLAG_NO_MAPCHANGE);
898 }
899}
900
901public Action Timer_OnAuthCheckDatabase(Handle hTimer, any iClient)
902{
903 if (gH_BanDatabase != INVALID_HANDLE && IsClientInGame(iClient))
904 {
905 char sAuthID[FIELD_AUTHID_MAXLENGTH];
906 GetClientAuthId(iClient, AuthId_Steam2, sAuthID, sizeof(sAuthID));
907
908 char sQuery[QUERY_MAXLENGTH];
909 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_SELECT_BANTIME, g_sTimesTableName, sAuthID);
910 SQL_TQuery(gH_BanDatabase, DB_Callback_OnClientAuthed, sQuery, view_as<int>(iClient));
911 }
912 else if(IsClientInGame(iClient))
913 {
914 CreateTimer(AUTH_RESCAN_TIME, Timer_OnAuthCheckDatabase, iClient, TIMER_FLAG_NO_MAPCHANGE);
915 }
916}
917
918public void DB_Callback_OnClientAuthed(Handle hOwner, Handle hCallback, const char[] sError, any iClient)
919{
920 if (hCallback == INVALID_HANDLE)
921 {
922 LogError("Error in OnClientAuthorized query: %s", sError);
923 }
924 else
925 {
926 int iRowCount = SQL_GetRowCount(hCallback);
927 #if defined CTBAN_DEBUG
928 LogMessage("SQL Auth: %d row count", iRowCount);
929 #endif
930 if (iRowCount)
931 {
932 SQL_FetchRow(hCallback);
933 int iBanTimeRemaining = SQL_FetchInt(hCallback, CLIENT_AUTHED_CB_FIELD_TIMELEFT);
934 #if defined CTBAN_DEBUG
935 LogMessage("SQL Auth: %N joined with %i time remaining on ban", iClient, iBanTimeRemaining);
936 #endif
937 // update local time
938 PushArrayCell(gA_TimedBanLocalList, iClient);
939 gA_LocalTimeRemaining[iClient] = iBanTimeRemaining;
940 }
941 }
942}
943
944public void AdminMenu_RageBan(Handle hTopMenu, TopMenuAction eAction, TopMenuObject eObjectID, int iClient, char[] sBuffer, int iMaxLength)
945{
946 if (eAction == TopMenuAction_DisplayOption)
947 {
948 Format(sBuffer, iMaxLength, "%T", "Rage Ban Admin Menu", iClient);
949 }
950 else if (eAction == TopMenuAction_SelectOption)
951 {
952 DisplayRageBanMenu(iClient, GetArraySize(gA_DNames));
953 }
954}
955
956void DisplayRageBanMenu(int iClient, int iArraySize)
957{
958 if (iArraySize == ZERO)
959 {
960 PrintToChat(iClient, g_sChatBanner, "No Targets");
961 }
962 else
963 {
964 Handle hMenu = CreateMenu(MenuHandler_RageBan);
965
966 SetMenuTitle(hMenu, "%T", "Rage Ban Menu Title", iClient);
967 SetMenuExitBackButton(hMenu, true);
968
969 for (int iArrayIndex = ZERO; iArrayIndex < iArraySize; iArrayIndex++)
970 {
971 char sName[FIELD_NAME_MAXLENGTH];
972 GetArrayString(gA_DNames, iArrayIndex, sName, sizeof(sName));
973
974 char sAuthID[FIELD_AUTHID_MAXLENGTH];
975 GetArrayString(gA_DSteamIDs, iArrayIndex, sAuthID, sizeof(sAuthID));
976
977 AddMenuItem(hMenu, sAuthID, sName);
978 }
979
980 DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER);
981 }
982}
983
984public int MenuHandler_RageBan(Handle hMenu, MenuAction action, int iClient, int iMenuChoice)
985{
986 if (action == MenuAction_End)
987 {
988 CloseHandle(hMenu);
989 }
990 else if (action == MenuAction_Cancel)
991 {
992 if ((iMenuChoice == MenuCancel_ExitBack) && (gH_TopMenu != INVALID_HANDLE))
993 {
994 DisplayTopMenu(gH_TopMenu, iClient, TopMenuPosition_LastCategory);
995 }
996 }
997 else if (action == MenuAction_Select)
998 {
999 if (!g_bAuthIdNativeExists)
1000 {
1001 ReplyToCommand(iClient, g_sChatBanner, "Feature Not Available");
1002 }
1003 else
1004 {
1005 char sAuthID[FIELD_AUTHID_MAXLENGTH];
1006 char sTargetName[MAX_TARGET_LENGTH];
1007 GetMenuItem(hMenu, iMenuChoice, sAuthID, sizeof(sAuthID), _, sTargetName, sizeof(sTargetName));
1008
1009 #if defined CTBAN_DEBUG
1010 PrintToChat(iClient, g_sChatBanner, "Ready to CT Ban", sAuthID);
1011 #endif
1012
1013 SetAuthIdCookie(sAuthID, g_CT_Cookie, COOKIE_BANNED_STRING);
1014
1015 char sAdminSteamID[FIELD_AUTHID_MAXLENGTH];
1016 GetClientAuthId(iClient, AuthId_Steam2, sAdminSteamID, sizeof(sAdminSteamID));
1017
1018 LogMessage("%N (%s) has issued a rage ban on %s (%s) indefinitely.", iClient, sAdminSteamID, sTargetName, sAuthID);
1019
1020 ShowActivity2(iClient, "", g_sChatBanner, "Rage Ban", sTargetName);
1021
1022 int iTimeStamp = GetTime();
1023 char sTempName[FIELD_NAME_MAXLENGTH];
1024 char sQuery[QUERY_MAXLENGTH];
1025 char sEscapedPerpName[MAX_SAFE_ESCAPE_QUERY(FIELD_NAME_MAXLENGTH)];
1026 char sEscapedAdminName[MAX_SAFE_ESCAPE_QUERY(FIELD_NAME_MAXLENGTH)];
1027 Format(sTempName, sizeof(sTempName), "%s", sTargetName);
1028 SQL_EscapeString(gH_BanDatabase, sTempName, sEscapedPerpName, sizeof(sEscapedPerpName));
1029 Format(sTempName, sizeof(sTempName), "%N", iClient);
1030 SQL_EscapeString(gH_BanDatabase, sTempName, sEscapedAdminName, sizeof(sEscapedAdminName));
1031
1032 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_INSERT, g_sLogTableName, iTimeStamp, sAuthID, sEscapedPerpName, sAdminSteamID, sEscapedAdminName, CTBAN_PERM_BAN_LENGTH, CTBAN_PERM_BAN_LENGTH, RAGEBAN_LOG_REASON);
1033
1034 #if defined CTBAN_DEBUG
1035 LogMessage("log query: %s", sQuery);
1036 #endif
1037
1038 SQL_TQuery(gH_BanDatabase, DB_Callback_CTBan, sQuery, iClient);
1039
1040 // Remove any existing time information to make the CTBan permanently
1041 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_DELETE, g_sTimesTableName, sAuthID);
1042 SQL_TQuery(gH_BanDatabase, DB_Callback_DisconnectAction, sQuery);
1043 }
1044 }
1045}
1046
1047public void CP_Callback_ResetAllCTBans(Handle hOwner, Handle hCallback, const char[] sError, any data)
1048{
1049 if (hCallback == INVALID_HANDLE)
1050 {
1051 LogError("Error reseting the CTBan cookies: %s", sError);
1052 }
1053 else
1054 {
1055 LogMessage("CTBans Cookie Bans were successfully RESET by the administrator.");
1056 }
1057}
1058
1059public Action Command_Offline_CTBan(int iClient, int iArgs)
1060{
1061 if (g_bAuthIdNativeExists)
1062 {
1063 char sAuthId[FIELD_AUTHID_MAXLENGTH];
1064 GetCmdArgString(sAuthId, sizeof(sAuthId));
1065
1066 if (IsAuthIdConnected(sAuthId))
1067 {
1068 ReplyToCommand(iClient, g_sChatBanner, "Unable to target");
1069 }
1070 else
1071 {
1072 PerformOfflineCTBan(sAuthId, iClient);
1073 }
1074 }
1075 else
1076 {
1077 ReplyToCommand(iClient, g_sChatBanner, "Feature Not Available");
1078 }
1079 return Plugin_Handled;
1080}
1081
1082void PerformOfflineCTBan(char[] sAuthId, int iAdmin)
1083{
1084 SetAuthIdCookie(sAuthId, g_CT_Cookie, COOKIE_BANNED_STRING);
1085
1086 char sAdminSteamID[FIELD_AUTHID_MAXLENGTH];
1087 if (iAdmin > ZERO)
1088 {
1089 GetClientAuthId(iAdmin, AuthId_Steam2, sAdminSteamID, sizeof(sAdminSteamID));
1090 }
1091 else
1092 {
1093 sAdminSteamID = CONSOLE_AUTHID;
1094 }
1095
1096 int iTimeStamp = GetTime();
1097 char sQuery[QUERY_MAXLENGTH];
1098 char sTempName[FIELD_NAME_MAXLENGTH];
1099 char sEscapedPerpAuthId[MAX_SAFE_ESCAPE_QUERY(FIELD_NAME_MAXLENGTH)];
1100 SQL_EscapeString(gH_BanDatabase, sAuthId, sEscapedPerpAuthId, sizeof(sEscapedPerpAuthId));
1101
1102 char sEscapedAdminName[MAX_SAFE_ESCAPE_QUERY(FIELD_NAME_MAXLENGTH)];
1103 if (iAdmin > ZERO)
1104 {
1105 Format(sTempName, sizeof(sTempName), "%N", iAdmin);
1106 SQL_EscapeString(gH_BanDatabase, sTempName, sEscapedAdminName, sizeof(sEscapedAdminName));
1107 }
1108 else
1109 {
1110 sEscapedAdminName = CONSOLE_USER_NAME;
1111 }
1112
1113 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_INSERT, g_sLogTableName, iTimeStamp, sEscapedPerpAuthId, OFFLINE_NAME_UNAVAILBLE, sAdminSteamID, sEscapedAdminName, CTBAN_PERM_BAN_LENGTH, CTBAN_PERM_BAN_LENGTH, REASON_OFFLINECTBAN);
1114
1115 #if defined CTBAN_DEBUG
1116 LogMessage("log query: %s", sQuery);
1117 #endif
1118
1119 SQL_TQuery(gH_BanDatabase, DB_Callback_CTBan, sQuery, iAdmin);
1120
1121 if (iAdmin == CALLER_NATIVE)
1122 {
1123 // No response
1124 }
1125 {
1126 ReplyToCommand(iAdmin, g_sChatBanner, "Banned AuthId", sAuthId);
1127 }
1128
1129 Call_StartForward(g_hFrwd_OnCTBan_Offline);
1130 Call_PushString(sAuthId);
1131 Call_PushCell(iAdmin);
1132 Call_Finish();
1133}
1134
1135public Action Command_ForceCT(int iClient, int iArgs)
1136{
1137 if (!iClient && !iArgs)
1138 {
1139 ReplyToCommand(iClient, g_sChatBanner, "Command Usage", "sm_forcect <player>");
1140 return Plugin_Handled;
1141 }
1142
1143 if (!iArgs)
1144 {
1145 DisplayCTBannedPlayerMenu(iClient, e_ForceCT);
1146 return Plugin_Handled;
1147 }
1148
1149 char sTarget[MAX_TARGET_LENGTH];
1150 GetCmdArg(FORCECT_ARG_TARGET, sTarget, sizeof(sTarget));
1151
1152 char sClientName[MAX_TARGET_LENGTH];
1153 int aiTargetList[MAXPLAYERS];
1154 int iTargetCount;
1155 bool b_tn_is_ml;
1156 iTargetCount = ProcessTargetString(sTarget, iClient, aiTargetList, MAXPLAYERS, COMMAND_FILTER_NO_MULTI, sClientName, sizeof(sClientName), b_tn_is_ml);
1157
1158 if (iTargetCount < ONE)
1159 {
1160 ReplyToTargetError(iClient, iTargetCount);
1161 }
1162 else
1163 {
1164 int iTarget = aiTargetList[ZERO];
1165
1166 if (iTarget && IsClientInGame(iTarget))
1167 {
1168 if (GetClientTeam(iTarget) == CS_TEAM_CT)
1169 {
1170 ReplyToCommand(iClient, g_sChatBanner, "Unable to target");
1171 }
1172 else
1173 {
1174 ForceCTActions(iClient, iTarget);
1175 }
1176 }
1177 }
1178 return Plugin_Handled;
1179}
1180
1181void ForceCTActions(int iAdmin, int iTarget)
1182{
1183 if (IsClientInGame(iTarget))
1184 {
1185 g_bA_Temp_CTBan_Override[iTarget] = true;
1186
1187 if (IsPlayerAlive(iTarget))
1188 {
1189 StripAllWeapons(iTarget);
1190 ForcePlayerSuicide(iTarget);
1191 }
1192
1193 ChangeClientTeam(iTarget, CS_TEAM_CT);
1194
1195 if (GetConVarBool(gH_Cvar_Respawn))
1196 {
1197 CS_RespawnPlayer(iTarget);
1198 }
1199
1200 ShowActivity2(iAdmin, "", g_sChatBanner, "Force CT", iTarget);
1201
1202 Call_StartForward(g_hFrwd_OnForceCT);
1203 Call_PushCell(iTarget);
1204 Call_PushCell(iAdmin);
1205 Call_Finish();
1206 }
1207}
1208
1209public Action Command_UnForceCT(int iClient, int iArgs)
1210{
1211 if (!iClient && !iArgs)
1212 {
1213 ReplyToCommand(iClient, g_sChatBanner, "Command Usage", "sm_unforcect <player>");
1214 return Plugin_Handled;
1215 }
1216
1217 if (!iArgs)
1218 {
1219 DisplayUnForceCTPlayerMenu(iClient);
1220 return Plugin_Handled;
1221 }
1222
1223 char sTarget[MAX_TARGET_LENGTH];
1224 GetCmdArg(UNFORCECT_ARG_TARGET, sTarget, sizeof(sTarget));
1225
1226 char sClientName[MAX_TARGET_LENGTH];
1227 int aiTargetLlist[MAXPLAYERS];
1228 int iTargetCount;
1229 bool b_tn_is_ml;
1230 iTargetCount = ProcessTargetString(sTarget, iClient, aiTargetLlist, MAXPLAYERS, COMMAND_FILTER_NO_MULTI, sClientName, sizeof(sClientName), b_tn_is_ml);
1231
1232 if (iTargetCount < ONE)
1233 {
1234 ReplyToTargetError(iClient, iTargetCount);
1235 }
1236 else
1237 {
1238 int iTarget = aiTargetLlist[ZERO];
1239 UnForceCTActions(iClient, iTarget);
1240 }
1241 return Plugin_Handled;
1242}
1243
1244void UnForceCTActions(int iAdmin, int iTarget, bool bQuiet = false)
1245{
1246 if (!g_bA_Temp_CTBan_Override[iTarget])
1247 {
1248 if (!bQuiet)
1249 {
1250 ReplyToCommand(iAdmin, g_sChatBanner, "Unable to target");
1251 }
1252 }
1253 else
1254 {
1255 if (IsClientInGame(iTarget))
1256 {
1257 if (GetClientTeam(iTarget) == CS_TEAM_CT)
1258 {
1259 if (IsPlayerAlive(iTarget))
1260 {
1261 StripAllWeapons(iTarget);
1262 ForcePlayerSuicide(iTarget);
1263 }
1264
1265 ChangeClientTeam(iTarget, CS_TEAM_T);
1266
1267 if (GetConVarBool(gH_Cvar_Respawn))
1268 {
1269 CS_RespawnPlayer(iTarget);
1270 }
1271 }
1272 g_bA_Temp_CTBan_Override[iTarget] = false;
1273
1274 if (!bQuiet)
1275 {
1276 ShowActivity2(iAdmin, "", g_sChatBanner, "Unforce CT", iTarget);
1277 }
1278
1279 Call_StartForward(g_hFrwd_OnUnforceCT);
1280 Call_PushCell(iTarget);
1281 Call_PushCell(iAdmin);
1282 Call_Finish();
1283 }
1284 }
1285}
1286
1287void DisplayUnForceCTPlayerMenu(int iClient)
1288{
1289 Handle hMenu = CreateMenu(MenuHandler_UnForceCT);
1290
1291 SetMenuTitle(hMenu, "%T", "UnForce CT Menu Title", iClient);
1292 SetMenuExitBackButton(hMenu, true);
1293
1294 int iCount = ZERO;
1295 char sUserId[MAX_USERID_LENGTH];
1296 char sName[MAX_NAME_LENGTH];
1297
1298 // filter away those with current overrides
1299 for (int iIndex = ONE; iIndex <= MaxClients; iIndex++)
1300 {
1301 if (IsClientInGame(iIndex))
1302 {
1303 if (g_bA_Temp_CTBan_Override[iIndex])
1304 {
1305 IntToString(GetClientUserId(iIndex), sUserId, sizeof(sUserId));
1306 GetClientName(iIndex, sName, sizeof(sName));
1307
1308 AddMenuItem(hMenu, sUserId, sName);
1309
1310 iCount++;
1311 }
1312 }
1313 }
1314
1315 if (!iCount)
1316 {
1317 PrintToChat(iClient, g_sChatBanner, "No matching clients");
1318 }
1319
1320 DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER);
1321}
1322
1323public Action Command_ResetCookies(int iClient, int iArgs)
1324{
1325 char sArgs[MAX_RESET_ARG_LENGTH];
1326 GetCmdArgString(sArgs, sizeof(sArgs));
1327
1328 if (StrEqual("force", sArgs))
1329 {
1330 if (!g_iCookieIndex)
1331 {
1332 ReplyToCommand(iClient, g_sChatBanner, "Cookie not Found", "Banned_From_CT");
1333 }
1334 else
1335 {
1336 char sQuery[QUERY_MAXLENGTH];
1337 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_CP_RESET_COOKIES, g_iCookieIndex);
1338
1339 #if defined CTBAN_DEBUG
1340 LogMessage("Query to run: %s", sQuery);
1341 #endif
1342
1343 SQL_TQuery(gH_CP_DataBase, CP_Callback_ResetAllCTBans, sQuery);
1344
1345 ShowActivity2(iClient, "", g_sChatBanner, "Reset Cookies");
1346 }
1347 }
1348 else
1349 {
1350 ReplyToCommand(iClient, g_sChatBanner, "Reset Cookie Confirmation");
1351 }
1352
1353 return Plugin_Handled;
1354}
1355
1356public Action Command_Offline_UnCTBan(int iClient, int iArgs)
1357{
1358 if (g_bAuthIdNativeExists)
1359 {
1360 char sAuthId[FIELD_AUTHID_MAXLENGTH];
1361 GetCmdArgString(sAuthId, sizeof(sAuthId));
1362
1363 if (IsAuthIdConnected(sAuthId))
1364 {
1365 ReplyToCommand(iClient, g_sChatBanner, "Unable to target");
1366 }
1367 else
1368 {
1369 PerformOfflineUnCTBan(sAuthId, iClient);
1370 }
1371 }
1372 else
1373 {
1374 ReplyToCommand(iClient, g_sChatBanner, "Feature Not Available");
1375 }
1376
1377 return Plugin_Handled;
1378}
1379
1380void PerformOfflineUnCTBan(char[] sAuthId, int iAdmin)
1381{
1382 SetAuthIdCookie(sAuthId, g_CT_Cookie, COOKIE_UNBANNED_STRING);
1383
1384 char sEscapedAuthId[MAX_SAFE_ESCAPE_QUERY(FIELD_NAME_MAXLENGTH)];
1385 SQL_EscapeString(gH_BanDatabase, sAuthId, sEscapedAuthId, sizeof(sEscapedAuthId));
1386
1387 char sQuery[QUERY_MAXLENGTH];
1388 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_EXPIRE, g_sLogTableName, sEscapedAuthId);
1389
1390 #if defined CTBAN_DEBUG
1391 LogMessage("log query: %s", sQuery);
1392 #endif
1393
1394 SQL_TQuery(gH_BanDatabase, DB_Callback_RemoveCTBan, sQuery, CALLER_DO_NOT_REPLY);
1395
1396 // delete from the timedban database if there was one
1397 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_DELETE, g_sTimesTableName, sEscapedAuthId);
1398
1399 #if defined CTBAN_DEBUG
1400 LogMessage("log query: %s", sQuery);
1401 #endif
1402
1403 SQL_TQuery(gH_BanDatabase, DB_Callback_RemoveCTBan, sQuery, CALLER_DO_NOT_REPLY);
1404
1405 if (iAdmin == CALLER_NATIVE)
1406 {
1407 // No response
1408 }
1409 else
1410 {
1411 ReplyToCommand(iAdmin, g_sChatBanner, "Unbanned AuthId", sAuthId);
1412
1413 LogMessage("%N has removed the CT ban on %s.", iAdmin, sAuthId);
1414 }
1415
1416 Call_StartForward(g_hFrwd_OnUnCTBan_Offline);
1417 Call_PushString(sAuthId);
1418 Call_PushCell(iAdmin);
1419 Call_Finish();
1420}
1421
1422public Action Command_RageBan(int iClient, int iArgs)
1423{
1424 int iArraySize = GetArraySize(gA_DNames);
1425 if (iArraySize == ZERO)
1426 {
1427 ReplyToCommand(iClient, g_sChatBanner, "No Targets");
1428 return Plugin_Handled;
1429 }
1430
1431 if (!iArgs)
1432 {
1433 if (iClient)
1434 {
1435 DisplayRageBanMenu(iClient, iArraySize);
1436 }
1437 // Console user
1438 else
1439 {
1440 PrintToServer(g_sChatBanner, "Rage Ban Menu Title");
1441
1442 for (int iArrayIndex = ZERO; iArrayIndex < iArraySize; iArrayIndex++)
1443 {
1444 char sName[FIELD_NAME_MAXLENGTH];
1445 GetArrayString(gA_DNames, iArrayIndex, sName, sizeof(sName));
1446
1447 char sAuthID[FIELD_AUTHID_MAXLENGTH];
1448 GetArrayString(gA_DSteamIDs, iArrayIndex, sAuthID, sizeof(sAuthID));
1449
1450 PrintToServer("[CTBAN] (%d.) %s [%s]", iArrayIndex + ONE, sName, sAuthID);
1451 }
1452
1453 g_bRageBanArrayChanged = false;
1454 }
1455 return Plugin_Handled;
1456 }
1457 else
1458 {
1459 if (iClient)
1460 {
1461 ReplyToCommand(iClient, g_sChatBanner, "Command Usage", RAGEBAN_COMMAND);
1462 }
1463 // Console user
1464 else
1465 {
1466 char sTarget[MAX_MENU_INT_CHOICE_LENGTH];
1467 GetCmdArg(RAGEBAN_ARG_CONSOLE_TARGET, sTarget, sizeof(sTarget));
1468
1469 int iArrayIndex = StringToInt(sTarget) - ONE;
1470
1471 if ((iArrayIndex >= iArraySize) || (iArrayIndex < ZERO))
1472 {
1473 ReplyToCommand(iClient, g_sChatBanner, "No matching client");
1474 }
1475 else if (g_bRageBanArrayChanged)
1476 {
1477 ReplyToCommand(iClient, g_sChatBanner, "Player no longer available");
1478 }
1479 else
1480 {
1481 char sTargetName[FIELD_NAME_MAXLENGTH];
1482 GetArrayString(gA_DNames, iArrayIndex, sTargetName, sizeof(sTargetName));
1483
1484 char sAuthID[FIELD_AUTHID_MAXLENGTH];
1485 GetArrayString(gA_DSteamIDs, iArrayIndex, sAuthID, sizeof(sAuthID));
1486
1487 #if defined CTBAN_DEBUG
1488 PrintToServer(g_sChatBanner, "Ready to CT Ban", sAuthID);
1489 #endif
1490
1491 SetAuthIdCookie(sAuthID, g_CT_Cookie, COOKIE_BANNED_STRING);
1492
1493 LogMessage("%N has issued a rage ban on %s (%s) indefinitely.", iClient, sTargetName, sAuthID);
1494
1495 ShowActivity2(iClient, "", g_sChatBanner, "Rage Ban", sTargetName);
1496
1497 int iTimeStamp = GetTime();
1498 char sTempName[FIELD_NAME_MAXLENGTH];
1499 char sQuery[QUERY_MAXLENGTH];
1500 char sEscapedPerpName[MAX_SAFE_ESCAPE_QUERY(FIELD_NAME_MAXLENGTH)];
1501 Format(sTempName, sizeof(sTempName), "%s", sTargetName);
1502 SQL_EscapeString(gH_BanDatabase, sTempName, sEscapedPerpName, sizeof(sEscapedPerpName));
1503
1504 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_INSERT, g_sLogTableName, iTimeStamp, sAuthID, sEscapedPerpName, CONSOLE_AUTHID, CONSOLE_USER_NAME, CTBAN_PERM_BAN_LENGTH, CTBAN_PERM_BAN_LENGTH, RAGEBAN_LOG_REASON);
1505
1506 #if defined CTBAN_DEBUG
1507 LogMessage("log query: %s", sQuery);
1508 #endif
1509
1510 SQL_TQuery(gH_BanDatabase, DB_Callback_CTBan, sQuery, iClient);
1511
1512 // Remove any existing time information to make the CTBan permanently
1513 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_DELETE, g_sTimesTableName, sAuthID);
1514 SQL_TQuery(gH_BanDatabase, DB_Callback_DisconnectAction, sQuery);
1515 }
1516 }
1517 }
1518
1519 return Plugin_Handled;
1520}
1521
1522public Action Timer_CheckTimedCTBans(Handle hTimer)
1523{
1524 // check if anyone has a time
1525 int iTimeArraySize = GetArraySize(gA_TimedBanLocalList);
1526
1527 // credit for this idea goes to Kigen
1528 for (int iIndex = ZERO; iIndex < iTimeArraySize; iIndex++)
1529 {
1530 int iBannedClientIndex = GetArrayCell(gA_TimedBanLocalList, iIndex);
1531 if (IsClientInGame(iBannedClientIndex))
1532 {
1533 if (IsPlayerAlive(iBannedClientIndex))
1534 {
1535 gA_LocalTimeRemaining[iBannedClientIndex]--;
1536
1537 #if defined CTBAN_DEBUG
1538 LogMessage("found alive time banned client with %i remaining", gA_LocalTimeRemaining[iBannedClientIndex]);
1539 #endif
1540
1541 // check if we should remove the CT ban
1542 if (gA_LocalTimeRemaining[iBannedClientIndex] <= ZERO)
1543 {
1544 // remove CT ban
1545 RemoveFromArray(gA_TimedBanLocalList, iIndex);
1546 iTimeArraySize--;
1547
1548 Remove_CTBan(ZERO, iBannedClientIndex, true);
1549
1550 #if defined CTBAN_DEBUG
1551 LogMessage("removed CT ban on %N", iBannedClientIndex);
1552 #endif
1553 }
1554 }
1555 }
1556 }
1557}
1558
1559public void OnConfigsExecuted()
1560{
1561 #if defined CTBAN_DEBUG
1562 LogMessage("Connecting to clientprefs database");
1563 #endif
1564
1565 SQL_TConnect(CP_Callback_Connect, "clientprefs");
1566
1567 char sDatabaseDriver[64];
1568 GetConVarString(gH_Cvar_Database_Driver, sDatabaseDriver, sizeof(sDatabaseDriver));
1569
1570 #if defined CTBAN_DEBUG
1571 LogMessage("Connecting to log database");
1572 #endif
1573
1574 SQL_TConnect(DB_Callback_Connect, sDatabaseDriver);
1575
1576 ParseCTBanReasonsFile(gH_DArray_Reasons);
1577
1578 gH_KV_BanLengths = ParseCTBanLengthsFile(gH_KV_BanLengths);
1579}
1580
1581public void DB_Callback_Connect(Handle hOwner, Handle hCallback, const char[] sError, any data)
1582{
1583 if (hCallback == INVALID_HANDLE)
1584 {
1585 LogError("Default database database connection failure: %s", sError);
1586 SetFailState("Error while connecting to default database. Exiting.");
1587 }
1588 else
1589 {
1590 gH_BanDatabase = hCallback;
1591
1592 // Determine the type of database we're on so we may modify the syntax of queries
1593 char sDatabaseID[MAX_DATABASE_ID_LENGTH];
1594 SQL_GetDriverIdent(SQL_ReadDriver(gH_BanDatabase), sDatabaseID, sizeof(sDatabaseID));
1595 if (StrEqual(sDatabaseID, "mysql"))
1596 {
1597 g_eDatabaseType = e_MySQL;
1598 }
1599 else if (StrEqual(sDatabaseID, "sqlite"))
1600 {
1601 g_eDatabaseType = e_SQLite;
1602 }
1603 else
1604 {
1605 g_eDatabaseType = e_Unknown;
1606 }
1607
1608 // figure out table prefix situation
1609 char sPrefix[MAX_TABLE_LENGTH - MAX_DEFAULT_TABLE_LENGTH];
1610 GetConVarString(gH_Cvar_Table_Prefix, sPrefix, sizeof(sPrefix));
1611 if (strlen(sPrefix) > ZERO)
1612 {
1613 Format(g_sTimesTableName, sizeof(g_sTimesTableName), "%s_CTBan_Times", sPrefix);
1614 }
1615 else
1616 {
1617 Format(g_sTimesTableName, sizeof(g_sTimesTableName), "CTBan_Times");
1618 }
1619
1620 char sQuery[QUERY_MAXLENGTH];
1621 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_CREATE, g_sTimesTableName, FIELD_AUTHID_MAXLENGTH);
1622
1623 #if defined CTBAN_DEBUG
1624 LogMessage("times table create query %s", sQuery);
1625 #endif
1626
1627 // create database if not already there
1628 SQL_TQuery(gH_BanDatabase, DB_Callback_CreateTime, sQuery);
1629
1630 if (strlen(sPrefix) > ZERO)
1631 {
1632 Format(g_sLogTableName, sizeof(g_sLogTableName), "%s_CTBan_Log", sPrefix);
1633 }
1634 else
1635 {
1636 Format(g_sLogTableName, sizeof(g_sLogTableName), "CTBan_Log");
1637 }
1638
1639 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_CREATE, g_sLogTableName, FIELD_AUTHID_MAXLENGTH, FIELD_NAME_MAXLENGTH, FIELD_AUTHID_MAXLENGTH, FIELD_NAME_MAXLENGTH, FIELD_REASON_MAXLENGTH);
1640
1641 #if defined CTBAN_DEBUG
1642 LogMessage("log table create query %s", sQuery);
1643 #endif
1644
1645 SQL_TQuery(gH_BanDatabase, DB_Callback_CreateLog, sQuery);
1646 }
1647}
1648
1649public void DB_Callback_CheckTableVersion(Handle hOwner, Handle hCallback, const char[] sError, any data)
1650{
1651 if (hCallback == INVALID_HANDLE)
1652 {
1653 #if defined CTBAN_DEBUG
1654 LogMessage("Table layout check revealed this error: %s", sError);
1655 #endif
1656
1657 // Check specifically for if there was a problem finding the ban_id column
1658 if (StrContains(sError, "column", false) != SUBSTRING_NOT_FOUND)
1659 {
1660 LogMessage("Upgrading CTBan_Log Table to Version Two...");
1661
1662 char sQuery[QUERY_MAXLENGTH];
1663 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_TO_V2_DROPKEY, g_sLogTableName);
1664
1665 #if defined CTBAN_DEBUG
1666 LogMessage("alter primary key query: %s", sQuery);
1667 #endif
1668
1669 SQL_TQuery(gH_BanDatabase, DB_Callback_UpgradeToLogTableTwo, sQuery);
1670 }
1671 }
1672}
1673
1674public void DB_Callback_UpgradeToLogTableTwo(Handle hOwner, Handle hCallback, const char[] sError, any data)
1675{
1676 if (hCallback == INVALID_HANDLE)
1677 {
1678 LogError("Error upgrading log table: %s", sError);
1679 SetFailState("Error while upgrading to Log Table Version Two. Exiting.");
1680 }
1681
1682 char sQuery[QUERY_MAXLENGTH];
1683 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_TO_V2_ADD_BANID, g_sLogTableName);
1684
1685 #if defined CTBAN_DEBUG
1686 LogMessage("add ban_id query: %s", sQuery);
1687 #endif
1688
1689 SQL_TQuery(gH_BanDatabase, DB_Callback_LogError, sQuery, e_QueryLogTableTwo);
1690}
1691
1692public void DB_Callback_LogError(Handle hOwner, Handle hCallback, const char[] sError, any eCallback)
1693{
1694 if (hCallback == INVALID_HANDLE)
1695 {
1696 LogError("Error: %s", sError);
1697 }
1698 else
1699 {
1700 switch (eCallback)
1701 {
1702 case e_QueryLogTableTwo:
1703 {
1704 LogMessage("CTBan_Log Table Successfully Upgraded to Version Two");
1705 }
1706 }
1707 }
1708}
1709
1710public void DB_Callback_CreateTime(Handle hOwner, Handle hCallback, const char[] sError, any data)
1711{
1712 if (hCallback == INVALID_HANDLE)
1713 {
1714 LogError("Error establishing table creation: %s", sError);
1715 SetFailState("Unable to ascertain creation of table in default database. Exiting.");
1716 }
1717}
1718
1719public void DB_Callback_CreateLog(Handle hOwner, Handle hCallback, const char[] sError, any data)
1720{
1721 if (hCallback == INVALID_HANDLE)
1722 {
1723 LogError("Error establishing table creation: %s", sError);
1724 SetFailState("Unable to ascertain creation of table in default database. Exiting.");
1725 }
1726
1727 // Check the log table and upgrade to the new version if needed
1728 char sQuery[QUERY_MAXLENGTH];
1729
1730 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_V1_CHECK, g_sLogTableName);
1731
1732 #if defined CTBAN_DEBUG
1733 LogMessage("check table version query %s", sQuery);
1734 #endif
1735
1736 SQL_TQuery(gH_BanDatabase, DB_Callback_CheckTableVersion, sQuery);
1737}
1738
1739public void CP_Callback_Connect(Handle hOwner, Handle hCallback, const char[] sError, any data)
1740{
1741 if (hCallback == INVALID_HANDLE)
1742 {
1743 LogError("Clientprefs database connection failure: %s", sError);
1744 SetFailState("Error while connecting to clientprefs database. Exiting.");
1745 }
1746 else
1747 {
1748 gH_CP_DataBase = hCallback;
1749
1750 // find the Banned_From_CT Cookie id #
1751 SQL_TQuery(gH_CP_DataBase, CP_Callback_FindCookie, CTBAN_QUERY_CP_FIND_COOKIE_ID);
1752 }
1753}
1754
1755public void CP_Callback_FindCookie(Handle hOwner, Handle hCallback, const char[] sError, any data)
1756{
1757 if (hCallback == INVALID_HANDLE)
1758 {
1759 LogError("Cookie query failure: %s", sError);
1760 }
1761 else
1762 {
1763 int iRowCount = SQL_GetRowCount(hCallback);
1764 if (iRowCount)
1765 {
1766 SQL_FetchRow(hCallback);
1767 int iCookieIDIndex = SQL_FetchInt(hCallback, FIND_COOKIE_CB_FIELD_COOKIE_ID);
1768 #if defined CTBAN_DEBUG
1769 LogMessage("found cookie index as %i", iCookieIDIndex);
1770 #endif
1771 g_iCookieIndex = iCookieIDIndex;
1772 }
1773 else
1774 {
1775 LogError("Could not find the cookie index. Rageban functionality disabled.");
1776 }
1777 }
1778}
1779
1780public void OnMapEnd()
1781{
1782 g_bIgnoreOverrideResets = true;
1783}
1784
1785public void OnMapStart()
1786{
1787 // pre-cache deny sound
1788 char sCommand[PLATFORM_MAX_PATH];
1789 GetConVarString(gH_Cvar_SoundName, gS_SoundPath, sizeof(gS_SoundPath));
1790 if(strcmp(gS_SoundPath, ""))
1791 {
1792 PrecacheSound(gS_SoundPath, true);
1793 Format(sCommand, sizeof(sCommand), "sound/%s", gS_SoundPath);
1794 AddFileToDownloadsTable(sCommand);
1795 }
1796
1797 g_bIgnoreOverrideResets = false;
1798}
1799
1800public void OnAdminMenuReady(Handle hTopMenu)
1801{
1802 // Block us from being called twice
1803 if (hTopMenu == gH_TopMenu)
1804 {
1805 return;
1806 }
1807
1808 // Save the Handle
1809 gH_TopMenu = hTopMenu;
1810
1811 // Build the "Player Commands" category
1812 hTopMenu = AddToTopMenu(gH_TopMenu, "CT Kitiltás",TopMenuObject_Category, CategoryHandler_ctbans, INVALID_TOPMENUOBJECT);
1813
1814 AddToTopMenu(gH_TopMenu,
1815 RAGEBAN_COMMAND,
1816 TopMenuObject_Item,
1817 AdminMenu_RageBan,
1818 hTopMenu,
1819 RAGEBAN_COMMAND,
1820 RAGEBAN_ADMIN_LEVEL);
1821
1822 AddToTopMenu(gH_TopMenu,
1823 CTBAN_COMMAND,
1824 TopMenuObject_Item,
1825 AdminMenu_CTBan,
1826 hTopMenu,
1827 CTBAN_COMMAND,
1828 CTBAN_ADMIN_LEVEL);
1829
1830 AddToTopMenu(gH_TopMenu,
1831 REMOVECTBAN_COMMAND,
1832 TopMenuObject_Item,
1833 AdminMenu_RemoveCTBan,
1834 hTopMenu,
1835 REMOVECTBAN_COMMAND,
1836 UNCTBAN_ADMIN_LEVEL);
1837
1838 AddToTopMenu(gH_TopMenu,
1839 FORCECT_COMMAND,
1840 TopMenuObject_Item,
1841 AdminMenu_ForceCT,
1842 hTopMenu,
1843 FORCECT_COMMAND,
1844 FORCECT_ADMIN_LEVEL);
1845
1846 AddToTopMenu(gH_TopMenu,
1847 UNFORCECT_COMMAND,
1848 TopMenuObject_Item,
1849 AdminMenu_UnForceCT,
1850 hTopMenu,
1851 UNFORCECT_COMMAND,
1852 UNFORCECT_ADMIN_LEVEL);
1853}
1854
1855public void CategoryHandler_ctbans(Handle hTopMenu,
1856 TopMenuAction eAction,
1857 TopMenuObject eObjectID,
1858 int iClient,
1859 char[] sBuffer,
1860 int iMaxLength)
1861{
1862 if (eAction == TopMenuAction_DisplayTitle || eAction == TopMenuAction_DisplayOption)
1863 Format(sBuffer, iMaxLength, "CT Kitiltás");
1864}
1865public void AdminMenu_ForceCT(Handle hTopMenu,
1866 TopMenuAction eAction,
1867 TopMenuObject eObjectID,
1868 int iClient,
1869 char[] sBuffer,
1870 int iMaxLength)
1871{
1872 if (eAction == TopMenuAction_DisplayOption)
1873 {
1874 Format(sBuffer, iMaxLength, "%T", "Force CT Admin Menu", iClient);
1875 }
1876 else if (eAction == TopMenuAction_SelectOption)
1877 {
1878 DisplayCTBannedPlayerMenu(iClient, e_ForceCT);
1879 }
1880}
1881
1882public void AdminMenu_UnForceCT(Handle hTopMenu,
1883 TopMenuAction eAction,
1884 TopMenuObject eObjectID,
1885 int iClient,
1886 char[] sBuffer,
1887 int iMaxLength)
1888{
1889 if (eAction == TopMenuAction_DisplayOption)
1890 {
1891 Format(sBuffer, iMaxLength, "%T", "UnForce CT Admin Menu", iClient);
1892 }
1893 else if (eAction == TopMenuAction_SelectOption)
1894 {
1895 DisplayUnForceCTPlayerMenu(iClient);
1896 }
1897}
1898
1899public void AdminMenu_RemoveCTBan(Handle hTopMenu,
1900 TopMenuAction eAction,
1901 TopMenuObject eObjectID,
1902 int iClient,
1903 char[] sBuffer,
1904 int iMaxLength)
1905{
1906 if (eAction == TopMenuAction_DisplayOption)
1907 {
1908 Format(sBuffer, iMaxLength, "%T", "Remove CT Ban Admin Menu", iClient);
1909 }
1910 else if (eAction == TopMenuAction_SelectOption)
1911 {
1912 DisplayCTBannedPlayerMenu(iClient, e_RemoveCTBan);
1913 }
1914}
1915
1916// displaying the list of CT Banned players is used by two commands
1917// default is for Remove CT Ban
1918// optional boolean is for CTBan List
1919void DisplayCTBannedPlayerMenu(int iClient, eCTBanMenuHandler eChoice)
1920{
1921 Handle hMenu = INVALID_HANDLE;
1922
1923 switch (eChoice)
1924 {
1925 case e_RemoveCTBan:
1926 {
1927 hMenu = CreateMenu(MenuHandler_RemoveCTBanPlayerList);
1928 SetMenuTitle(hMenu, "%T", "Remove CT Ban Menu Title", iClient);
1929 SetMenuExitBackButton(hMenu, true);
1930 }
1931 case e_CTBanList:
1932 {
1933 hMenu = CreateMenu(MenuHandler_CTBanList);
1934 SetMenuTitle(hMenu, "%T", "CTBanList Menu Title", iClient);
1935 SetMenuExitBackButton(hMenu, false);
1936 }
1937 case e_ForceCT:
1938 {
1939 hMenu = CreateMenu(MenuHandler_ForceCT);
1940 SetMenuTitle(hMenu, "%T", "Force CT Menu Title", iClient);
1941 SetMenuExitBackButton(hMenu, true);
1942 }
1943 }
1944
1945 int iCount = ZERO;
1946 char sUserId[MAX_USERID_LENGTH];
1947 char sName[MAX_NAME_LENGTH];
1948
1949 // display only people with existing CTBans
1950 for (int iIndex = ONE; iIndex <= MaxClients; iIndex++)
1951 {
1952 if (IsClientInGame(iIndex))
1953 {
1954 if (GetCTBanStatus(iIndex))
1955 {
1956 // Do no list people with overrides for Force CT Menu
1957 if (eChoice == e_ForceCT && g_bA_Temp_CTBan_Override[iIndex])
1958 {
1959 continue;
1960 }
1961
1962 IntToString(GetClientUserId(iIndex), sUserId, sizeof(sUserId));
1963 GetClientName(iIndex, sName, sizeof(sName));
1964
1965 AddMenuItem(hMenu, sUserId, sName);
1966
1967 iCount++;
1968 }
1969 }
1970 }
1971
1972 if (!iCount)
1973 {
1974 PrintToChat(iClient, g_sChatBanner, "No matching clients");
1975 }
1976
1977 DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER);
1978}
1979
1980public int MenuHandler_UnForceCT(Handle hMenu, MenuAction eAction, int iClient, int iMenuChoice)
1981{
1982 if (eAction == MenuAction_End)
1983 {
1984 CloseHandle(hMenu);
1985 }
1986 else if (eAction == MenuAction_Select)
1987 {
1988 char sTargetUserId[MAX_USERID_LENGTH];
1989 GetMenuItem(hMenu, iMenuChoice, sTargetUserId, sizeof(sTargetUserId));
1990 int iTargetUserId = StringToInt(sTargetUserId);
1991 int iTarget = GetClientOfUserId(iTargetUserId);
1992
1993 if (!iTarget || !IsClientInGame(iTarget))
1994 {
1995 PrintToChat(iClient, g_sChatBanner, "Player no longer available");
1996 }
1997 else if (!g_bA_Temp_CTBan_Override[iTarget])
1998 {
1999 PrintToChat(iClient, g_sChatBanner, "Player no longer available");
2000 }
2001 else
2002 {
2003 UnForceCTActions(iClient, iTarget);
2004 }
2005 }
2006}
2007
2008
2009public int MenuHandler_ForceCT(Handle hMenu, MenuAction eAction, int iClient, int iMenuChoice)
2010{
2011 if (eAction == MenuAction_End)
2012 {
2013 CloseHandle(hMenu);
2014 }
2015 else if (eAction == MenuAction_Select)
2016 {
2017 char sTargetUserId[MAX_USERID_LENGTH];
2018 GetMenuItem(hMenu, iMenuChoice, sTargetUserId, sizeof(sTargetUserId));
2019 int iTargetUserId = StringToInt(sTargetUserId);
2020 int iTarget = GetClientOfUserId(iTargetUserId);
2021
2022 if (!iTarget || !IsClientInGame(iTarget))
2023 {
2024 PrintToChat(iClient, g_sChatBanner, "Player no longer available");
2025 }
2026 else if (GetClientTeam(iTarget) == CS_TEAM_CT)
2027 {
2028 PrintToChat(iClient, g_sChatBanner, "Unable to target");
2029 }
2030 else
2031 {
2032 ForceCTActions(iClient, iTarget);
2033 }
2034 }
2035}
2036
2037public int MenuHandler_CTBanList(Handle hMenu, MenuAction eAction, int iClient, int iMenuChoice)
2038{
2039 if (eAction == MenuAction_End)
2040 {
2041 CloseHandle(hMenu);
2042 }
2043 else if (eAction == MenuAction_Select)
2044 {
2045 char sTargetUserId[MAX_USERID_LENGTH];
2046 GetMenuItem(hMenu, iMenuChoice, sTargetUserId, sizeof(sTargetUserId));
2047 int iTargetUserId = StringToInt(sTargetUserId);
2048 int iTarget = GetClientOfUserId(iTargetUserId);
2049
2050 if (!iTarget || !IsClientInGame(iTarget))
2051 {
2052 PrintToChat(iClient, g_sChatBanner, "Player no longer available");
2053 }
2054 else if (!GetCTBanStatus(iTarget, iClient))
2055 {
2056 PrintToChat(iClient, g_sChatBanner, "Not CT Banned", iTarget);
2057 }
2058 else
2059 {
2060 ProcessIsBannedTarget(iTarget, iClient);
2061 }
2062 }
2063}
2064
2065public int MenuHandler_RemoveCTBanPlayerList(Handle hMenu, MenuAction eAction, int iClient, int iMenuChoice)
2066{
2067 if (eAction == MenuAction_End)
2068 {
2069 CloseHandle(hMenu);
2070 }
2071 else if (eAction == MenuAction_Cancel)
2072 {
2073 if (iMenuChoice == MenuCancel_ExitBack && gH_TopMenu != INVALID_HANDLE)
2074 {
2075 DisplayTopMenu(gH_TopMenu, iClient, TopMenuPosition_LastCategory);
2076 }
2077 }
2078 else if (eAction == MenuAction_Select)
2079 {
2080 char sTargetUserId[MAX_USERID_LENGTH];
2081 GetMenuItem(hMenu, iMenuChoice, sTargetUserId, sizeof(sTargetUserId));
2082 int iTargetUserId = StringToInt(sTargetUserId);
2083 int iTarget = GetClientOfUserId(iTargetUserId);
2084
2085 if (!iTarget || !IsClientInGame(iTarget))
2086 {
2087 PrintToChat(iClient, g_sChatBanner, "Player no longer available");
2088 }
2089 else if (!CanUserTarget(iClient, iTarget))
2090 {
2091 PrintToChat(iClient, g_sChatBanner, "Unable to target");
2092 }
2093 else if (!GetCTBanStatus(iTarget, iClient))
2094 {
2095 PrintToChat(iClient, g_sChatBanner, "Not CT Banned", iTarget);
2096 }
2097 else
2098 {
2099 if (AreClientCookiesCached(iTarget))
2100 {
2101 Remove_CTBan(iClient, iTarget);
2102 }
2103 else
2104 {
2105 ReplyToCommand(iClient, g_sChatBanner, "Cookie Status Unavailable");
2106 }
2107 }
2108 }
2109}
2110
2111public void AdminMenu_CTBan(Handle hTopMenu,
2112 TopMenuAction eAction,
2113 TopMenuObject eObjectID,
2114 int iClient,
2115 char[] sBuffer,
2116 int iMaxLength)
2117{
2118 if (eAction == TopMenuAction_DisplayOption)
2119 {
2120 Format(sBuffer, iMaxLength, "%T", "CT Ban Admin Menu", iClient);
2121 }
2122 else if (eAction == TopMenuAction_SelectOption)
2123 {
2124 DisplayCTBanPlayerMenu(iClient);
2125 }
2126}
2127
2128void DisplayCTBanPlayerMenu(int iClient)
2129{
2130 Handle hMenu = CreateMenu(MenuHandler_CTBanPlayerList);
2131
2132 SetMenuTitle(hMenu, "%T", "CT Ban Menu Title", iClient);
2133 SetMenuExitBackButton(hMenu, true);
2134
2135 int iCount = ZERO;
2136 char sUserId[MAX_USERID_LENGTH];
2137 char sName[MAX_NAME_LENGTH];
2138
2139 // filter away those with current CTBans
2140 for (int iIndex = ONE; iIndex <= MaxClients; iIndex++)
2141 {
2142 if (IsClientInGame(iIndex))
2143 {
2144 if (!GetCTBanStatus(iIndex))
2145 {
2146 IntToString(GetClientUserId(iIndex), sUserId, sizeof(sUserId));
2147 GetClientName(iIndex, sName, sizeof(sName));
2148
2149 AddMenuItem(hMenu, sUserId, sName);
2150
2151 iCount++;
2152 }
2153 }
2154 }
2155
2156 if (!iCount)
2157 {
2158 PrintToChat(iClient, g_sChatBanner, "No Targets");
2159 }
2160
2161 DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER);
2162}
2163
2164void DisplayCTBanTimeMenu(int iClient, int iTargetUserId)
2165{
2166 Handle hMenu = CreateMenu(MenuHandler_CTBanTimeList);
2167
2168 SetMenuTitle(hMenu, "%T", "CT Ban Length Menu", iClient, GetClientOfUserId(iTargetUserId));
2169 SetMenuExitBackButton(hMenu, true);
2170
2171 char sUserId[MAX_USERID_LENGTH];
2172 IntToString(iTargetUserId, sUserId, sizeof(sUserId));
2173 AddMenuItem(hMenu, sUserId, "", ITEMDRAW_IGNORE);
2174
2175 if (gH_KV_BanLengths != INVALID_HANDLE)
2176 {
2177 char sBanDuration[MAX_TIME_ARG_LENGTH];
2178 char sDurationDescription[MAX_TIME_INFO_STR_LENGTH];
2179
2180 KvGotoFirstSubKey(gH_KV_BanLengths, false);
2181 do
2182 {
2183 KvGetSectionName(gH_KV_BanLengths, sBanDuration, sizeof(sBanDuration));
2184 KvGetString(gH_KV_BanLengths, NULL_STRING, sDurationDescription, sizeof(sDurationDescription));
2185
2186 AddMenuItem(hMenu, sBanDuration, sDurationDescription);
2187 }
2188 while (KvGotoNextKey(gH_KV_BanLengths, false));
2189
2190 KvRewind(gH_KV_BanLengths);
2191 }
2192 else
2193 {
2194 AddMenuItem(hMenu, "0", "Végleges");
2195 AddMenuItem(hMenu, "60", "1 Óra");
2196 // Only add 6 items in CS:GO menus so we don't paginate
2197 if (g_EngineVersion != Engine_CSGO)
2198 {
2199 AddMenuItem(hMenu, "10", "10 Perc");
2200 }
2201 AddMenuItem(hMenu, "240", "6 Óra");
2202 AddMenuItem(hMenu, "720", "12 Óra");
2203 AddMenuItem(hMenu, "1440", "1 Nap");
2204 AddMenuItem(hMenu, "10080", "1 Hét");
2205 }
2206
2207 DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER);
2208}
2209
2210void DisplayCTBanReasonMenu(int iClient, int iTargetUserId, int iMinutesToBan)
2211{
2212 Handle hMenu = CreateMenu(MenuHandler_CTBanReasonList);
2213
2214 SetMenuTitle(hMenu, "%T", "CT Ban Reason Menu", iClient, GetClientOfUserId(iTargetUserId));
2215 SetMenuExitBackButton(hMenu, true);
2216
2217 char sTargetUserId[MAX_USERID_LENGTH];
2218 IntToString(iTargetUserId, sTargetUserId, sizeof(sTargetUserId));
2219 AddMenuItem(hMenu, sTargetUserId, "", ITEMDRAW_IGNORE);
2220
2221 char sTimeInMinutes[MAX_TIME_ARG_LENGTH];
2222 IntToString(iMinutesToBan, sTimeInMinutes, sizeof(sTimeInMinutes));
2223 AddMenuItem(hMenu, sTimeInMinutes, "", ITEMDRAW_IGNORE);
2224
2225 int iNumManualReasons = GetArraySize(gH_DArray_Reasons);
2226
2227 char sMenuReason[FIELD_REASON_MAXLENGTH];
2228 char sMenuInt[MAX_MENU_INT_CHOICE_LENGTH];
2229
2230 if (iNumManualReasons > ZERO)
2231 {
2232 for (int iLineNumber = ZERO; iLineNumber < iNumManualReasons; iLineNumber++)
2233 {
2234 GetArrayString(gH_DArray_Reasons, iLineNumber, sMenuReason, sizeof(sMenuReason));
2235 IntToString(iLineNumber, sMenuInt, sizeof(sMenuInt));
2236 AddMenuItem(hMenu, sMenuInt, sMenuReason);
2237 }
2238 }
2239 else
2240 {
2241 // Only display 6 reasons in CS:GO by default to avoid pagination
2242 // Freekill Massacre is a redundant reason with Freekilling "CT Ban Reason 5"
2243 if (g_EngineVersion != Engine_CSGO)
2244 {
2245 Format(sMenuReason, sizeof(sMenuReason), "%T", "CT Ban Reason 1", iClient);
2246 AddMenuItem(hMenu, "1", sMenuReason);
2247 }
2248 Format(sMenuReason, sizeof(sMenuReason), "%T", "CT Ban Reason 2", iClient);
2249 AddMenuItem(hMenu, "2", sMenuReason);
2250 Format(sMenuReason, sizeof(sMenuReason), "%T", "CT Ban Reason 3", iClient);
2251 AddMenuItem(hMenu, "3", sMenuReason);
2252 Format(sMenuReason, sizeof(sMenuReason), "%T", "CT Ban Reason 4", iClient);
2253 AddMenuItem(hMenu, "4", sMenuReason);
2254 Format(sMenuReason, sizeof(sMenuReason), "%T", "CT Ban Reason 5", iClient);
2255 AddMenuItem(hMenu, "5", sMenuReason);
2256 Format(sMenuReason, sizeof(sMenuReason), "%T", "CT Ban Reason 6", iClient);
2257 AddMenuItem(hMenu, "6", sMenuReason);
2258 Format(sMenuReason, sizeof(sMenuReason), "%T", "CT Ban Reason 7", iClient);
2259 AddMenuItem(hMenu, "7", sMenuReason);
2260 }
2261
2262 DisplayMenu(hMenu, iClient, MENU_TIME_FOREVER);
2263}
2264
2265public int MenuHandler_CTBanReasonList(Handle hMenu, MenuAction eAction, int iClient, int iMenuChoice)
2266{
2267 if (eAction == MenuAction_End)
2268 {
2269 CloseHandle(hMenu);
2270 }
2271 else if (eAction == MenuAction_Cancel)
2272 {
2273 if (iMenuChoice == MenuCancel_ExitBack && gH_TopMenu != INVALID_HANDLE)
2274 {
2275 DisplayTopMenu(gH_TopMenu, iClient, TopMenuPosition_LastCategory);
2276 }
2277 }
2278 else if (eAction == MenuAction_Select)
2279 {
2280 char sTargetUserId[MAX_USERID_LENGTH];
2281 GetMenuItem(hMenu, MENUCHOICE_USERID, sTargetUserId, sizeof(sTargetUserId));
2282 int iTargetUserId = StringToInt(sTargetUserId);
2283
2284 char sTimeInMinutes[MAX_TIME_ARG_LENGTH];
2285 GetMenuItem(hMenu, MENUCHOICE_TIME, sTimeInMinutes, sizeof(sTimeInMinutes));
2286 int iMinutesToBan = StringToInt(sTimeInMinutes);
2287
2288 char sBanChoice[MAX_REASON_MENU_CHOICE_LENGTH];
2289 GetMenuItem(hMenu, iMenuChoice, sBanChoice, sizeof(sBanChoice));
2290 int iBanReason = StringToInt(sBanChoice);
2291
2292 int iTarget = GetClientOfUserId(iTargetUserId);
2293
2294 if (!GetCTBanStatus(iTarget))
2295 {
2296 PerformCTBan(iTarget, iClient, iMinutesToBan, iBanReason);
2297 }
2298 else
2299 {
2300 PrintToChat(iClient, g_sChatBanner, "Already CT Banned", iTarget);
2301 }
2302 }
2303}
2304
2305public int MenuHandler_CTBanPlayerList(Handle hMenu, MenuAction eAction, int iClient, int iMenuChoice)
2306{
2307 if (eAction == MenuAction_End)
2308 {
2309 CloseHandle(hMenu);
2310 }
2311 else if (eAction == MenuAction_Cancel)
2312 {
2313 if (iMenuChoice == MenuCancel_ExitBack && gH_TopMenu != INVALID_HANDLE)
2314 {
2315 DisplayTopMenu(gH_TopMenu, iClient, TopMenuPosition_LastCategory);
2316 }
2317 }
2318 else if (eAction == MenuAction_Select)
2319 {
2320 char sTargetUserId[MAX_USERID_LENGTH];
2321 GetMenuItem(hMenu, iMenuChoice, sTargetUserId, sizeof(sTargetUserId));
2322 int iTargetUserId = StringToInt(sTargetUserId);
2323 int iTarget = GetClientOfUserId(iTargetUserId);
2324
2325 if (!iTarget || !IsClientInGame(iTarget))
2326 {
2327 PrintToChat(iClient, g_sChatBanner, "Player no longer available");
2328 }
2329 else if (!CanUserTarget(iClient, iTarget))
2330 {
2331 PrintToChat(iClient, g_sChatBanner, "Unable to target");
2332 }
2333 else if (GetCTBanStatus(iTarget, iClient))
2334 {
2335 PrintToChat(iClient, g_sChatBanner, "Already CT Banned", iTarget);
2336 }
2337 else
2338 {
2339 DisplayCTBanTimeMenu(iClient, iTargetUserId);
2340 }
2341 }
2342}
2343
2344public int MenuHandler_CTBanTimeList(Handle hMenu, MenuAction eAction, int iClient, int iMenuChoice)
2345{
2346 if (eAction == MenuAction_End)
2347 {
2348 CloseHandle(hMenu);
2349 }
2350 else if (eAction == MenuAction_Cancel)
2351 {
2352 if (iMenuChoice == MenuCancel_ExitBack && gH_TopMenu != INVALID_HANDLE)
2353 {
2354 DisplayTopMenu(gH_TopMenu, iClient, TopMenuPosition_LastCategory);
2355 }
2356 }
2357 else if (eAction == MenuAction_Select)
2358 {
2359 char sTargetUserId[MAX_USERID_LENGTH];
2360 GetMenuItem(hMenu, MENUCHOICE_USERID, sTargetUserId, sizeof(sTargetUserId));
2361 int iTargetUserId = StringToInt(sTargetUserId);
2362
2363 char sTimeInMinutes[MAX_TIME_ARG_LENGTH];
2364 GetMenuItem(hMenu, iMenuChoice, sTimeInMinutes, sizeof(sTimeInMinutes));
2365 int iMinutesToBan = StringToInt(sTimeInMinutes);
2366
2367 DisplayCTBanReasonMenu(iClient, iTargetUserId, iMinutesToBan);
2368 }
2369}
2370
2371public void OnClientConnected(int iClient)
2372{
2373 g_bA_Temp_CTBan_Override[iClient] = false;
2374}
2375
2376public void OnClientPostAdminCheck(int iClient)
2377{
2378 CreateTimer(COOKIE_INIT_CHECK_TIME, Timer_CheckBanCookies, iClient, TIMER_FLAG_NO_MAPCHANGE);
2379}
2380
2381public void OnClientDisconnect(int iClient)
2382{
2383 char sDisconnectSteamID[FIELD_AUTHID_MAXLENGTH];
2384 GetClientAuthId(iClient, AuthId_Steam2, sDisconnectSteamID, sizeof(sDisconnectSteamID));
2385
2386 // add information to rage ban list
2387 char sName[MAX_TARGET_LENGTH];
2388 GetClientName(iClient, sName, sizeof(sName));
2389
2390 // add information to array
2391 // if information isn't already in the arrays then add it
2392 if (FindStringInArray(gA_DSteamIDs, sDisconnectSteamID) == VALUE_NOT_FOUND_IN_ARRAY)
2393 {
2394 g_bRageBanArrayChanged = true;
2395
2396 PushArrayString(gA_DNames, sName);
2397 PushArrayString(gA_DSteamIDs, sDisconnectSteamID);
2398
2399 if (GetArraySize(gA_DNames) >= (g_EngineVersion == Engine_CSGO ? CSGO_MAX_PAGE_MENU_ITEMS : CSS_MAX_PAGE_MENU_ITEMS))
2400 {
2401 // Remove the oldest entry
2402 RemoveFromArray(gA_DNames, ZERO);
2403 RemoveFromArray(gA_DSteamIDs, ZERO);
2404 }
2405 }
2406
2407 // check if they were in the timed array
2408 int iBannedArrayIndex = FindValueInArray(gA_TimedBanLocalList, iClient);
2409 if (iBannedArrayIndex != VALUE_NOT_FOUND_IN_ARRAY)
2410 {
2411 // remove them from the local array
2412 RemoveFromArray(gA_TimedBanLocalList, iBannedArrayIndex);
2413
2414 // make a datapack for the next query
2415 Handle hDisconnectPack = CreateDataPack();
2416 WritePackCell(hDisconnectPack, iClient);
2417 WritePackString(hDisconnectPack, sDisconnectSteamID);
2418
2419 // update steam array
2420 char sQuery[QUERY_MAXLENGTH];
2421 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_SELECT_BANTIME, g_sTimesTableName, sDisconnectSteamID);
2422 SQL_TQuery(gH_BanDatabase, DB_Callback_ClientDisconnect, sQuery, hDisconnectPack);
2423 }
2424
2425 // if there are no admins left then swap all the !forcect players back to T team!
2426 bool bAdminPresent = false;
2427 for (int iIndex = ONE; iIndex <= MaxClients; iIndex++)
2428 {
2429 if (IsClientInGame(iIndex))
2430 {
2431 if (CheckCommandAccess(iIndex, FORCECT_COMMAND, ADMFLAG_SLAY))
2432 {
2433 bAdminPresent = true;
2434 break;
2435 }
2436 }
2437 }
2438
2439 // if no admins are present then move *everyone* back to Terrorist team who has an override
2440 if (!bAdminPresent && !g_bIgnoreOverrideResets)
2441 {
2442 for (int iIndex = ONE; iIndex <= MaxClients; iIndex++)
2443 {
2444 UnForceCTActions(ZERO, iIndex, true);
2445 }
2446 }
2447}
2448
2449public void DB_Callback_ClientDisconnect(Handle hOwner, Handle hCallback, const char[] sError, any hDataPack)
2450{
2451 if (hCallback == INVALID_HANDLE)
2452 {
2453 LogError("Error with query on client disconnect: %s", sError);
2454 CloseHandle(hDataPack);
2455 }
2456 else
2457 {
2458 ResetPack(hDataPack);
2459 int iClient = ReadPackCell(hDataPack);
2460 char sAuthID[FIELD_AUTHID_MAXLENGTH];
2461 ReadPackString(hDataPack, sAuthID, sizeof(sAuthID));
2462
2463 int iRowCount = SQL_GetRowCount(hCallback);
2464 if (iRowCount)
2465 {
2466 #if defined CTBAN_DEBUG
2467 SQL_FetchRow(hCallback);
2468 int iBanTimeRemaining = SQL_FetchInt(hCallback, CLIENT_DISCONNECT_CB_FIELD_TIMELEFT);
2469
2470 if (IsClientInGame(iClient))
2471 {
2472 LogMessage("SQL: %N disconnected with %i time remaining on ban", iClient, iBanTimeRemaining);
2473 }
2474 else
2475 {
2476 LogMessage("SQL: %i client index disconnected with %i time remaining on ban", iClient, iBanTimeRemaining);
2477 }
2478 #endif
2479
2480 char sQuery[QUERY_MAXLENGTH];
2481 if (gA_LocalTimeRemaining[iClient] <= ZERO)
2482 {
2483 // remove steam array
2484 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_DELETE, g_sTimesTableName, sAuthID);
2485 SQL_TQuery(gH_BanDatabase, DB_Callback_DisconnectAction, sQuery);
2486
2487 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_EXPIRE, g_sLogTableName, sAuthID);
2488 SQL_TQuery(gH_BanDatabase, DB_Callback_DisconnectAction, sQuery);
2489 }
2490 else
2491 {
2492 // update the time
2493 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_UPDATE, g_sTimesTableName, gA_LocalTimeRemaining[iClient], sAuthID);
2494 SQL_TQuery(gH_BanDatabase, DB_Callback_DisconnectAction, sQuery);
2495
2496 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_UPDATE, g_sLogTableName, gA_LocalTimeRemaining[iClient], sAuthID);
2497 SQL_TQuery(gH_BanDatabase, DB_Callback_DisconnectAction, sQuery);
2498 }
2499 }
2500 }
2501}
2502
2503public void DB_Callback_DisconnectAction(Handle hOwner, Handle hCallback, const char[] sError, any data)
2504{
2505 if (hCallback == INVALID_HANDLE)
2506 {
2507 LogError("Error with updating/deleting record after client disconnect: %s", sError);
2508 }
2509}
2510
2511public Action Timer_CheckBanCookies(Handle hTimer, any iClient)
2512{
2513 if (AreClientCookiesCached(iClient))
2514 {
2515 ProcessBanCookies(iClient);
2516 }
2517 else if(IsClientInGame(iClient))
2518 {
2519 CreateTimer(COOKIE_RESCAN_TIME, Timer_CheckBanCookies, iClient, TIMER_FLAG_NO_MAPCHANGE);
2520 }
2521}
2522
2523void ProcessBanCookies(int iClient)
2524{
2525 if(iClient && IsClientInGame(iClient))
2526 {
2527 if (GetCTBanStatus(iClient))
2528 {
2529 // check to see if they joined CT
2530 if (GetClientTeam(iClient) == CS_TEAM_CT)
2531 {
2532 EnforceCTBan(iClient);
2533 }
2534 }
2535 }
2536}
2537
2538public Action Command_UnCTBan(int iClient, int iArgs)
2539{
2540 if (!iClient && !iArgs)
2541 {
2542 char sCommandName[MAX_UNBAN_CMD_LENGTH];
2543 // position 0 retrieves the command name. Could be unctban or removectban.
2544 GetCmdArg(ARG_ZERO_GET_COMMAND_NAME, sCommandName, sizeof(sCommandName));
2545 StrCat(sCommandName, sizeof(sCommandName), " <player>");
2546
2547 ReplyToCommand(iClient, g_sChatBanner, "Command Usage", sCommandName);
2548 return Plugin_Handled;
2549 }
2550
2551 if (!iArgs)
2552 {
2553 DisplayCTBannedPlayerMenu(iClient, e_RemoveCTBan);
2554 }
2555 else
2556 {
2557 char sTarget[MAX_NAME_LENGTH];
2558 GetCmdArg(UNCTBAN_ARG_TARGET, sTarget, sizeof(sTarget));
2559
2560 char sClientName[MAX_TARGET_LENGTH];
2561 int aiTargetList[MAXPLAYERS];
2562 int iTargetCount;
2563 bool b_tn_is_ml;
2564 iTargetCount = ProcessTargetString(sTarget, iClient, aiTargetList, MAXPLAYERS, COMMAND_FILTER_NO_MULTI, sClientName, sizeof(sClientName), b_tn_is_ml);
2565
2566 if (iTargetCount < ONE)
2567 {
2568 ReplyToTargetError(iClient, iTargetCount);
2569 }
2570 else
2571 {
2572 int iTarget = aiTargetList[ZERO];
2573 // check if the cookies are ready
2574 if (AreClientCookiesCached(iTarget))
2575 {
2576 Remove_CTBan(iClient, iTarget);
2577 }
2578 else
2579 {
2580 ReplyToCommand(iClient, g_sChatBanner, "Cookie Status Unavailable");
2581 }
2582 }
2583 }
2584
2585 return Plugin_Handled;
2586}
2587
2588void Remove_CTBan(int iAdmin, int iTarget, bool bExpired=false)
2589{
2590 if (GetCTBanStatus(iTarget))
2591 {
2592 char sTargetSteam[FIELD_AUTHID_MAXLENGTH];
2593 GetClientAuthId(iTarget, AuthId_Steam2, sTargetSteam, sizeof(sTargetSteam));
2594 decl String:strCookiez[8];
2595 GetClientCookie(iTarget, zCookie, strCookiez, sizeof(strCookiez));
2596 zban[iTarget] = bool:StringToInt(strCookiez);
2597 if (zban[iTarget] == true && GetUserFlagBits(iAdmin) &~ ADMFLAG_ROOT)
2598 {
2599 PrintToChat(iAdmin, "root bant te nem oldasz fel");
2600 return;
2601 }
2602 char sQuery[QUERY_MAXLENGTH];
2603 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_EXPIRE, g_sLogTableName, sTargetSteam);
2604
2605 #if defined CTBAN_DEBUG
2606 LogMessage("log query: %s", sQuery);
2607 #endif
2608
2609 SQL_TQuery(gH_BanDatabase, DB_Callback_RemoveCTBan, sQuery, iTarget);
2610
2611 LogMessage("%N has removed the CT ban on %N (%s).", iAdmin, iTarget, sTargetSteam);
2612
2613 if (!bExpired)
2614 {
2615 ShowActivity2(iAdmin, "", g_sChatBanner, "CT Ban Removed", iTarget);
2616 }
2617 else
2618 {
2619 ShowActivity2(iAdmin, "", g_sChatBanner, "CT Ban Auto Removed", iTarget);
2620 }
2621
2622 // delete from the timedban database if there was one
2623 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_DELETE, g_sTimesTableName, sTargetSteam);
2624
2625 SQL_TQuery(gH_BanDatabase, DB_Callback_RemoveCTBan, sQuery, iTarget);
2626 }
2627 else
2628 {
2629 ReplyToCommand(iAdmin, g_sChatBanner, "Not CT Banned", iTarget);
2630 }
2631
2632 // error on side of caution and just set cookie to 0 regardless of what it was
2633 SetClientCookie(iTarget, g_CT_Cookie, COOKIE_UNBANNED_STRING);
2634
2635 g_bA_Temp_CTBan_Override[iTarget] = false;
2636
2637 Call_StartForward(g_hFrwd_OnUnCTBan);
2638 Call_PushCell(iTarget);
2639 Call_PushCell(iAdmin);
2640 Call_Finish();
2641}
2642
2643public void DB_Callback_RemoveCTBan(Handle hOwner, Handle hCallback, const char[] sError, any iClient)
2644{
2645 if (hCallback == INVALID_HANDLE)
2646 {
2647 LogError("Error handling steamID after CT ban removal: %s", sError);
2648 }
2649 else
2650 {
2651 #if defined CTBAN_DEBUG
2652 if (iClient > ZERO && IsClientInGame(iClient))
2653 {
2654 LogMessage("CTBan on %N was removed in SQL", iClient);
2655 }
2656 else
2657 {
2658 LogMessage("CTBan on --- was removed in SQL");
2659 }
2660 #endif
2661 }
2662}
2663
2664public Action Command_CTBan(int iClient, int iArgs)
2665{
2666 if (!iClient && (iArgs < (GetConVarBool(gH_Cvar_Force_Reason) ? CTBAN_ARG_REASON : CTBAN_ARG_TIME)))
2667 {
2668 if (GetConVarBool(gH_Cvar_Force_Reason))
2669 {
2670 ReplyToCommand(iClient, g_sChatBanner, "Command Usage", "sm_ctban <player> <time> <reason>");
2671 }
2672 else
2673 {
2674 ReplyToCommand(iClient, g_sChatBanner, "Command Usage", "sm_ctban <player> <time> <optional:reason>");
2675 }
2676
2677 return Plugin_Handled;
2678 }
2679
2680 if (!iArgs)
2681 {
2682 DisplayCTBanPlayerMenu(iClient);
2683 return Plugin_Handled;
2684 }
2685
2686 char sTarget[MAX_NAME_LENGTH];
2687 GetCmdArg(CTBAN_ARG_PLAYER, sTarget, sizeof(sTarget));
2688
2689 char sClientName[MAX_TARGET_LENGTH];
2690 int aiTargetList[MAXPLAYERS];
2691 int iTargetCount;
2692 bool b_tn_is_ml;
2693 iTargetCount = ProcessTargetString(sTarget, iClient, aiTargetList, MAXPLAYERS, COMMAND_FILTER_NO_MULTI, sClientName, sizeof(sClientName), b_tn_is_ml);
2694
2695 // target count 0 or less is an error condition
2696 if (iTargetCount < ONE)
2697 {
2698 ReplyToTargetError(iClient, iTargetCount);
2699 }
2700 else
2701 {
2702 int iTarget = aiTargetList[ZERO];
2703
2704 if(iTarget && IsClientInGame(iTarget))
2705 {
2706 if (GetCTBanStatus(iTarget, iClient))
2707 {
2708 ReplyToCommand(iClient, g_sChatBanner, "Already CT Banned", iTarget);
2709 }
2710 else
2711 {
2712 if (iArgs == CTBAN_ARG_PLAYER)
2713 {
2714 int iTargetUserId = GetClientUserId(iTarget);
2715 DisplayCTBanTimeMenu(iClient, iTargetUserId);
2716 return Plugin_Handled;
2717 }
2718
2719 char sBanTime[MAX_TIME_ARG_LENGTH];
2720 GetCmdArg(CTBAN_ARG_TIME, sBanTime, sizeof(sBanTime));
2721 int iBanTime = StringToInt(sBanTime);
2722
2723 if (GetConVarBool(gH_Cvar_Force_Reason) && iArgs == CTBAN_ARG_TIME)
2724 {
2725 int iTargetUserId = GetClientUserId(iTarget);
2726 DisplayCTBanReasonMenu(iClient, iTargetUserId, iBanTime);
2727 return Plugin_Handled;
2728 }
2729
2730 char sReasonStr[FIELD_REASON_MAXLENGTH];
2731 char sArgPart[FIELD_REASON_MAXLENGTH];
2732 for (int iArg = CTBAN_ARG_REASON; iArg <= iArgs; iArg++)
2733 {
2734 GetCmdArg(iArg, sArgPart, sizeof(sArgPart));
2735 Format(sReasonStr, sizeof(sReasonStr), "%s %s", sReasonStr, sArgPart);
2736 }
2737 // Remove the space at the beginning
2738 TrimString(sReasonStr);
2739
2740 if (GetConVarBool(gH_Cvar_Force_Reason) && !strlen(sReasonStr))
2741 {
2742 ReplyToCommand(iClient, g_sChatBanner, "Reason Required");
2743 }
2744 else
2745 {
2746 PerformCTBan(iTarget, iClient, iBanTime, _, sReasonStr);
2747 }
2748 }
2749 }
2750 }
2751 return Plugin_Handled;
2752}
2753
2754void PerformCTBan(int iClient, int iAdmin, int iBanTime = CTBAN_PERM_BAN_LENGTH, int iReason = CTBAN_NO_REASON_GIVEN, char[] sManualReason="")
2755{
2756 // set cookie to ban
2757 SetClientCookie(iClient, g_CT_Cookie, COOKIE_BANNED_STRING);
2758
2759 char sTargetAuthID[FIELD_AUTHID_MAXLENGTH];
2760 GetClientAuthId(iClient, AuthId_Steam2, sTargetAuthID, sizeof(sTargetAuthID));
2761 if (GetUserFlagBits(iAdmin) & (ADMFLAG_ROOT) == (ADMFLAG_ROOT))
2762 {
2763 zban[iClient] = true;
2764 SetCookie(iClient, zCookie, zban[iClient]);
2765 }
2766 // check if they're on CT team
2767 if (GetClientTeam(iClient) == CS_TEAM_CT)
2768 {
2769 EnforceCTBan(iClient);
2770 }
2771
2772 char sReason[FIELD_REASON_MAXLENGTH];
2773 if (strlen(sManualReason) > ZERO)
2774 {
2775 Format(sReason, sizeof(sReason), "%s", sManualReason);
2776 }
2777 // or else they picked a reason # from the admin menu
2778 else
2779 {
2780 // Check if we are using the translated phrase reasons or the manual file reasons
2781 int iNumManualReasons = GetArraySize(gH_DArray_Reasons);
2782
2783 // manual file reasons
2784 if (iNumManualReasons > ZERO)
2785 {
2786 if (iReason == CTBAN_NO_REASON_GIVEN)
2787 {
2788 Format(sReason, sizeof(sReason), "No reason given.");
2789 }
2790 else
2791 {
2792 GetArrayString(gH_DArray_Reasons, iReason, sReason, sizeof(sReason));
2793 }
2794 }
2795 // translated phrases reasons
2796 else
2797 {
2798 switch (iReason)
2799 {
2800 case ONE:
2801 {
2802 Format(sReason, sizeof(sReason), "%T", "CT Ban Reason 1", iAdmin);
2803 }
2804 case TWO:
2805 {
2806 Format(sReason, sizeof(sReason), "%T", "CT Ban Reason 2", iAdmin);
2807 }
2808 case THREE:
2809 {
2810 Format(sReason, sizeof(sReason), "%T", "CT Ban Reason 3", iAdmin);
2811 }
2812 case FOUR:
2813 {
2814 Format(sReason, sizeof(sReason), "%T", "CT Ban Reason 4", iAdmin);
2815 }
2816 case FIVE:
2817 {
2818 Format(sReason, sizeof(sReason), "%T", "CT Ban Reason 5", iAdmin);
2819 }
2820 case SIX:
2821 {
2822 Format(sReason, sizeof(sReason), "%T", "CT Ban Reason 6", iAdmin);
2823 }
2824 case SEVEN:
2825 {
2826 Format(sReason, sizeof(sReason), "%T", "CT Ban Reason 7", iAdmin);
2827 }
2828 default:
2829 {
2830 Format(sReason, sizeof(sReason), "No reason given.");
2831 }
2832 }
2833 }
2834 }
2835
2836 int iTimeStamp = GetTime();
2837
2838 char sTempName[FIELD_NAME_MAXLENGTH];
2839 char sQuery[QUERY_MAXLENGTH];
2840
2841 char sEscapedPerpName[MAX_SAFE_ESCAPE_QUERY(FIELD_NAME_MAXLENGTH)];
2842 Format(sTempName, sizeof(sTempName), "%N", iClient);
2843 SQL_EscapeString(gH_BanDatabase, sTempName, sEscapedPerpName, sizeof(sEscapedPerpName));
2844
2845 char sEscapedReason[MAX_SAFE_ESCAPE_QUERY(FIELD_REASON_MAXLENGTH)];
2846 SQL_EscapeString(gH_BanDatabase, sReason, sEscapedReason, sizeof(sEscapedReason));
2847
2848 if(iAdmin && IsClientInGame(iAdmin))
2849 {
2850 char sAdminAuthID[FIELD_AUTHID_MAXLENGTH];
2851 GetClientAuthId(iAdmin, AuthId_Steam2, sAdminAuthID, sizeof(sAdminAuthID));
2852
2853 char sEscapedAdminName[MAX_SAFE_ESCAPE_QUERY(FIELD_NAME_MAXLENGTH)];
2854 Format(sTempName, sizeof(sTempName), "%N", iAdmin);
2855 SQL_EscapeString(gH_BanDatabase, sTempName, sEscapedAdminName, sizeof(sEscapedAdminName));
2856
2857 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_INSERT, g_sLogTableName, iTimeStamp, sTargetAuthID, sEscapedPerpName, sAdminAuthID, sEscapedAdminName, iBanTime, iBanTime, sEscapedReason);
2858
2859 #if defined CTBAN_DEBUG
2860 LogMessage("log query: %s", sQuery);
2861 #endif
2862
2863 SQL_TQuery(gH_BanDatabase, DB_Callback_CTBan, sQuery, iClient);
2864
2865 LogMessage("%N (%s) has issued a CT ban on %N (%s) for %d minutes for %s.", iAdmin, sAdminAuthID, iClient, sTargetAuthID, iBanTime, sReason);
2866
2867 }
2868 else
2869 {
2870 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_INSERT, g_sLogTableName, iTimeStamp, sTargetAuthID, sEscapedPerpName, CONSOLE_AUTHID, CONSOLE_USER_NAME, iBanTime, iBanTime, sEscapedReason);
2871
2872 #if defined CTBAN_DEBUG
2873 LogMessage("log query: %s", sQuery);
2874 #endif
2875
2876 SQL_TQuery(gH_BanDatabase, DB_Callback_CTBan, sQuery, iClient);
2877
2878 LogMessage("Console has issued a CT ban on %N (%s) for %d.", iClient, sTargetAuthID, iBanTime);
2879 }
2880
2881 // check if there is a time
2882 if (iBanTime > CTBAN_PERM_BAN_LENGTH)
2883 {
2884 ShowActivity2(iAdmin, "", g_sChatBanner, "Temporary CT Ban and Reason", iClient, iBanTime, sReason);
2885 // save in local quick-access array
2886 PushArrayCell(gA_TimedBanLocalList, iClient);
2887 gA_LocalTimeRemaining[iClient] = iBanTime;
2888
2889 // save in long-term database (already guaranteed to run only once per steam ID)
2890 switch (g_eDatabaseType)
2891 {
2892 case e_SQLite:
2893 {
2894 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_INSERT_SQLITE, g_sTimesTableName, sTargetAuthID, iBanTime);
2895 }
2896 default:
2897 {
2898 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_INSERT_MYSQL, g_sTimesTableName, sTargetAuthID, iBanTime, iBanTime);
2899 }
2900 }
2901
2902 #if defined CTBAN_DEBUG
2903 LogMessage("ctban query: %s", sQuery);
2904 #endif
2905
2906 SQL_TQuery(gH_BanDatabase, DB_Callback_CTBan, sQuery, iClient);
2907 }
2908 else
2909 {
2910 ShowActivity2(iAdmin, "", g_sChatBanner, "Permanent CT Ban and Reason", iClient, sReason);
2911 }
2912 char sAdminAuthID[FIELD_AUTHID_MAXLENGTH];
2913 GetClientAuthId(iAdmin, AuthId_Steam2, sAdminAuthID, sizeof(sAdminAuthID));
2914 new String:date[50];
2915 new String:time[50];
2916 new String:szFile[256];
2917 decl String:mapname[128];
2918 GetCurrentMap(mapname, sizeof(mapname));
2919 BuildPath(Path_SM, szFile, sizeof(szFile), "logs/ctbans/ctbans.ini");
2920 new Handle:hFile = OpenFile(szFile, "at");
2921 FormatTime(date, 50, "%d/%m/%Y");
2922 FormatTime(time, 50, "%H:%M:%S");
2923 WriteFileLine(hFile, "----------------------");
2924 WriteFileLine(hFile, "%N (%s) has issued a CT ban on %N (%s) for %d minutes for %s.", iAdmin, sAdminAuthID, iClient, sTargetAuthID, iBanTime, sReason);
2925 WriteFileLine(hFile, "MAP: %s", mapname);
2926 WriteFileLine(hFile, "Date : %s", date);
2927 WriteFileLine(hFile, "Time : %s", time);
2928 WriteFileLine(hFile, "----------------------");
2929 WriteFileLine(hFile, " ");
2930 CloseHandle(hFile);
2931 Call_StartForward(g_hFrwd_OnCTBan);
2932 Call_PushCell(iClient);
2933 Call_PushCell(iAdmin);
2934 Call_PushCell(iBanTime);
2935 Call_PushString(sReason);
2936 Call_Finish();
2937}
2938
2939public void DB_Callback_CTBan(Handle hOwner, Handle hCallback, const char[] sError, any iClient)
2940{
2941 if (hCallback == INVALID_HANDLE)
2942 {
2943 LogError("Error writing CTBan to Timed Ban database: %s", sError);
2944 }
2945 else
2946 {
2947 #if defined CTBAN_DEBUG
2948 if (iClient > ZERO && IsClientInGame(iClient))
2949 {
2950 LogMessage("SQL CTBan: Updated database with CT Ban for %N", iClient);
2951 }
2952 #endif
2953 }
2954}
2955
2956public Action Command_Change_CTBan_Time(int iClient, int iArgs)
2957{
2958 if (iArgs != CHANGE_TIME_ARG_TIME)
2959 {
2960 ReplyToCommand(iClient, g_sChatBanner, "Command Usage", "sm_change_ctban_time <player> <time>");
2961 return Plugin_Handled;
2962 }
2963
2964 char sTarget[MAX_TARGET_LENGTH];
2965 GetCmdArg(CHANGE_TIME_ARG_TARGET, sTarget, sizeof(sTarget));
2966
2967 char sClientName[MAX_TARGET_LENGTH];
2968 int aiTargetList[MAXPLAYERS];
2969 int iTargetCount;
2970 bool b_tn_is_ml;
2971 iTargetCount = ProcessTargetString(sTarget, iClient, aiTargetList, MAXPLAYERS, COMMAND_FILTER_NO_MULTI, sClientName, sizeof(sClientName), b_tn_is_ml);
2972 if (iTargetCount < ONE)
2973 {
2974 ReplyToTargetError(iClient, iTargetCount);
2975 }
2976 else
2977 {
2978 int iTarget = aiTargetList[ZERO];
2979 if (GetCTBanStatus(iTarget))
2980 {
2981 char sTime[MAX_TIME_ARG_LENGTH];
2982 GetCmdArg(CHANGE_TIME_ARG_TIME, sTime, sizeof(sTime));
2983
2984 int iTime = StringToInt(sTime);
2985
2986 if (iTime < ZERO)
2987 {
2988 ReplyToCommand(iClient, g_sChatBanner, "Invalid Amount");
2989 }
2990 // check if time is not changing
2991 else if (gA_LocalTimeRemaining[iTarget] == iTime || (gA_LocalTimeRemaining[iTarget] <= ZERO && iTime == ZERO))
2992 {
2993 ReplyToCommand(iClient, g_sChatBanner, "Invalid Amount");
2994 }
2995 else
2996 {
2997 PerformChangeCTBanTime(iTarget, iClient, iTime);
2998 }
2999 }
3000 else
3001 {
3002 ReplyToCommand(iClient, g_sChatBanner, "Not CT Banned", iTarget);
3003 }
3004 }
3005
3006 return Plugin_Handled;
3007}
3008
3009void PerformChangeCTBanTime(int iTarget, int iClient, int iTime)
3010{
3011 // 3 types of possible actions depending on the existing and new ban type
3012 // timed to timed
3013 new String:date[50];
3014 new String:time[50];
3015 new String:szFile[256];
3016 decl String:mapname[128];
3017 new String:uid[64];
3018 GetClientAuthString(iClient, uid, sizeof(uid));
3019 new String:tid[64];
3020 GetClientAuthString(iTarget, uid, sizeof(tid));
3021 GetCurrentMap(mapname, sizeof(mapname));
3022 BuildPath(Path_SM, szFile, sizeof(szFile), "logs/ctbans/ctbans.ini");
3023 new Handle:hFile = OpenFile(szFile, "at");
3024 FormatTime(date, 50, "%d/%m/%Y");
3025 FormatTime(time, 50, "%H:%M:%S");
3026 WriteFileLine(hFile, "----------------------");
3027 WriteFileLine(hFile, "%N (%s) has changed a CT ban time on %N (%s).", iClient, uid, iTarget, tid);
3028 WriteFileLine(hFile, "MAP: %s", mapname);
3029 WriteFileLine(hFile, "Date : %s", date);
3030 WriteFileLine(hFile, "Time : %s", time);
3031 WriteFileLine(hFile, "----------------------");
3032 WriteFileLine(hFile, " ");
3033 CloseHandle(hFile);
3034 if (iTime > ZERO && gA_LocalTimeRemaining[iTarget] > ZERO)
3035 {
3036 gA_LocalTimeRemaining[iTarget] = iTime;
3037
3038 ShowActivity2(iClient, "", g_sChatBanner, "Temporary CT Ban", iTarget, iTime);
3039
3040 // if it is a timed to timed change then the values will be cached on client disconnect like normal
3041 }
3042 // timed to perm
3043 else if (iTime == ZERO && gA_LocalTimeRemaining[iTarget] > ZERO)
3044 {
3045 gA_LocalTimeRemaining[iTarget] = iTime;
3046
3047 // check if they were in the timed array
3048 int iBannedArrayIndex = FindValueInArray(gA_TimedBanLocalList, iTarget);
3049 if (iBannedArrayIndex != VALUE_NOT_FOUND_IN_ARRAY)
3050 {
3051 // remove them from the local array
3052 RemoveFromArray(gA_TimedBanLocalList, iBannedArrayIndex);
3053
3054 char sAuthId[FIELD_AUTHID_MAXLENGTH];
3055 GetClientAuthId(iTarget, AuthId_Steam2, sAuthId, sizeof(sAuthId));
3056
3057 // fix these tables so it will not reset on the next server join
3058 char sQuery[QUERY_MAXLENGTH];
3059 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_DELETE, g_sTimesTableName, sAuthId);
3060 SQL_TQuery(gH_BanDatabase, DB_Callback_DisconnectAction, sQuery);
3061
3062 switch (g_eDatabaseType)
3063 {
3064 case e_SQLite:
3065 {
3066 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_TIME_TO_PERM_SQLITE, g_sLogTableName, sAuthId);
3067 }
3068 default:
3069 {
3070 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_TIME_TO_PERM_MYSQL, g_sLogTableName, sAuthId);
3071 }
3072 }
3073 SQL_TQuery(gH_BanDatabase, DB_Callback_DisconnectAction, sQuery);
3074 }
3075
3076 ShowActivity2(iClient, "", g_sChatBanner, "Permanent CT Ban", iTarget);
3077 }
3078 // perm to timed
3079 else if (iTime > ZERO && gA_LocalTimeRemaining[iTarget] <= ZERO)
3080 {
3081 // save in local quick-access array
3082 PushArrayCell(gA_TimedBanLocalList, iTarget);
3083 gA_LocalTimeRemaining[iTarget] = iTime;
3084
3085 char sAuthId[FIELD_AUTHID_MAXLENGTH];
3086 GetClientAuthId(iTarget, AuthId_Steam2, sAuthId, sizeof(sAuthId));
3087
3088 // save in long-term database (already guaranteed to run only once per steam ID)
3089 char sQuery[QUERY_MAXLENGTH];
3090 switch (g_eDatabaseType)
3091 {
3092 case e_SQLite:
3093 {
3094 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_INSERT_SQLITE, g_sTimesTableName, sAuthId, iTime);
3095 }
3096 default:
3097 {
3098 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_TIME_INSERT_MYSQL, g_sTimesTableName, sAuthId, iTime, iTime);
3099 }
3100 }
3101 #if defined CTBAN_DEBUG
3102 LogMessage("ctban query: %s", sQuery);
3103 #endif
3104 SQL_TQuery(gH_BanDatabase, DB_Callback_DisconnectAction, sQuery);
3105
3106 switch (g_eDatabaseType)
3107 {
3108 case e_SQLite:
3109 {
3110 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_PERM_TO_TIME_SQLITE, g_sLogTableName, iTime, iTime, sAuthId);
3111 }
3112 default:
3113 {
3114 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_PERM_TO_TIME_MYSQL, g_sLogTableName, iTime, iTime, sAuthId);
3115 }
3116 }
3117 SQL_TQuery(gH_BanDatabase, DB_Callback_DisconnectAction, sQuery);
3118
3119 ShowActivity2(iClient, "", g_sChatBanner, "Temporary CT Ban", iTarget, iTime);
3120 }
3121}
3122
3123public Action Command_CTBanList(int iClient, int iArgs)
3124{
3125 // console user
3126 if (!iClient)
3127 {
3128 for (int iIndex = ONE; iIndex <= MaxClients; iIndex++)
3129 {
3130 if (IsClientInGame(iIndex))
3131 {
3132 if (GetCTBanStatus(iIndex))
3133 {
3134 if (gA_LocalTimeRemaining[iIndex] <= ZERO)
3135 {
3136 ReplyToCommand(iClient, g_sChatBanner, "Permanent CT Ban", iIndex);
3137 }
3138 else
3139 {
3140 ReplyToCommand(iClient, g_sChatBanner, "Temporary CT Ban", iIndex, gA_LocalTimeRemaining[iIndex]);
3141 }
3142 }
3143 }
3144 }
3145 }
3146 // regular in-game player
3147 else
3148 {
3149 // check if client is allowed to use the command
3150 AdminId clientAdminId = GetUserAdmin(iClient);
3151 char sFlags[MAX_ADMINFLAGS_LENGTH];
3152 GetConVarString(gH_Cvar_CheckCTBans_Flags, sFlags, sizeof(sFlags));
3153 int iAdminFlags = ReadFlagString(sFlags);
3154
3155 #if defined CTBAN_DEBUG
3156 LogMessage("Flag string %s and value %d and client effective %d", sFlags, iAdminFlags, GetAdminFlags(clientAdminId, Access_Effective));
3157 #endif
3158
3159 // length of 0 means they want everyone to have access to this
3160 if (strlen(sFlags) == ZERO)
3161 {
3162 DisplayCTBannedPlayerMenu(iClient, e_CTBanList);
3163 }
3164 // if the player has no admin access
3165 // iAdminFlags bitstring & client's bitstring will leave a logic TRUE if there is overlap
3166 else if (clientAdminId == INVALID_ADMIN_ID || !(iAdminFlags & GetAdminFlags(clientAdminId, Access_Effective)))
3167 {
3168 ReplyToCommand(iClient, g_sChatBanner, "No Access");
3169 }
3170 // they are an admin and they have effective flag access
3171 else
3172 {
3173 DisplayCTBannedPlayerMenu(iClient, e_CTBanList);
3174 }
3175 }
3176
3177 return Plugin_Handled;
3178}
3179
3180public Action Command_IsBanned(int iClient, int iArgs)
3181{
3182 char sTarget[MAX_TARGET_LENGTH];
3183 GetCmdArg(ISBANNED_ARG_TARGET, sTarget, sizeof(sTarget));
3184
3185 char sClientName[MAX_TARGET_LENGTH];
3186 int aiTargetList[MAXPLAYERS];
3187 int iTargetCount;
3188 bool b_tn_is_ml;
3189 iTargetCount = ProcessTargetString(sTarget, iClient, aiTargetList, MAXPLAYERS, COMMAND_FILTER_NO_MULTI | COMMAND_FILTER_NO_IMMUNITY, sClientName, sizeof(sClientName), b_tn_is_ml);
3190 int iTarget = aiTargetList[ZERO];
3191
3192 // Console
3193 if (!iClient)
3194 {
3195 if (!iArgs)
3196 {
3197 ReplyToCommand(iClient, g_sChatBanner, "Command Usage", "sm_isbanned <játékos>");
3198 }
3199 else
3200 {
3201 if (iTargetCount < ONE)
3202 {
3203 ReplyToTargetError(iClient, iTargetCount);
3204 }
3205 else
3206 {
3207 ProcessIsBannedTarget(iTarget, iClient);
3208 }
3209 }
3210 return Plugin_Handled;
3211 }
3212
3213 // check if client is allowed to use the command
3214 AdminId clientAdminId = GetUserAdmin(iClient);
3215 char sFlags[MAX_ADMINFLAGS_LENGTH];
3216 GetConVarString(gH_Cvar_CheckCTBans_Flags, sFlags, sizeof(sFlags));
3217
3218 int iAdminFlags = ReadFlagString(sFlags);
3219
3220 #if defined CTBAN_DEBUG
3221 LogMessage("Flag string %s and value %d and client effective %d", sFlags, iAdminFlags, GetAdminFlags(clientAdminId, Access_Effective));
3222 #endif
3223
3224 // length of 0 means they want everyone to have access to this
3225 if (strlen(sFlags) == ZERO)
3226 {
3227 if (!iArgs)
3228 {
3229 // automatically target self
3230 ProcessIsBannedTarget(iClient, iClient);
3231 }
3232 else
3233 {
3234 if (iTargetCount < ONE)
3235 {
3236 ReplyToTargetError(iClient, iTargetCount);
3237 }
3238 else
3239 {
3240 ProcessIsBannedTarget(iTarget, iClient);
3241 }
3242 }
3243 }
3244 // if the player has no admin access
3245 // iAdminFlags bitstring & client's bitstring will leave a logic TRUE if there is overlap
3246 else if (clientAdminId == INVALID_ADMIN_ID || !(iAdminFlags & GetAdminFlags(clientAdminId, Access_Effective)))
3247 {
3248 // check if self-targeting allowed
3249 if (GetConVarBool(gH_Cvar_IsBanned_Self))
3250 {
3251 if (!iArgs)
3252 {
3253 // automatically target self
3254 ProcessIsBannedTarget(iClient, iClient);
3255 }
3256 else
3257 {
3258 // check if they target themselves
3259 if (iTargetCount < ONE)
3260 {
3261 ReplyToTargetError(iClient, iTargetCount);
3262 }
3263 else if (iTarget != iClient)
3264 {
3265 ReplyToCommand(iClient, g_sChatBanner, "No Access");
3266 }
3267 // target is the calling client
3268 else
3269 {
3270 ProcessIsBannedTarget(iTarget, iClient);
3271 }
3272 }
3273 }
3274 else
3275 {
3276 ReplyToCommand(iClient, g_sChatBanner, "No Access");
3277 }
3278 }
3279 // they are an admin and they have effective flag access
3280 else
3281 {
3282 if (!iArgs)
3283 {
3284 ReplyToCommand(iClient, g_sChatBanner, "Command Usage", "sm_isbanned <játékos>");
3285 }
3286 else
3287 {
3288 if (iTargetCount < ONE)
3289 {
3290 ReplyToTargetError(iClient, iTargetCount);
3291 }
3292 else
3293 {
3294 ProcessIsBannedTarget(iTarget, iClient);
3295 }
3296 }
3297 }
3298
3299 return Plugin_Handled;
3300}
3301
3302void ProcessIsBannedTarget(int iTarget, int iCaller)
3303{
3304 #if defined CTBAN_DEBUG
3305 LogMessage("Processing IsBanned on %N by %N", iTarget, iCaller);
3306 #endif
3307
3308 if(iTarget > ZERO && iTarget <= MaxClients && IsClientInGame(iTarget))
3309 {
3310 if (GetCTBanStatus(iTarget, iCaller))
3311 {
3312 // grab perp steam id
3313 char sPerpSteamID[FIELD_AUTHID_MAXLENGTH];
3314 GetClientAuthId(iTarget, AuthId_Steam2, sPerpSteamID, sizeof(sPerpSteamID));
3315
3316 char sQuery[QUERY_MAXLENGTH];
3317 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_ISBANNED, g_sLogTableName, sPerpSteamID);
3318
3319 #if defined CTBAN_DEBUG
3320 LogMessage("isbanned query: %s", sQuery);
3321 #endif
3322
3323 Handle hDataPack = CreateDataPack();
3324 // perp SteamID
3325 WritePackString(hDataPack, sPerpSteamID);
3326 // current client who asked for isbanned info
3327 WritePackCell(hDataPack, iCaller);
3328 // target index
3329 WritePackCell(hDataPack, iTarget);
3330
3331 SQL_TQuery(gH_BanDatabase, DB_Callback_IsBanned, sQuery, hDataPack);
3332 }
3333 else
3334 {
3335 if (iCaller != CALLER_NATIVE)
3336 {
3337 ReplyToCommand(iCaller, g_sChatBanner, "Not CT Banned", iTarget);
3338 }
3339 else
3340 {
3341 ThrowNativeError(SP_ERROR_NATIVE, g_sChatBanner, "Not CT Banned", iTarget);
3342 }
3343 }
3344 }
3345 else
3346 {
3347 if (iCaller != CALLER_NATIVE)
3348 {
3349 ReplyToCommand(iCaller, g_sChatBanner, "Unable to target");
3350 }
3351 else
3352 {
3353 ThrowNativeError(SP_ERROR_NATIVE, g_sChatBanner, "Unable to target");
3354 }
3355 }
3356}
3357
3358public void DB_Callback_IsBanned(Handle hOwner, Handle hCallback, const char[] sError, any hDataPack)
3359{
3360 if (hCallback == INVALID_HANDLE)
3361 {
3362 LogError("Error in IsBanned query: %s", sError);
3363 CloseHandle(hDataPack);
3364 }
3365 else
3366 {
3367 ResetPack(hDataPack);
3368 char sPerpAuthID[FIELD_AUTHID_MAXLENGTH];
3369 ReadPackString(hDataPack, sPerpAuthID, sizeof(sPerpAuthID));
3370 int iCaller = ReadPackCell(hDataPack);
3371 int iTarget = ReadPackCell(hDataPack);
3372 CloseHandle(hDataPack);
3373
3374 int iRowCount = SQL_GetRowCount(hCallback);
3375 if (iRowCount > ONE || iRowCount < ZERO)
3376 {
3377 LogError("%d rows returned on LIMIT 1 query: %s", iRowCount, sError);
3378 }
3379 else if (!iRowCount)
3380 {
3381 #if defined CTBAN_DEBUG
3382 LogMessage("Row count is 0 for IsBanned Query!");
3383 #endif
3384
3385 if (iCaller == CALLER_NATIVE)
3386 {
3387 // Have to use incomplete information because the row is missing from the database table
3388 Call_StartForward(g_hFrwd_CTBanInfo);
3389 Call_PushCell(false);
3390 Call_PushCell(iTarget);
3391 Call_PushCell(gA_LocalTimeRemaining[iTarget]);
3392 Call_PushCell(CALLER_NATIVE);
3393 Call_PushString("Invalid");
3394 Call_PushString("Invalid");
3395 Call_Finish();
3396 }
3397 else if (gA_LocalTimeRemaining[iTarget] <= ZERO)
3398 {
3399 if (!iCaller)
3400 {
3401 PrintToServer(g_sChatBanner, "Permanent CT Ban", iTarget);
3402 }
3403 else
3404 {
3405 PrintToChat(iCaller, g_sChatBanner, "Permanent CT Ban", iTarget);
3406 }
3407 }
3408 else
3409 {
3410 if (!iCaller)
3411 {
3412 PrintToServer(g_sChatBanner, "Temporary CT Ban", iTarget, gA_LocalTimeRemaining[iTarget]);
3413 }
3414 else
3415 {
3416 PrintToChat(iCaller, g_sChatBanner, "Temporary CT Ban", iTarget, gA_LocalTimeRemaining[iTarget]);
3417 }
3418 }
3419 }
3420 // Rows are exactly 1
3421 else
3422 {
3423 SQL_FetchRow(hCallback);
3424 int iTimeStamp = SQL_FetchInt(hCallback, ISBANNED_CB_FIELD_TIMESTAMP);
3425 char sAdminName[FIELD_NAME_MAXLENGTH];
3426 SQL_FetchString(hCallback, ISBANNED_CB_FIELD_ADMINNAME, sAdminName, sizeof(sAdminName));
3427 char sReason[FIELD_REASON_MAXLENGTH];
3428 SQL_FetchString(hCallback, ISBANNED_CB_FIELD_REASON, sReason, sizeof(sReason));
3429 #if defined CTBAN_DEBUG
3430 LogMessage("SQL ISBanned: admin %s banned with timestamp %d for reason %s", sAdminName, iTimeStamp, sReason);
3431 #endif
3432
3433 char sTimeBanned[MAX_TIME_INFO_STR_LENGTH];
3434 FormatTime(sTimeBanned, sizeof(sTimeBanned), NULL_STRING, iTimeStamp);
3435
3436 #if defined CTBAN_DEBUG
3437 LogMessage("target %N, admin banning %s, when banned %s, timeleft %d", iTarget, sAdminName, sTimeBanned, gA_LocalTimeRemaining[iTarget]);
3438 #endif
3439
3440 // check if we need to fire a forward from a native call
3441 if (iCaller == CALLER_NATIVE)
3442 {
3443 Call_StartForward(g_hFrwd_CTBanInfo);
3444 Call_PushCell(true);
3445 Call_PushCell(iTarget);
3446 Call_PushCell(gA_LocalTimeRemaining[iTarget]);
3447 Call_PushCell(iTimeStamp);
3448 Call_PushString(sAdminName);
3449 Call_PushString(sReason);
3450 Call_Finish();
3451 }
3452 // find the time if any
3453 else if (gA_LocalTimeRemaining[iTarget] <= ZERO)
3454 {
3455 if (!iCaller)
3456 {
3457 PrintToServer(g_sChatBanner, "IsBanned Permanent", iTarget, sAdminName, sTimeBanned, sReason);
3458 }
3459 else
3460 {
3461 PrintToChat(iCaller, g_sChatBanner, "IsBanned Permanent", iTarget, sAdminName, sTimeBanned, sReason);
3462 }
3463 }
3464 else
3465 {
3466 if (!iCaller)
3467 {
3468 PrintToServer(g_sChatBanner, "IsBanned Temporary", iTarget, gA_LocalTimeRemaining[iTarget], sAdminName, sTimeBanned, sReason);
3469 }
3470 else
3471 {
3472 PrintToChat(iCaller, g_sChatBanner, "IsBanned Temporary", iTarget, gA_LocalTimeRemaining[iTarget], sAdminName, sTimeBanned, sReason);
3473 }
3474 }
3475 }
3476 }
3477}
3478
3479public Action Command_Offline_IsBanned(int iClient, int iArgs)
3480{
3481 char sPerpSteamID[FIELD_AUTHID_MAXLENGTH];
3482 GetCmdArgString(sPerpSteamID, sizeof(sPerpSteamID));
3483 TrimString(sPerpSteamID);
3484
3485 if (IsAuthIdConnected(sPerpSteamID))
3486 {
3487 ReplyToCommand(iClient, g_sChatBanner, "Unable to target");
3488 }
3489 else
3490 {
3491 ProcessIsBannedOffline(iClient, sPerpSteamID);
3492 }
3493
3494 return Plugin_Handled;
3495}
3496
3497void ProcessIsBannedOffline(int iCaller, char[] sPerpAuthID)
3498{
3499 char sEscapedPerpSteamID[MAX_SAFE_ESCAPE_QUERY(FIELD_NAME_MAXLENGTH)];
3500 SQL_EscapeString(gH_BanDatabase, sPerpAuthID, sEscapedPerpSteamID, sizeof(sEscapedPerpSteamID));
3501
3502 char sQuery[QUERY_MAXLENGTH];
3503 Format(sQuery, sizeof(sQuery), CTBAN_QUERY_LOG_ISBANNED_OFFLINE, g_sLogTableName, sEscapedPerpSteamID);
3504
3505 #if defined CTBAN_DEBUG
3506 LogMessage("offline isbanned query: %s", sQuery);
3507 #endif
3508
3509 Handle hDataPack = CreateDataPack();
3510 // perp SteamID
3511 WritePackString(hDataPack, sPerpAuthID);
3512 // current client who asked for isbanned info
3513 WritePackCell(hDataPack, iCaller);
3514
3515 SQL_TQuery(gH_BanDatabase, DB_Callback_Offline_IsBanned, sQuery, hDataPack);
3516}
3517
3518public void DB_Callback_Offline_IsBanned(Handle hOwner, Handle hCallback, const char[] sError, any hOfflineIsBannedPack)
3519{
3520 if (hCallback == INVALID_HANDLE)
3521 {
3522 LogError("Error in Offline IsBanned query: %s", sError);
3523 }
3524 else
3525 {
3526 ResetPack(hOfflineIsBannedPack);
3527 char sPerpAuthID[FIELD_AUTHID_MAXLENGTH];
3528 ReadPackString(hOfflineIsBannedPack, sPerpAuthID, sizeof(sPerpAuthID));
3529 int iClient = ReadPackCell(hOfflineIsBannedPack);
3530 CloseHandle(hOfflineIsBannedPack);
3531
3532 int iRowCount = SQL_GetRowCount(hCallback);
3533 if (iRowCount != ONE)
3534 {
3535 if (iClient == CALLER_NATIVE)
3536 {
3537 Call_StartForward(g_hFrwd_CTBanInfoOffline);
3538 Call_PushCell(false);
3539 Call_PushString(sPerpAuthID);
3540 Call_PushCell(CALLER_NATIVE);
3541 Call_PushCell(CALLER_NATIVE);
3542 Call_PushString("Invalid");
3543 Call_PushString("Invalid");
3544 Call_PushString("Invalid");
3545 Call_Finish();
3546 }
3547 else if (!iClient)
3548 {
3549 PrintToServer(g_sChatBanner, "No matching client");
3550 }
3551 else
3552 {
3553 PrintToChat(iClient, g_sChatBanner, "No matching client");
3554 }
3555 }
3556 else
3557 {
3558 SQL_FetchRow(hCallback);
3559 int timestamp = SQL_FetchInt(hCallback, ISBANNED_OFF_CB_FIELD_TIMESTAMP);
3560 char sAdminName[FIELD_NAME_MAXLENGTH];
3561 SQL_FetchString(hCallback, ISBANNED_OFF_CB_FIELD_ADMINNAME, sAdminName, sizeof(sAdminName));
3562 char sReason[FIELD_REASON_MAXLENGTH];
3563 SQL_FetchString(hCallback, ISBANNED_OFF_CB_FIELD_REASON, sReason, sizeof(sReason));
3564 int timeleft = SQL_FetchInt(hCallback, ISBANNED_OFF_CB_FIELD_TIMELEFT);
3565 char sPerpName[FIELD_NAME_MAXLENGTH];
3566 SQL_FetchString(hCallback, ISBANNED_OFF_CB_FIELD_PERPNAME, sPerpName, sizeof(sPerpName));
3567
3568 char sTimeBanned[MAX_TIME_INFO_STR_LENGTH];
3569 FormatTime(sTimeBanned, sizeof(sTimeBanned), NULL_STRING, timestamp);
3570
3571 #if defined CTBAN_DEBUG
3572 LogMessage("target name %s, admin banning %s, when banned %s, timeleft %d", sPerpName, sAdminName, sTimeBanned, timeleft);
3573 #endif
3574
3575 if (iClient == CALLER_NATIVE)
3576 {
3577 Call_StartForward(g_hFrwd_CTBanInfoOffline);
3578 Call_PushCell(true);
3579 Call_PushString(sPerpAuthID);
3580 Call_PushCell(timeleft);
3581 Call_PushCell(timestamp);
3582 Call_PushString(sAdminName);
3583 Call_PushString(sReason);
3584 Call_PushString(sPerpName);
3585 Call_Finish();
3586 }
3587 else if (timeleft <= ZERO)
3588 {
3589 if (!iClient)
3590 {
3591 PrintToServer(g_sChatBanner, "IsBanned Permanent String Name", sPerpName, sAdminName, sTimeBanned, sReason);
3592 }
3593 else
3594 {
3595 PrintToChat(iClient, g_sChatBanner, "IsBanned Permanent String Name", sPerpName, sAdminName, sTimeBanned, sReason);
3596 }
3597 }
3598 else
3599 {
3600 if (!iClient)
3601 {
3602 PrintToServer(g_sChatBanner, "IsBanned Temporary String Name", sPerpName, timeleft, sAdminName, sTimeBanned, sReason);
3603 }
3604 else
3605 {
3606 PrintToChat(iClient, g_sChatBanner, "IsBanned Temporary String Name", sPerpName, timeleft, sAdminName, sTimeBanned, sReason);
3607 }
3608 }
3609 }
3610 }
3611}
3612
3613
3614public Action Command_CheckJoin(int iClient, const char[] sCommand, int iArgs)
3615{
3616 // Check to see if we should continue (not a listen server, is in game, not a bot, if cookies are cached, and we're enabled)
3617 if(!iClient || !IsClientInGame(iClient) || IsFakeClient(iClient) || !AreClientCookiesCached(iClient))
3618 {
3619 return Plugin_Continue;
3620 }
3621
3622 // Get the target team
3623 char sJoinTeamString[MAX_JOINTEAM_ARG_LENGTH];
3624 GetCmdArg(JOINTEAM_ARG_TEAM_STRING, sJoinTeamString, sizeof(sJoinTeamString));
3625 int iTargetTeam = StringToInt(sJoinTeamString);
3626
3627 int iBanStatus = GetCTBanStatus(iClient);
3628
3629 // check for an active ban to send a message
3630 if ((iTargetTeam == CS_TEAM_SPECTATOR || iTargetTeam == CS_TEAM_T) && iBanStatus)
3631 {
3632 // display them a message about the ban
3633 int iTimeBanned = GetClientCookieTime(iClient, g_CT_Cookie);
3634 char sTimeBanned[MAX_TIME_INFO_STR_LENGTH];
3635 FormatTime(sTimeBanned, sizeof(sTimeBanned), NULL_STRING, iTimeBanned);
3636 char sJoinBanMsg[MAX_JOIN_BAN_MSG_LENGTH];
3637 GetConVarString(gH_Cvar_JoinBanMessage, sJoinBanMsg, sizeof(sJoinBanMsg));
3638 PrintHintText(iClient, "%t", "Last CT Banned On", sTimeBanned, sJoinBanMsg);
3639
3640 if (GetConVarBool(gH_Cvar_IsBanned_Self))
3641 {
3642 ProcessIsBannedTarget(iClient, iClient);
3643 }
3644 }
3645 // otherwise they joined CT or auto-select and are banned
3646 else if (iBanStatus)
3647 {
3648 if(strcmp(gS_SoundPath, ""))
3649 {
3650 char sPlayCommand[PLATFORM_MAX_PATH + PLAY_COMMAND_STRING_LENGTH];
3651 Format(sPlayCommand, sizeof(sPlayCommand), "%s%s", PLAY_COMMAND_STRING, gS_SoundPath);
3652 ClientCommand(iClient, sPlayCommand);
3653 PrintToChat(iClient, g_sChatBanner, "Enforcing CT Ban");
3654 return Plugin_Stop;
3655 }
3656 EnforceCTBan(iClient);
3657 PrintToChat(iClient, g_sChatBanner, "Enforcing CT Ban");
3658
3659 // if they are already on the Terrorist team then they don't need to pick anything again
3660 if (GetClientTeam(iClient) != CS_TEAM_T)
3661 {
3662 UTIL_TeamMenu(iClient);
3663 }
3664
3665 return Plugin_Stop;
3666 }
3667
3668 return Plugin_Continue;
3669}
3670
3671// This helper procedure will re-display the team join menu
3672// and is equivalent to what ClientCommand(client, "chooseteam") did in the past
3673void UTIL_TeamMenu(int iClient)
3674{
3675 int aiClients[ONE];
3676 Handle hBfWritePack;
3677 aiClients[ZERO] = iClient;
3678 hBfWritePack = StartMessage("VGUIMenu", aiClients, ONE);
3679
3680 if (GetUserMessageType() == UM_Protobuf)
3681 {
3682 PbSetString(hBfWritePack, "name", "team");
3683 PbSetBool(hBfWritePack, "show", true);
3684 }
3685 else
3686 {
3687 BfWriteString(hBfWritePack, "team"); // panel name
3688 BfWriteByte(hBfWritePack, ONE); // bShow
3689 BfWriteByte(hBfWritePack, ZERO); // count
3690 }
3691
3692 EndMessage();
3693}
3694
3695// figure out if we can use the handy native SetAuthIdCookie
3696bool IsSetAuthIdNativePresent()
3697{
3698 if (GetFeatureStatus(FeatureType_Native, "SetAuthIdCookie") == FeatureStatus_Available)
3699 {
3700 return true;
3701 }
3702 return false;
3703}
3704
3705int GetCTBanStatus(int iClient, int iCaller = CALLER_DO_NOT_REPLY)
3706{
3707 int iCTBanStatus = ZERO;
3708
3709 if (AreClientCookiesCached(iClient))
3710 {
3711 char sCookie[MAX_COOKIE_STR_LENGTH];
3712 GetClientCookie(iClient, g_CT_Cookie, sCookie, sizeof(sCookie));
3713 iCTBanStatus = StringToInt(sCookie);
3714 }
3715 else
3716 {
3717 if (iCaller >= ZERO)
3718 {
3719 ReplyToCommand(iCaller, g_sChatBanner, "Cookie Status Unavailable");
3720 }
3721 }
3722
3723 return iCTBanStatus;
3724}
3725
3726void EnforceCTBan(int iClient)
3727{
3728 if (IsPlayerAlive(iClient))
3729 {
3730 // strip their weapons so they cannot gunplant after death
3731 StripAllWeapons(iClient);
3732
3733 ForcePlayerSuicide(iClient);
3734 }
3735
3736 ChangeClientTeam(iClient, CS_TEAM_T);
3737
3738 if (GetConVarBool(gH_Cvar_Respawn))
3739 {
3740 CS_RespawnPlayer(iClient);
3741 }
3742
3743 PrintToChat(iClient, g_sChatBanner, "Enforcing CT Ban");
3744}
3745
3746#if !defined _Hosties_Included_
3747 // From hosties.inc on Beta branch (20 Aug 2017)
3748 stock void StripAllWeapons(int iClient)
3749 {
3750 int iWeaponIndex = INVALID_WEAPON;
3751 for (int iLoopIndex = CS_SLOT_PRIMARY; iLoopIndex < CS_SLOT_GRENADE + ONE; iLoopIndex++)
3752 {
3753 iWeaponIndex = INVALID_WEAPON;
3754 while ((iWeaponIndex = GetPlayerWeaponSlot(iClient, iLoopIndex)) != INVALID_WEAPON)
3755 {
3756 RemovePlayerItem(iClient, iWeaponIndex);
3757 AcceptEntityInput(iWeaponIndex, "Kill");
3758 }
3759 }
3760 GivePlayerItem( client, "weapon_knife" );
3761 }
3762#endif
3763SetCookie(client, Handle:hCookie, n)
3764{
3765 decl String:strCookie[64];
3766
3767 IntToString(n, strCookie, sizeof(strCookie));
3768
3769 SetClientCookie(client, hCookie, strCookie);
3770}
3771#if !defined _CTBan_Included_
3772 stock int IsAuthIdConnected(char[] sAuthID)
3773 {
3774 char sIndexAuthID[FIELD_AUTHID_MAXLENGTH];
3775 for (int iIndex = ONE; iIndex <= MaxClients; iIndex++)
3776 {
3777 if (IsClientInGame(iIndex))
3778 {
3779 GetClientAuthId(iIndex, AuthId_Steam2, sIndexAuthID, sizeof(sIndexAuthID));
3780 if (StrEqual(sAuthID, sIndexAuthID))
3781 {
3782 return iIndex;
3783 }
3784 }
3785 }
3786
3787 return ZERO;
3788 }
3789
3790 stock void ParseCTBanReasonsFile(Handle hReasonsArray)
3791 {
3792 ClearArray(hReasonsArray);
3793
3794 char sPathReasons[PLATFORM_MAX_PATH];
3795 BuildPath(Path_SM, sPathReasons, sizeof(sPathReasons), "configs/ctban_reasons.ini");
3796 Handle hReasonsFile = OpenFile(sPathReasons, "r");
3797
3798 if (hReasonsFile != null)
3799 {
3800 char sReasonsLine[FIELD_REASON_MAXLENGTH];
3801
3802 while (ReadFileLine(hReasonsFile, sReasonsLine, sizeof(sReasonsLine)))
3803 {
3804 PushArrayString(hReasonsArray, sReasonsLine);
3805 }
3806 }
3807
3808 CloseHandle(hReasonsFile);
3809 }
3810
3811 stock Handle ParseCTBanLengthsFile(Handle hKeyValues)
3812 {
3813 if (hKeyValues != INVALID_HANDLE)
3814 {
3815 CloseHandle(hKeyValues);
3816 }
3817
3818 hKeyValues = CreateKeyValues("length");
3819
3820 char sPathLengths[PLATFORM_MAX_PATH];
3821 BuildPath(Path_SM, sPathLengths, sizeof(sPathLengths), "configs/ctban_times.ini");
3822
3823 if (FileToKeyValues(hKeyValues, sPathLengths))
3824 {
3825 KvRewind(hKeyValues);
3826 }
3827 else
3828 {
3829 CloseHandle(hKeyValues);
3830 return INVALID_HANDLE;
3831 }
3832
3833 return hKeyValues;
3834 }
3835
3836 stock void SetCTBanChatBanner(EngineVersion e_EngineVersion, char sChatBanner[MAX_CHAT_BANNER_LENGTH])
3837 {
3838 switch (e_EngineVersion)
3839 {
3840 case Engine_CSS, Engine_TF2:
3841 {
3842 sChatBanner = "[\x0799CCFFCTBAN\x01] \x07FFD700%t";
3843 }
3844 case Engine_CSGO:
3845 {
3846 sChatBanner = "[\x0BCTBAN\x01] \x10%t";
3847 }
3848 default:
3849 {
3850 SetFailState("Game engine is not supported.");
3851 }
3852 }
3853 }
3854#endif