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