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