/* Account Commands */

#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <unistd.h>
#include <dirent.h>
#include "channel.h"
#include "include.h"


ACCOUNT_COMMAND(acnt_who)
{	ACCOUNT *wAcnt;
	DESCRIPTOR_DATA *d;
	int count = 0;
	INIT_BUFFER(pAcnt);
	pAcnt->buffer->Add("{DConnected Players{r:{x\n\r");
	pAcnt->buffer->Add("{r[]{W %-15s %s{x\n\r", "Name", "Mud" );
	for(d = descriptor_list ; d; d = d->next )
	{	if(d->connected != CON_OOC_CHAT )
			continue;
		wAcnt = d->account;
		pAcnt->buffer->Add("{r[]{D %-15s %s{r@{D%s{x\n\r",  
			wAcnt->name,
			wAcnt->mud,
			wAcnt->url );
		count++;
	}
	pAcnt->buffer->Add("\n\r{DPlayers Connected{r: [{W%-5d{r]\n\r{x", count );
	return;
}
ACCOUNT_COMMAND(acnt_tell)
{	ACCOUNT *vAcnt;
	char arg[MSL];
	argument = one_argument(argument, arg);
	if(arg[0] == '\0' || argument[0] == '\0')
	{	ptc(pAcnt, "{DSyntax{r: {Wtell {r<{Waccount name{r> <{Wmessage{r>{x\n\r");
		return;
	}

	if( !( vAcnt = get_account(arg) ) )
	{	ptc(pAcnt, "You can't find them anywhere!\n\r");
		return;
	}

	vAcnt->reply = pAcnt;
	ptc(vAcnt, "{D%s tells you{r '{W%s{r'{x\n\r", pAcnt->name, argument);
	ptc(pAcnt, "{DYou tell %s{r '{W%s{r'{x\n\r", vAcnt->name, argument);
	return;
}
ACCOUNT_COMMAND(acnt_reply)
{	if(pAcnt->reply == NULL )
	{	ptc(pAcnt, "You have no one to reply to!\n\r");
		return;
	}
	if(argument[0] == '\0' )
	{	ptc(pAcnt, "Tell them what?\n\r");
		return;
	}

	ACCOUNT *vAcnt = pAcnt->reply;
	ptc(vAcnt, "{D%s tells you {r'{W%s{r'{x\n\r", pAcnt->name, argument);
	ptc(pAcnt, "{DYou tell %s {r'{W%s{r'{x\n\r", vAcnt->name, argument );
	return;
}
ACCOUNT_COMMAND(acnt_chat)
{	if(argument[0] == '\0' )
	{	write_to_buffer(pAcnt->desc, "What would you like to say?\n\r", 0 );
		return;
	}
	acnt_act(pAcnt, NULL, TO_WORLD, "{r[{WChat{r]{D $n says {r'{W%s{r'{x\n\r", argument );
	return;
}

ACCOUNT_COMMAND(acnt_save )
{       acnt_act(pAcnt, NULL, TO_CHAR, "Your Account has been saved.\n\r" );
        save_account(pAcnt);
        return;
}

ACCOUNT_COMMAND(acnt_quit )
{	save_account(pAcnt );
	ACCOUNT *vAcnt;
	for( vAcnt = account_list ; vAcnt; vAcnt = vAcnt->next )
	{	if(vAcnt->reply == pAcnt )
			vAcnt->reply = NULL;
	}
	acnt_act(pAcnt, NULL, TO_CHAR, "Thank you for Chattin'. Come back soon!\n\r" );
	close_socket(pAcnt->desc);
	free_account(pAcnt);
	return;
}

ACCOUNT_COMMAND( acnt_typo )
{	if(argument[0] == '\0' )
	{	write_to_buffer(pAcnt->desc, "What typo would you like to report?\n\r", 0 );
		return;
	}

	acnt_act(pAcnt, NULL, TO_CHAR, "Thank you for your input! Typo logged!\n\r" );
	logfp(LOG_TYPO, "%s: %s", pAcnt->name, argument );
	return;
}

extern int port, control;

ACCOUNT_COMMAND(acnt_copyover)
{	char buf[MSL], buf2[MSL];
	FILE *fpAc;
	DESCRIPTOR_DATA *d;
	ACCOUNT *wch;
	int pid;

	oCopyover = true;
	mysql_close(db);
	logfp(LOG_BUG, "acnt_copyover: Shut down MySQL Connection.");
	write_to_buffer(pAcnt->desc, "Copyover sequence initiated.\n\r", 0);
	/* I'm gunna asume we need to write the copyover file first in this process */
	if( ( fpAc = fopen("./copyover.acnt", "w" ) ) == NULL )
	{	logfp(LOG_BUG, "COPYOVER: Failed on fopen of ./copyover.Acnt");
		oCopyover = false;
		return;
	}		
		
	for(d = descriptor_list; d; d = d->next )
	{	wch = d->account;

		if(strcasecmp(argument, "disregard" ) )
		if(d->connected != CON_OOC_CHAT)
		{	write_to_buffer(pAcnt->desc, "You can't copyover. Not everyone is playing! Check your sockets!\n\r", 0);
			fclose(fpAc);
			oCopyover = false;
			return;
		}
		if(d->connected != CON_OOC_CHAT)
		{   write_to_buffer(d, "Sorry, we're running a Copyover. Be back soon!\n\r",0);
			close(d->descriptor);
			continue;
		}

		if(d->connected == CON_OOC_CHAT )
			fprintf(fpAc, "%d %s %s\n", d->descriptor, wch->name, d->host );
	}
	fprintf(fpAc, "-1\n" );
	fclose(fpAc);
	pid = fork();
	
	if(pid < 0)
	{	write_to_buffer(pAcnt->desc, "Copyover squence failed on fork.\n\r", 0);
		oCopyover = false;
		return;
	}
	if(pid == 0 ) /* Child Process */
	{	sprintf (buf, "%d", port);
		sprintf (buf2, "%d", control);
		execl (EXE_FILE, "tor", buf, "copyover", buf2, (char *) NULL);
		fclose( fopen("copyover.fail", "w" ) );
	}
	return;
}

ACCOUNT_COMMAND(acnt_command )
{	ACNT_CMD *pCmd;
	int col = 0, count = 0;
	for(pCmd = acnt_cmd_list; pCmd ; pCmd = pCmd->next )
	{	if(pCmd->level > pAcnt->level) continue;
		acnt_act(pAcnt, NULL, TO_CHAR, "{r[{D%15s{r] ",pCmd->name );
		if(++col % 4 == 0) write_to_buffer(pAcnt->desc, "\n\r", 0 );
		count++;
	}
	if(col % 4 != 0 ) acnt_act(pAcnt, NULL, TO_CHAR, "\n\r" );
	acnt_act(pAcnt, NULL, TO_CHAR, "\n\r{DCommand Count{r: [{W%d{r]{x\n\r", count );
	return;
}

ACCOUNT_COMMAND(acnt_afk )
{	if(IS_SET(pAcnt->common_flags, COMMON_AFK ) )
	{	write_to_buffer(pAcnt->desc, "You have returned from AFK.\n\r",0);
		UNSET_BIT(pAcnt->common_flags, COMMON_AFK );
		return;
	}

	SET_BIT(pAcnt->common_flags, COMMON_AFK );
	write_to_buffer(pAcnt->desc, "You have gone AFK.\n\r", 0);
	free_string(pAcnt->afk_string);
	if(argument[0] == '\0' )
		pAcnt->afk_string = str_dup("Away From Keyboard" );
	else
		pAcnt->afk_string = str_dup(argument);
	return;
}

ACCOUNT_COMMAND( acnt_advance )
{	int level;
	char arg[MSL], arg2[MSL];
	ACCOUNT *victim;
	char string[MSL];

	argument = one_argument(argument,arg);
	one_argument(argument, arg2);

	if(arg[0] == '\0' || arg2[0] == '\0' )
	{	acnt_act(pAcnt, NULL, TO_CHAR, "Syntax: advance <character> <level>\n\r" );
		return;
	}

	if(!is_number(arg2) )
	{	acnt_act(pAcnt, NULL, TO_CHAR, "What type of level is that?\n\r" );
		return;
	}

	level = atoi(arg2);

	if(level < 0 )
	{	acnt_act(pAcnt, NULL, TO_CHAR, "It must be greater than 0\n\r");
		return;
	}

	if( level > MAX_ACNT_LEVEL )
	{	acnt_act(pAcnt, NULL, TO_CHAR, "It must be less than %d.\n\r", MAX_ACNT_LEVEL );
		return;
	}

	if( ( victim = get_account(arg) ) == NULL )
	{	acnt_act(pAcnt, NULL, TO_CHAR, "You cannot find them.\n\r" );
		return;
	}
	if( victim->level > level )
		sprintf(string, "lowers" );
	else
		sprintf(string, "raises" );

	if(victim->level == level )
	{	write_to_buffer(pAcnt->desc, "They are already that level.\n\r", 0 );
		return;
	}

	acnt_act(pAcnt, victim, TO_CHAR, "You %s %N to level %d.\n\r", string, level );
	victim->level = level;
	acnt_act(pAcnt, victim, TO_VICT, "$n %s you to level %d.\n\r", string, level );
	return;
}

ACCOUNT_COMMAND( acnt_socket )
{	DESCRIPTOR_DATA *d;
	ACCOUNT *ac;

	acnt_act(pAcnt, NULL, TO_CHAR, "{r[{DD#{r] [{D%10s{r] [{D%40s{r]{x\n\r", "Account Name", "Host" );

	for( d = descriptor_list ; d ; d = d->next )
	{	ac = d->account;
		acnt_act(pAcnt, NULL, TO_CHAR, "{r[{W%2d{r] [{W%12s{r] [{W%40s{r]{x\n\r", d->descriptor, ac ? ac->name : "None", d->host);
	}
	return;

}

ACCOUNT_COMMAND( acnt_filecount )
{	struct dirent *Dir;
	DIR *Directory;
    int count = 0;    

	Directory = opendir( "../src/" );
	Dir = readdir( Directory );

	for(; Dir ; Dir = readdir( Directory ), count++ );
	acnt_act( pAcnt, NULL, TO_CHAR, "You have %d files in your src directory.\n\r",  (count - 2 )); // We subtract 2 cause /.. and /. are counted
	return;
}

ACCOUNT_COMMAND( acnt_ignore )
{	Channel *channel;
	std::list<Channel *>::iterator i;
	if(argument[0] == '\0')
	{	for(i = chanList.begin() ; i != chanList.end() ; ++i )
			pAcnt->showIgnore(*i);
	}
	if( !( channel = Channel::find(argument ) ) )
	{	ptc(pAcnt, "That channel doesn't exist\n\r");
		return;
	}
	pAcnt->showIgnore(channel);
	return;
}

extern std::list<Channel *> chanList;
ACCOUNT_COMMAND( acnt_channels )
{	std::list<Channel *>::iterator i;
	for(i = chanList.begin() ; i != chanList.end() ; ++i )
		ptc(pAcnt, "{r%25s{W:%s{x\n\r", (*i)->name, IS_SET(pAcnt->channel, (*i)->bit) ? "{rOn" : "{DOff");
	return;
}

ACCOUNT_COMMAND( acnt_ban )
{	ACCOUNT *vict;
	
	if(!(vict = get_account(argument) ) )
	{	ptc(pAcnt, "You can't find them anywhere!\n\r");
		return;
	}
	if(IS_SET(vict->common_flags, COMMON_BANNED) )
	{	ptc(pAcnt, "You remove %s's ban.\n\r", vict->name);
		UNSET_BIT(vict->common_flags, COMMON_BANNED);
		return;
	}
	SET_BIT(vict->common_flags, COMMON_BANNED);
	ptc(pAcnt, "You have banned %s.\n\r",vict->name);
	return;
}

ACCOUNT_COMMAND( acnt_view )
{	CodeBlob *blob;
	int id, start=0, finish=0;
	char arg[MSL], arg2[MSL], arg3[MSL];
	argument = one_argument(argument, arg);
	argument = one_argument(argument, arg2);
	argument = one_argument(argument, arg3);
	
	if(arg[0] == '\0')
	{	ptc(pAcnt, "{DSyntax{r: {Wview {r<{Wcode ID{r> [<{Wstart line{r>] [<{Wend line{r>]{D\n\r");
		ptc(pAcnt, "        {Wview list{x\n\r");
		ptc(pAcnt, "\n\r{DThis command allows you to view code inserted into the paste bin\n\rlocated at {rhttp://{Wmudcon.thehighc.com/bin/\n\r{x");
		return;
	}
	if(!strcasecmp(arg, "list" ) )
	{	MYSQL_RES *res;
		MYSQL_ROW row;
		char query[MSL];
		int size;
		sprintf(query, "SELECT * FROM `Bin`");
		if( mysql_real_query( db, query, strlen(query) ) )
		{	logfp(LOG_BUG, "acnt_view:list: %s", mysql_error(db) );
			return;
		}
		if( !( res = mysql_store_result(db) ) || (size = mysql_num_rows(res) ) <= 0 )
		{	ptc(pAcnt, "I'm sorry, our paste bin is empty!\n\r");
			return;
		}
		INIT_BUFFER(pAcnt);
		for( int i = 0; i < size ; ++i )
		{	row = mysql_fetch_row(res);
			pAcnt->buffer->Add("{W%s{r[{W%s{r][{W%s{r] {D%s {Wby {D%s{x\n\r", row[5], row[0], row[1], row[2], row[3]);
		}
		mysql_free_result(res);
		return;
	}
	if( arg2[0] != '\0' )
	{	if(!is_number(arg2) )
		{	ptc(pAcnt, "{DThe line from which you start must be a number!\n\r");
			return;
		}
		if(arg3[0] != '\0' )
		{	if(!is_number(arg3) )
			{	ptc(pAcnt, "{DThe line from which you finish must be a number!\n\r");
				return;
			}
			finish = atoi(arg3);
		}
		start = atoi(arg2)-1;
		if(finish && start > finish)
		{	ptc(pAcnt, "I don't think so.\n\r");
			return;
		}
	}
	
	if(!is_number(arg) )
	{	ptc(pAcnt, "The ID must be a number.\n\r");
		return;
	}
	id = atoi(arg);
	if( !( blob = CodeBlob::find(id) ) )
	{	MYSQL_ROW row;
		MYSQL_RES *res;
		
		char query[MSL];
		sprintf(query, "SELECT * FROM `Bin` WHERE id=%d", id);
		if( mysql_real_query(db, query, strlen(query)) )
		{	logfp(LOG_BUG, "acnt_view: %s", mysql_error(db) );
			return;
		}
		if( !(res = mysql_store_result(db) ) || mysql_num_rows(res) <= 0 )
		{	ptc(pAcnt, "That Code Blob was not found! Sorry!\n\r");
			return;
		}
		row = mysql_fetch_row(res);
		logfp(LOG_BUG, "acnt_view: Blob size %d", strlen(row[4]) );
		blob = new CodeBlob(row);
		mysql_free_result(res);
	}
	
	pAcnt->buffer = blob->buffer;
	if(finish > (int)pAcnt->buffer->lines.size())
		finish = (int)pAcnt->buffer->lines.size();
	if(finish && start > finish)
		start = finish ? finish : start;
	pAcnt->bufEnd = finish ? finish : pAcnt->buffer->lines.size();
	pAcnt->bufPos = start;
	ptc(pAcnt, "{r[{WPress Enter to Continue{r]---[{W%d{r/{D%d{r]{x\n\r", start+1, finish ? finish : pAcnt->buffer->lines.size() );
	return;
}
#define SET_POST 0
#define SET_REPLY 1
#define SET_TOPIC 2

#define PREVENT_CODE(code, string) \
if(strstr(string, code) ) \
{	ptc(pAcnt, "{DSorry, you can't use the {r'{W%s{r'{D code here.\n\r", code); \
	invalid = true; \
}

ACCOUNT_COMMAND( acnt_customize )
{	char arg[MSL];
	int set = 0;
	bool invalid = false;
	argument = one_argument(argument, arg);
	
	if(arg[0] == '\0')
	{	ptc(pAcnt, "{DSyntax{r: {Wcustomize post {r<{Wstring{r>\n\r");
		ptc(pAcnt, "        {Wcustomize reply {r<{Wstring{r>\n\r");
		ptc(pAcnt, "        {Wcustomize topic {r<{Wstring{r>{x\n\r\n\r");
		ptc(pAcnt, "{DWe understand that tonight will be one intense night! So we\n\r");
		ptc(pAcnt, "feel no one should be stuck with an output that they don't like!\n\r");
		ptc(pAcnt, "It'd just ruin the night for you. We want to make this as painless\n\r");
		ptc(pAcnt, "as possible. So for that we offer this! This will allow you to\n\r");
		ptc(pAcnt, "customize the way the channels look for you.\n\r\n\r");
		ptc(pAcnt, "The {r'{Wpost{r'{D argument allows you to set how a post on the channels\n\r");
		ptc(pAcnt, "looks when there is no one to reply too. So it will usually be the\n\r");
		ptc(pAcnt, "first post in the topic!\n\r\n\r");
		ptc(pAcnt, "The {r'{Wreply{r'{D argument customizes the output when there is a reply.\n\r\n\r");
		ptc(pAcnt, "And finally the {r'{Wtopic{r'{D argument allows you to customize the\n\r");
		ptc(pAcnt, "string sent to you when a new topic is posted.\n\r\n\r");
		ptc(pAcnt, "Type one of these three with no argument, to see the codes.\n\r");
		ptc(pAcnt, "Use these commands with the {r'{W!restore{r'{D argument to restore defaults.\n\r");
		return;
	}

	if(LOWER(arg[0]) == 'r' && !str_prefix(arg, "reply") )
		set = SET_REPLY;
	else if( LOWER(arg[0]) == 't' && !str_prefix(arg, "topic") )
		set = SET_TOPIC;
	else if( LOWER(arg[0]) == 'p' && !str_prefix(arg, "post") )
		set = SET_POST;
	else
	{	ptc(pAcnt, "Sorry! You have to use either {r'{Wpost{r'{D, {r'{Wreply{r'{D, or {r'{Wtopic{r'{D.\n\r");
		return;
	}
	
	if(argument[0] == '\0')
	{	ptc(pAcnt, "{DThese are the codes used for customizing your output! If you've used\n\r");
		ptc(pAcnt, "a diku codebase with a customizable prompt, this should be kinda familure\n\r");
		ptc(pAcnt, "to you... I hope! Anyways, here they are.\n\r\n\r");
		ptc(pAcnt, "\t{W%%t {r- {DTopic ID Number\n\r");
		ptc(pAcnt, "\t{W%%T {r- {DTopic Subject\n\r");
		ptc(pAcnt, "\t{W%%a {r- {DAuthor of Topic\n\r");
		ptc(pAcnt, "\t{W%%A {r- {DAuthor of Post\n\r");
		ptc(pAcnt, "\t{W%%p {r- {DPost ID Number\n\r");
		ptc(pAcnt, "\t{W%%r {r- {DPost ID Number for post being replied to\n\r");
		ptc(pAcnt, "\t{W%%R {r- {DName of author of post being replied to\n\r\n\r");
		ptc(pAcnt, "{DObviously some of these aren't valid in all fields (You cant use %%r\n\r");
		ptc(pAcnt, "{Dor %%R in noreply or topic for instance.)\n\r");
		ptc(pAcnt, "{WNote{r:{D For {r'{Wpost{r'{D and {r'{Wreply{r'{D a space will always seperate your string\n\r");
		ptc(pAcnt, "{Dand the message of the post. To set the colour of the post message, leave\n\r");
		ptc(pAcnt, "{Dstrap the wanted colour code at the very end.\n\r\n\r");
		if(set == SET_REPLY)
			ptc(pAcnt, "{DYour current {r'{Wreply{r'{D string is{r:{D %s", pAcnt->custReply);
		else if( set == SET_POST )
			ptc(pAcnt, "{DYour current {r'{Wpost{r'{D string is{r:{D %s", pAcnt->custPost);
		else
			ptc(pAcnt, "{DYour current {r'{Wtopic{r'{D string is{r:{D %s", pAcnt->custTopic);
		return;
	}
	if(*argument == '!')
	{	++argument;
		if(!strcasecmp(argument, "restore") )
		{	if( set == SET_REPLY )
			{	free_string(pAcnt->custReply);
				pAcnt->custReply = str_dup(CUSTREPLY);
			}
			else if ( set == SET_POST )
			{	free_string(pAcnt->custPost);
				pAcnt->custReply = str_dup(CUSTPOST);
			}
			else
			{	free_string(pAcnt->custTopic);
				pAcnt->custTopic = str_dup(CUSTTOPIC);
			}
			ptc(pAcnt, "Default restored.\n\r");
			return;
		}
		ptc(pAcnt, "{DCustomize function not found. Try{r: {Wrestore{D\n\r");
		return;
	}
	if(!strstr(argument, "%") )
	{	ptc(pAcnt, "You have to use -some- codes!\n\r");
		return;
	}

	if(set == SET_POST)
	{	PREVENT_CODE("%r", argument);
		PREVENT_CODE("%R", argument);
		if(invalid)
		{	ptc(pAcnt, "Sorry, string contains invalid codes. Rejected.\n\r");
			return;
		}
		free_string(pAcnt->custPost);
		pAcnt->custPost = str_dup(argument);
		ptc(pAcnt, "{DPost string set to{r:{D %s", pAcnt->custPost);
	}
	else if( set == SET_REPLY)
	{	free_string(pAcnt->custReply);
		pAcnt->custReply = str_dup(argument);
		ptc(pAcnt, "{DReply string set to{r:{D %s", pAcnt->custReply);
	}
	else if( set == SET_TOPIC)
	{	PREVENT_CODE("%r", argument);
		PREVENT_CODE("%R", argument);
		PREVENT_CODE("%A", argument);
		PREVENT_CODE("%p", argument);
		if(invalid)
		{	ptc(pAcnt, "Sorry, string contains invalid codes. Rejected.\n\r");
			return;
		}
		free_string(pAcnt->custTopic);
		pAcnt->custTopic = str_dup(argument);
		ptc(pAcnt, "{DPost string set to{r:{D %s", pAcnt->custTopic);
	}
	return;
}

ACCOUNT_COMMAND( acnt_help )
{	if(argument[0] == '\0')
	{	ptc(pAcnt,"{r____\n\r");
		ptc(pAcnt,"{WHelp{r\\_________\n\r");
		ptc(pAcnt,"     {r|{WChannels{r\\_____________________\n\r");
		ptc(pAcnt,"     {r|{DChannels are a huge slice of MUD-Con as it is meant for discussion.\n\r");
		ptc(pAcnt,"     {r|{DWe recommend you become as familiar with this system as quick as possible.\n\r");
		ptc(pAcnt,"     {r|{DYou can use the 'chat' channel to ask questions without having to follow\n\r");
		ptc(pAcnt,"{r____ {r|{Dthe syntax of the living-forum channel system. I'm sure you'll catch on quickly.\n\r");
		ptc(pAcnt,"    {r\\______________\n\r");
		ptc(pAcnt,"     {r|{WCustomization{r\\_________________\n\r");
		ptc(pAcnt,"     {r|{DWe are attempting to make this event as painless as possible. Judging by how\n\r");
		ptc(pAcnt,"     {r|{Ddifferent everyones MU* background is, we're allowing you to customize the\n\r");
		ptc(pAcnt,"     {r|{Doutput of the channels! It's a simple diku-style prompt code that allows for\n\r");
		ptc(pAcnt,"{r____ {r|{Dcomplete customization that can totally change the look and feel of the Con.\n\r");
		ptc(pAcnt,"    {r\\_____\n\r");
		ptc(pAcnt,"     {r|{WView{r\\__________________________\n\r");
		ptc(pAcnt,"     {r|{DIn light of the event, we hope to account for all interfaces going through\n\r");
		ptc(pAcnt,"     {r|{Dthe MUD and staying consistent (so you don't have to link hunt should you read\n\r");
		ptc(pAcnt,"     {r|{Dthe logs after the event.) We now provide a paste-bin like interface from the\n\r");
		ptc(pAcnt,"     {r|{Dwebsite - http://mudcon.thehighc.com/bin/ - This allows you to\n\r");
		ptc(pAcnt,"     {r|{Dpost code to the web, and have it viewable in game, or from the web.\n\r");
		ptc(pAcnt,"     {r|{DYou can use this for more than just code. Stories to share, logs,\n\r");
		ptc(pAcnt,"     {r|{Dstories, area descriptions, what ever blob of text you want out there!\n\r");
		ptc(pAcnt,"{r_____|_______________________________{D\n\r");
		ptc(pAcnt,"Typing any of these commands, (channels, customize, and view) provides\n\r");
		ptc(pAcnt,"Syntax and basic help, along with ways to get more help. The only helpfile is\n\r");
		ptc(pAcnt,"is 'credits' for license purposes. Any more questions ask on the Chat channel!\n\r");
	}
	else
	if(!strncasecmp(argument, "credits", strlen(argument)))
		acnt_credits(pAcnt, argument);

	return;
}

ACCOUNT_COMMAND(acnt_credits )
{
	ptc(pAcnt, "           Original game idea, concept, and design:\n\r");
	ptc(pAcnt, "Katja Nyboe               [Superwoman] (katz@freja.diku.dk)\n\r");
	ptc(pAcnt, "Tom Madsen              [Stormbringer] (noop@freja.diku.dk)\n\r");
	ptc(pAcnt, "Hans Henrik Staerfeldt           [God] (bombman@freja.diku.dk)\n\r");
	ptc(pAcnt, "Michael Seifert                 [Papi] (seifert@freja.diku.dk)\n\r");
	ptc(pAcnt, "Sebastian Hammer               [Quinn] (quinn@freja.diku.dk)\n\r");
	ptc(pAcnt, "Developed at: DIKU -- The Department of Computer Science\n\r");
	ptc(pAcnt, "          at the University of Copenhagen.\n\r");
}
void ACCOUNT::addIgnore(Topic *topic, int channl)
{	if(isIgnoring(topic, channl) )
		return;
	ignore[channl].push_back(topic);
}

void ACCOUNT::remIgnore(Topic *topic, int channl )
{	std::list<Topic *>::iterator i;
	for( i = ignore[channl].begin() ; i != ignore[channl].end() ; ++i )
		if(topic == (*i) )
		{	ignore[channl].erase(i);
			break;
		}

}

bool ACCOUNT::isIgnoring(Topic *topic, int channl )
{	std::list<Topic *>::iterator i;
	for( i = ignore[channl].begin() ; i != ignore[channl].end() ; ++i )
		if( topic == (*i) )
			return true;
	return false;
}

bool ACCOUNT::canSend(Topic *topic, Channel * channl)
{	if(isIgnoring(topic, channl->bit) )
		return false;
	if(!IS_SET(channel, channl->bit) )
		return false;
	return true;
}

void ACCOUNT::page()
{	if(buffer == NULL)
		return;
	buffer->Send(this);
	if( !buffer->isBlob && buffer->pos >= (int)buffer->lines.size() )
	{	buffer->Empty();
		delete buffer;
		buffer = NULL;
	}
	else
	if(buffer->isBlob && bufEnd != 0)
	{	if(bufPos >= bufEnd)
		{	bufPos = -1;
			bufEnd = 0;
			buffer = NULL;
		}
		
	}
}

void ACCOUNT::showIgnore(Channel *channl )
{	std::list<Topic *>::iterator i;
	if(ignore[channl->bit].size() == 0 )
	{	ptc(this, "You aren't ignoring any topics on %s.\n\r",channl->name);
		return;
	}
	INIT_BUFFER(this);
	buffer->Add("These are the topics your ignoring on %s\n\r", channl->name );
	for( i = ignore[channl->bit].begin() ; i != ignore[channl->bit].end() ; ++i )
		buffer->Add("\t{r[{W%d{r]{W%s{r:{D%s{x\n\r", (*i)->id, (*i)->name, (*i)->subject );
	return;
}

void ACCOUNT::showLocked(Channel *channel)
{	std::list<Topic *>::iterator i;
	bool found = false;
	INIT_BUFFER(this);
	buffer->Add("These are the locked topics on %s.\n\r", channel->name);
	for( i =  channel->topics.begin() ; i != channel->topics.end() ; ++i)
	{	if( (*i)->locked )
		{	found = true;
			buffer->Add("\t{r[{W%d{r]{W%s{r:{D%s{x\n\r", (*i)->id, (*i)->name, (*i)->subject);
		}
	}

	if(!found)
		buffer->Add("\t{WThere are no locked topics on this channel\n\r");
	return;
}

char * ACCOUNT::genChanPrefix(Post *post, Topic *topic)
{	Post *parent = NULL;
	char *str, *ptr = 0,*ptr2 = 0, add[MSL];
	static char buf[MSL];
	if(post)
		parent = post->on->getPost(post->parentID);
	buf[0] = '\0';
	ptr = buf;
	if(parent)
	{	str = custReply;
		topic = post->on;
	}
	else if (topic)
		str = custTopic;
	else
	{	str = custPost;
		topic = post->on;
	}

	while(*str != '\0')
	{	if(*str == '%')
		{	++str;
			switch(*str)
			{	case 'a':
					if(!topic)
					{	logfp(LOG_BUG,"ACCOUNT::genChanPrefix: Null Topic!");
						sprintf(add, "None");
					}
					else
						sprintf(add, topic->name);
					break;
				case 'A':
					sprintf(add, post->poster);
					break;
				case 'p':
					sprintf(add, "%d", post->id);
					break;
				case 'r':
					sprintf(add, "%d", parent->id);
					break;
				case 'R':
					sprintf(add, parent->poster);
					break;
				case 't':
					if(!topic)
					{	logfp(LOG_BUG,"ACCOUNT::genChanPrefix: Null Topic!");
						sprintf(add, "None");
					}
					else
						sprintf(add, "%d", topic->id);
					break;
				case 'T':
					if(!topic)
					{	logfp(LOG_BUG,"ACCOUNT::genChanPrefix: Null Topic!");
						sprintf(add, "None");
					}
					else
						sprintf(add, topic->subject);
					break;
				default:
					sprintf(add, "%%%c", *str);
			}
			ptr2 = add;
			while(	*ptr2 != '\0' )
			{	*ptr = *ptr2;
				++ptr; ++ptr2;
			}
			*str++;
			continue;
		}
		*ptr = *str;
		++ptr; ++str;
	}
	*ptr = '\0';
	return buf;
}