/***************************************************************************
 * plugin_sank_nameban.sma
 * Author: Luke Sankey
 * November 25, 2001 - Original version
 * February 15, 2002 - Added some debug code because of incorrect bans and
 *  the option for exact names to ban, or just partial names to ban
 * November 15, 2002 - Updated file locations to be compliant with the new
 *  directory structure.  Also, updated the debug code with contact
 *  information.
 *
 * Fuctionality of this plugin:
 * Bans players based on their name. If a player connects with a name that
 * contains one of the entries listed in the text file, then they will get
 * banned.  If a player changes their name to one of the offending names,
 * they will also get banned.
 *
 * Credit is due to Vince Hague for inspiring me to write this plugin
 ***************************************************************************/
 
 
#include <core>
#include <console>
#include <string>
#include <admin>
#include <adminlib>
 
// This is the name of the file to log name-ban events to
new LOG_FILE[MAX_DATA_LENGTH] = "addons\adminmod\config\NameBanLog.txt";
// This is the name of the file to read the forbidden names from
new TAG_FILE[MAX_DATA_LENGTH] = "addons\adminmod\config\NameBanList.txt";
// This is the maximum number of entries allowed in the name ban file
#define MAX_ENTRIES 20
// Defining this value will make the plugin ban players with exact name matches
//#define EXACTNAME
 
/****************************************************************************/
/****************************************************************************/
/************** DO NOT MODIFY CONTENTS BELOW THIS LINE !!! ******************/
/************** DO NOT MODIFY CONTENTS BELOW THIS LINE !!! ******************/
/************** DO NOT MODIFY CONTENTS BELOW THIS LINE !!! ******************/
/****************************************************************************/
/****************************************************************************/
 
new STRING_VERSION[MAX_DATA_LENGTH] = "2.50.50";
#define INFINITE_TIMER 99999
 
// Holds the banned entries from the text file
new BannedNames[MAX_ENTRIES][MAX_NAME_LENGTH];
 
// Make sure the timer matches the person
new TimerLookup[MAX_PLAYERS];
 
/****************************************************************************/
 
public plugin_connect(HLUserName, HLIP, UserIndex) 
{
	new PlayerName[MAX_NAME_LENGTH];
 
	convert_string(HLUserName, PlayerName, MAX_NAME_LENGTH);
 
	CheckName(PlayerName, UserIndex);
 
	return PLUGIN_CONTINUE;
}
 
/****************************************************************************/
 
public plugin_info(HLOldName, HLNewName, UserIndex)
{
	new NewName[MAX_NAME_LENGTH];
	new OldName[MAX_NAME_LENGTH];
 
	convert_string(HLNewName, NewName, MAX_NAME_LENGTH);
	convert_string(HLOldName, OldName, MAX_NAME_LENGTH);
 
	// If name has not changed
	if (strcmp(NewName, OldName) == 0)
		return PLUGIN_CONTINUE;
 
	// Or if there was no previous name
	else if (strlen(OldName) == 0)
		return PLUGIN_CONTINUE;
 
	CheckName(NewName, UserIndex);
 
	return PLUGIN_CONTINUE;
}
 
/****************************************************************************/
 
public plugin_init() 
{
	plugin_registerinfo("Sank NameBan Plugin", "Bans users by name", STRING_VERSION);
	plugin_registercmd("admin_nameban", "admin_nameban", ACCESS_ALL, "admin_nameban : Prints out list of names that get banned.");
 
	parse_file();
 
	return PLUGIN_CONTINUE;
}
 
/****************************************************************************/
 
public admin_nameban(HLCommand, HLData, HLUserName, UserIndex)
{
	new i;
 
	selfmessage("NameBan entries:");
	for (i = 0; i < MAX_ENTRIES; i++)
	{
		if (BannedNames[i][0] == 0)
			break;
		selfmessage(BannedNames[i]);
	}
 
	return PLUGIN_HANDLED;
}
 
/****************************************************************************/
 
public ban_timer(Timer, Repeat, HLUserName, HLParam)
{
	new PlayerName[MAX_NAME_LENGTH];
//	new ServerName[MAX_TEXT_LENGTH];
	new Text[MAX_TEXT_LENGTH];
	new Date[MAX_NUMBER_LENGTH];
	new WONID;
 
	convert_string(HLUserName, PlayerName, MAX_NAME_LENGTH);
 
	// PlayerName will exist once the player has truly connected.
	// Until then, we will keep looping.
	if (strlen(PlayerName))
	{
		new Index;
		get_userindex(PlayerName, Index);
		servertime(Date, MAX_NUMBER_LENGTH, "%m/%d/%y %H:%M:%S");
 
		// First make sure the Timer and UserIndex match
		// Then, if the player is not immune, ban them.
		if (TimerLookup[Index] == Timer)
		{
			if (check_immunity(PlayerName) == 0)
			{
				ban(PlayerName, 0);
 
				// Let the players know
//				getstrvar("hostname", ServerName, MAX_TEXT_LENGTH);
//				snprintf(Text, MAX_TEXT_LENGTH, "<%s>: %s has been permanently banned from the server.", ServerName, PlayerName);
//				say(Text);
 
				// Let the admin know
				get_userWONID(PlayerName, WONID);
				snprintf(Text, MAX_TEXT_LENGTH, "L %s - %s<%i>", Date, PlayerName, WONID);
				writefile(LOG_FILE, Text);
				log(Text);
			}
		}
		else
		{
			// This is all debugging stuff for adminmod.  I've never seen it, but I"ve heard
			// cases where this plugin would ban the wrong player.  The only way this could
			// happen is if the timer callback function sent me the wrong name.  So, in this
			// rare case, we will log special error messages.
 
			// The first special error message is that we almost banned the wrong person
			snprintf(Text, MAX_TEXT_LENGTH, "L %s - UserName and UserIndex did not match. %s:%i", Date, PlayerName, Index);
			writefile(LOG_FILE, Text);
			log(Text);
 
			// Get UserIndex of who we should've banned
			for (Index = 1; Index <= MAX_PLAYERS; Index++)
			{
				if (TimerLookup[Index] == Timer)
					break;
			}
			// Get name of who we should've banned
			numtostr(Index, Text);
			get_username(Text, PlayerName, MAX_NAME_LENGTH);
			snprintf(Text, MAX_TEXT_LENGTH, "L %s - I think we really wanted this banned. %s:%i", Date, PlayerName, Index);
			writefile(LOG_FILE, Text);
			log(Text);
			snprintf(Text, MAX_TEXT_LENGTH, "If you see this line, please please email me: sank@spu.edu Subject: Admin Mod nameban bug");
			writefile(LOG_FILE, Text);
			log(Text);
		}
 
		// Stop this infinite timer
		kill_timer(Timer);
 
		return PLUGIN_CONTINUE;
	}
 
	return PLUGIN_CONTINUE;
}
 
/****************************************************************************/
 
CheckName(PlayerName[], UserIndex)
{
	new Text[MAX_TEXT_LENGTH];
	new i;
	new status = -1;
	for (i = 0; i < MAX_ENTRIES; i++)
	{
#if defined EXACTNAME
		status = strcasecmp(PlayerName, BannedNames[i]);
		if (status == 0)
#else
		status = strcasestrx(PlayerName, BannedNames[i]);
		if (status != -1)
#endif
		{
			snprintf(Text, MAX_TEXT_LENGTH, "Setting timer to ban %s containing %s", PlayerName, BannedNames[i]);
			log(Text);
			TimerLookup[UserIndex] = set_timer("ban_timer", 3, INFINITE_TIMER);
			break;
		}
	}
}
 
/****************************************************************************/
 
parse_file()
{
	new i;
	new GotLine;
	new iLineNum = 0;
	new strLineBuf[MAX_TEXT_LENGTH];
 
	// Clear memory before using it
	for(i = 0; i < MAX_ENTRIES; i++)
		BannedNames[i][0] = 0;
 
	// File does not exist, try MOD directory (for backwards compatibility)
	if (!fileexists(TAG_FILE))
	{
		strcpy(TAG_FILE, "NameBanList.txt", MAX_DATA_LENGTH);
		strcpy(LOG_FILE, "NameBanLog.txt", MAX_DATA_LENGTH);
	}
 
	i = 0;
	if (fileexists(TAG_FILE))
	{
		GotLine = readfile(TAG_FILE, strLineBuf, iLineNum, MAX_TEXT_LENGTH);
 
		if (GotLine <= 0)
		{
			// See if file access is set correctly
			if (getvar("file_access_read") == 1)
				snprintf(strLineBuf, MAX_TEXT_LENGTH, "[plugin_sank_nameban] Unable to read from %s file.", TAG_FILE);
			else
				snprintf(strLineBuf, MAX_TEXT_LENGTH, "[plugin_sank_nameban] CVAR file_access_read is set incorrectly.");
 
			log(strLineBuf);
			return;
		}
 
		while (GotLine > 0)
		{
			// If there is no more room in our banned name list, then stop reading the file
			if (i >= MAX_ENTRIES)
			{
				log("[plugin_sank_nameban] Name list truncated. Increase MAX_ENTRIES.");
				printf("[plugin_sank_nameban] Stopped parsing %s file.^n", TAG_FILE);
				break;
			}
 
			// As long as the line isn't commented out, and isn't blank, then remember it.
			if ((strncmp(strLineBuf, "#", 1) != 0) && (strncmp(strLineBuf, "//", 2) != 0) && (strlen(strLineBuf) != 0))
			{
				strcpy(BannedNames[i], strLineBuf, MAX_TEXT_LENGTH);
				i++;
			}
			// Read in the next line from the file
			GotLine = readfile(TAG_FILE, strLineBuf, ++iLineNum, MAX_TEXT_LENGTH);
		}
	}
}