Beispiel #1
0
string CIncomingGameHost :: GetIPString( )
{
	string Result;

	if( m_IP.size( ) >= 4 )
	{
		for( unsigned int i = 0; i < 4; i++ )
		{
			Result += UTIL_ToString( (unsigned int)m_IP[i] );

			if( i < 3 )
				Result += ".";
		}
	}

	return Result;
}
Beispiel #2
0
bool CUDPSocket :: Broadcast( uint16_t port, BYTEARRAY message )
{
	if( m_Socket == INVALID_SOCKET || m_HasError )
		return false;

	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = m_BroadcastTarget.s_addr;
	sin.sin_port = htons( port );

	string MessageString = string( message.begin( ), message.end( ) );

	if( sendto( m_Socket, MessageString.c_str( ), MessageString.size( ), 0, (struct sockaddr *)&sin, sizeof( sin ) ) == -1 )
	{
		CONSOLE_Print( "[UDPSOCKET] failed to broadcast packet (port " + UTIL_ToString( port ) + ", size " + UTIL_ToString( MessageString.size( ) ) + " bytes)" );
		return false;
	}

	return true;
}
CLanguage :: CLanguage( string nCFGFile )
{
	m_CFG = new CConfig( );
	m_CFG->Read( nCFGFile );
	
	ifstream in;
	in.open( "jokes.txt" );

	if( in.fail( ) )
		CONSOLE_Print( "[JOKES] error loading jokes from [jokes.txt]" );
	else
	{
		CONSOLE_Print( "[JOKES] loading jokes from [jokes.txt]" );
		m_Jokes.clear();
		
		string Line;

		while( !in.eof( ) )
		{
			getline( in, Line );

			// ignore blank lines and comments

			if( Line.empty( ) || Line[0] == '#' )
				continue;

			// remove newlines and partial newlines to help fix issues with Windows formatted files on Linux systems

			//Line.erase( remove( Line.begin( ), Line.end( ), ' ' ), Line.end( ) );
			Line.erase( remove( Line.begin( ), Line.end( ), '\r' ), Line.end( ) );
			Line.erase( remove( Line.begin( ), Line.end( ), '\n' ), Line.end( ) );

			m_Jokes.push_back( Line );
		}

		in.close( );

		CONSOLE_Print( "[JOKES] loaded " + UTIL_ToString( m_Jokes.size( ) ) + " jokes." );
	}
}
Beispiel #4
0
CCCBot :: CCCBot( CConfig *CFG ) : m_Exiting( false), m_Version( "1.04" )
{
	CONSOLE_Print( "[CCBOT] Channel && Clan Bot - " + m_Version + ", based on GHost++" );
			
	m_DB = new CCCBotDB( CFG );
	m_Language = new CLanguage( LanguageFile );
	m_Warcraft3Path = CFG->GetString( "bot_war3path", "C:\\Program Files\\Warcraft III\\" );

	// load the battle.net connections
	// we're just loading the config data and creating the CBNET classes here, the connections are established later (in the Update function)

	if( CFG->GetGenerated( ) )
	{
		CONSOLE_Print( "[CONFIG] EDIT ccbot.cfg IN THE cfg FOLDER AND RESTART CCBOT!" );
		CONSOLE_Print( "[CONFIG] EDIT ccbot.cfg IN THE cfg FOLDER AND RESTART CCBOT!" );
		CONSOLE_Print( "[CONFIG] EDIT ccbot.cfg IN THE cfg FOLDER AND RESTART CCBOT!" );
		CONSOLE_Print( "[CONFIG] EDIT ccbot.cfg IN THE cfg FOLDER AND RESTART CCBOT!" );
		
		return;
	}
		
	for( unsigned int i = 1; i < 10; ++i )
	{
		string Prefix;

		if( i == 1 )
			Prefix = "bnet_";
		else
			Prefix = "bnet" + UTIL_ToString( i ) + "_";

		string Server = CFG->GetString( Prefix + "server", string( ) );
		transform( Server.begin( ), Server.end( ), Server.begin( ), (int(*)(int))tolower );
		string CDKeyROC = CFG->GetString( Prefix + "cdkeyroc", string( ) );
		string CDKeyTFT = CFG->GetString( Prefix + "cdkeytft", string( ) );
		string CountryAbbrev = CFG->GetString( Prefix + "countryabbrev", "FIN" );
		string Country = CFG->GetString( Prefix + "country", "Finland" );
		string UserName = CFG->GetString( Prefix + "username", string( ) );
		string UserPassword = CFG->GetString( Prefix + "password", string( ) );
		string FirstChannel = CFG->GetString( Prefix + "firstchannel", "The Void" );
		string RootAdmin = CFG->GetString( Prefix + "rootadmin", string( ) );
		string BNETCommandTrigger = CFG->GetString( Prefix + "commandtrigger", "!" );

		string ClanTag = CFG->GetString( Prefix + "clantag", "" );
		string HostbotName = CFG->GetString( Prefix + "hostbotname", "" );
		bool AntiSpam = CFG->GetInt( Prefix + "antispam", 0 ) == 0 ? false : true;
		bool GreetUsers = CFG->GetInt( Prefix + "greetusers", 0 ) == 0 ? false : true;
		bool SwearingKick = CFG->GetInt( Prefix + "swearingkick", 0 ) == 0 ? false : true;
		bool AnnounceGames = CFG->GetInt( Prefix + "announcegames", 0 ) == 0 ? false : true;
		bool SelfJoin = CFG->GetInt( Prefix + "selfjoin", 0 ) == 0 ? false : true;
		bool BanChat = CFG->GetInt( Prefix + "banchat", 0 ) == 0 ? false : true;		
		unsigned char ClanDefaultAccess = CFG->GetInt( Prefix + "clanmembersdefaultaccess", 4 );

		if( ClanDefaultAccess > 9 )
			ClanDefaultAccess = 9;

		unsigned char War3Version = CFG->GetInt( Prefix + "custom_war3version", 24 );
		BYTEARRAY EXEVersion = UTIL_ExtractNumbers( CFG->GetString( Prefix + "custom_exeversion", string( ) ), 4 );
		BYTEARRAY EXEVersionHash = UTIL_ExtractNumbers( CFG->GetString( Prefix + "custom_exeversionhash", string( ) ), 4 );
		string PasswordHashType = CFG->GetString( Prefix + "custom_passwordhashtype", string( ) );
		unsigned char MaxMessageLength = CFG->GetInt( Prefix + "custom_maxmessagelength", 200 );

		if( Server.empty( ) )
			break;

		CONSOLE_Print( "[CCBOT] found battle.net connection #" + UTIL_ToString( i ) + " for server [" + Server + "]" );
		m_BNETs.push_back( new CBNET( this, Server, CDKeyROC, CDKeyTFT, CountryAbbrev, Country, UserName, UserPassword, FirstChannel, RootAdmin, BNETCommandTrigger[0], War3Version, EXEVersion, EXEVersionHash, PasswordHashType, MaxMessageLength, ClanTag, GreetUsers, SwearingKick, AnnounceGames, SelfJoin, BanChat, ClanDefaultAccess, HostbotName, AntiSpam ) );
	}

	if( m_BNETs.empty( ) )
		CONSOLE_Print( "[CCBOT] warning - no battle.net connections found in config file" );	

	// Update the swears.cfg file
	UpdateSwearList( );
	
	// Check for the default access system values
	UpdateCommandAccess( );

	m_Uptime = GetTime( );
}
Beispiel #5
0
void CReplay :: ParseReplay( bool parseBlocks )
{
	m_HostPID = 0;
	m_HostName.clear( );
	m_GameName.clear( );
	m_StatString.clear( );
	m_PlayerCount = 0;
	m_MapGameType = 0;
	m_Players.clear( );
	m_Slots.clear( );
	m_RandomSeed = 0;
	m_SelectMode = 0;
	m_StartSpotCount = 0;
	m_LoadingBlocks = queue<BYTEARRAY>( );
	m_Blocks = queue<BYTEARRAY>( );
	m_CheckSums = queue<uint32_t>( );

	if( m_Flags != 32768 )
	{
		CONSOLE_Print( "[REPLAY] invalid replay (flags mismatch)" );
		m_Valid = false;
		return;
	}

	istringstream ISS( m_Decompressed );

	unsigned char Garbage1;
	uint32_t Garbage4;
	string GarbageString;
	unsigned char GarbageData[65535];

	READB( ISS, &Garbage4, 4 );				// Unknown (4.0)

	if( Garbage4 != 272 )
	{
		CONSOLE_Print( "[REPLAY] invalid replay (4.0 Unknown mismatch)" );
		m_Valid = false;
		return;
	}

	READB( ISS, &Garbage1, 1 );				// Host RecordID (4.1)

	if( Garbage1 != 0 )
	{
		CONSOLE_Print( "[REPLAY] invalid replay (4.1 Host RecordID mismatch)" );
		m_Valid = false;
		return;
	}

	READB( ISS, &m_HostPID, 1 );

	if( m_HostPID > 15 )
	{
		CONSOLE_Print( "[REPLAY] invalid replay (4.1 Host PlayerID is invalid)" );
		m_Valid = false;
		return;
	}

	READSTR( ISS, m_HostName );				// Host PlayerName (4.1)
	READB( ISS, &Garbage1, 1 );				// Host AdditionalSize (4.1)

	if( Garbage1 != 1 )
	{
		CONSOLE_Print( "[REPLAY] invalid replay (4.1 Host AdditionalSize mismatch)" );
		m_Valid = false;
		return;
	}

	READB( ISS, &Garbage1, 1 );				// Host AdditionalData (4.1)

	if( Garbage1 != 0 )
	{
		CONSOLE_Print( "[REPLAY] invalid replay (4.1 Host AdditionalData mismatch)" );
		m_Valid = false;
		return;
	}

	AddPlayer( m_HostPID, m_HostName );
	READSTR( ISS, m_GameName );				// GameName (4.2)
	READSTR( ISS, GarbageString );			// Null (4.0)
	READSTR( ISS, m_StatString );			// StatString (4.3)
	READB( ISS, &m_PlayerCount, 4 );		// PlayerCount (4.6)

	if( m_PlayerCount > 12 )
	{
		CONSOLE_Print( "[REPLAY] invalid replay (4.6 PlayerCount is invalid)" );
		m_Valid = false;
		return;
	}

	READB( ISS, &m_MapGameType, 4 );		// GameType (4.7)
	READB( ISS, &Garbage4, 4 );				// LanguageID (4.8)

	while( 1 )
	{
		READB( ISS, &Garbage1, 1 );			// Player RecordID (4.1)

		if( Garbage1 == 22 )
		{
			unsigned char PlayerID;
			string PlayerName;
			READB( ISS, &PlayerID, 1 );		// Player PlayerID (4.1)

			if( PlayerID > 15 )
			{
				CONSOLE_Print( "[REPLAY] invalid replay (4.9 Player PlayerID is invalid)" );
				m_Valid = false;
				return;
			}

			READSTR( ISS, PlayerName );		// Player PlayerName (4.1)
			READB( ISS, &Garbage1, 1 );		// Player AdditionalSize (4.1)

			if( Garbage1 != 1 )
			{
				CONSOLE_Print( "[REPLAY] invalid replay (4.9 Player AdditionalSize mismatch)" );
				m_Valid = false;
				return;
			}

			READB( ISS, &Garbage1, 1 );		// Player AdditionalData (4.1)

			if( Garbage1 != 0 )
			{
				CONSOLE_Print( "[REPLAY] invalid replay (4.9 Player AdditionalData mismatch)" );
				m_Valid = false;
				return;
			}

			READB( ISS, &Garbage4, 4 );		// Unknown

			if( Garbage4 != 0 )
			{
				CONSOLE_Print( "[REPLAY] invalid replay (4.9 Unknown mismatch)" );
				m_Valid = false;
				return;
			}

			AddPlayer( PlayerID, PlayerName );
		}
		else if( Garbage1 == 25 )
			break;
		else
		{
			CONSOLE_Print( "[REPLAY] invalid replay (4.9 Player RecordID mismatch)" );
			m_Valid = false;
			return;
		}
	}

	uint16_t Size;
	unsigned char NumSlots;
	READB( ISS, &Size, 2 );					// Size (4.10)
	READB( ISS, &NumSlots, 1 );				// NumSlots (4.10)

	if( Size != 7 + NumSlots * 9 )
	{
		CONSOLE_Print( "[REPLAY] invalid replay (4.10 Size is invalid)" );
		m_Valid = false;
		return;
	}

	if( NumSlots == 0 || NumSlots > 12 )
	{
		CONSOLE_Print( "[REPLAY] invalid replay (4.10 NumSlots is invalid)" );
		m_Valid = false;
		return;
	}

        for( int i = 0; i < NumSlots; ++i )
	{
		unsigned char SlotData[9];
		READB( ISS, SlotData, 9 );
		BYTEARRAY SlotDataBA = UTIL_CreateByteArray( SlotData, 9 );
		m_Slots.push_back( CGameSlot( SlotDataBA ) );
	}

	READB( ISS, &m_RandomSeed, 4 );			// RandomSeed (4.10)
	READB( ISS, &m_SelectMode, 1 );			// SelectMode (4.10)
	READB( ISS, &m_StartSpotCount, 1 );		// StartSpotCount (4.10)

	if( ISS.eof( ) || ISS.fail( ) )
	{
		CONSOLE_Print( "[SAVEGAME] failed to parse replay header" );
		m_Valid = false;
		return;
	}

	if( !parseBlocks )
		return;

	READB( ISS, &Garbage1, 1 );				// first start block ID (5.0)

	if( Garbage1 != CReplay :: REPLAY_FIRSTSTARTBLOCK )
	{
		CONSOLE_Print( "[REPLAY] invalid replay (5.0 first start block ID mismatch)" );
		m_Valid = false;
		return;
	}

	READB( ISS, &Garbage4, 4 );				// first start block data (5.0)

	if( Garbage4 != 1 )
	{
		CONSOLE_Print( "[REPLAY] invalid replay (5.0 first start block data mismatch)" );
		m_Valid = false;
		return;
	}

	READB( ISS, &Garbage1, 1 );				// second start block ID (5.0)

	if( Garbage1 != CReplay :: REPLAY_SECONDSTARTBLOCK )
	{
		CONSOLE_Print( "[REPLAY] invalid replay (5.0 second start block ID mismatch)" );
		m_Valid = false;
		return;
	}

	READB( ISS, &Garbage4, 4 );				// second start block data (5.0)

	if( Garbage4 != 1 )
	{
		CONSOLE_Print( "[REPLAY] invalid replay (5.0 second start block data mismatch)" );
		m_Valid = false;
		return;
	}

	while( 1 )
	{
		READB( ISS, &Garbage1, 1 );			// third start block ID *or* loading block ID (5.0)

		if( ISS.eof( ) || ISS.fail( ) )
		{
			CONSOLE_Print( "[REPLAY] invalid replay (5.0 third start block unexpected end of file found)" );
			m_Valid = false;
			return;
		}
		if( Garbage1 == CReplay :: REPLAY_LEAVEGAME )
		{
			READB( ISS, GarbageData, 13 );
			BYTEARRAY LoadingBlock;
			LoadingBlock.push_back( Garbage1 );
			UTIL_AppendByteArray( LoadingBlock, GarbageData, 13 );
			m_LoadingBlocks.push( LoadingBlock );
		}
		else if( Garbage1 == CReplay :: REPLAY_THIRDSTARTBLOCK )
			break;
		else
		{
			CONSOLE_Print( "[REPLAY] invalid replay (5.0 third start block ID mismatch)" );
			m_Valid = false;
			return;
		}
	}

	READB( ISS, &Garbage4, 4 );				// third start block data (5.0)

	if( Garbage4 != 1 )
	{
		CONSOLE_Print( "[REPLAY] invalid replay (5.0 third start block data mismatch)" );
		m_Valid = false;
		return;
	}

	if( ISS.eof( ) || ISS.fail( ) )
	{
		CONSOLE_Print( "[SAVEGAME] failed to parse replay start blocks" );
		m_Valid = false;
		return;
	}

	uint32_t ActualReplayLength = 0;

	while( 1 )
	{
		READB( ISS, &Garbage1, 1 );			// block ID (5.0)

		if( ISS.eof( ) || ISS.fail( ) )
			break;
		else if( Garbage1 == CReplay :: REPLAY_LEAVEGAME )
		{
			READB( ISS, GarbageData, 13 );

			// reconstruct the block

			BYTEARRAY Block;
			Block.push_back( CReplay :: REPLAY_LEAVEGAME );
			UTIL_AppendByteArray( Block, GarbageData, 13 );
			m_Blocks.push( Block );
		}
		else if( Garbage1 == CReplay :: REPLAY_TIMESLOT )
		{
			uint16_t BlockSize;
			READB( ISS, &BlockSize, 2 );
			READB( ISS, GarbageData, BlockSize );

			if( BlockSize >= 2 )
				ActualReplayLength += GarbageData[0] | GarbageData[1] << 8;

			// reconstruct the block

			BYTEARRAY Block;
			Block.push_back( CReplay :: REPLAY_TIMESLOT );
			UTIL_AppendByteArray( Block, BlockSize, false );
			UTIL_AppendByteArray( Block, GarbageData, BlockSize );
			m_Blocks.push( Block );
		}
		else if( Garbage1 == CReplay :: REPLAY_CHATMESSAGE )
		{
			unsigned char PID;
			uint16_t BlockSize;
			READB( ISS, &PID, 1 );

			if( PID > 15 )
			{
				CONSOLE_Print( "[REPLAY] invalid replay (5.0 chatmessage pid is invalid)" );
				m_Valid = false;
				return;
			}

			READB( ISS, &BlockSize, 2 );
			READB( ISS, GarbageData, BlockSize );

			// reconstruct the block

			BYTEARRAY Block;
			Block.push_back( CReplay :: REPLAY_CHATMESSAGE );
			Block.push_back( PID );
			UTIL_AppendByteArray( Block, BlockSize, false );
			UTIL_AppendByteArray( Block, GarbageData, BlockSize );
			m_Blocks.push( Block );
		}
		else if( Garbage1 == CReplay :: REPLAY_CHECKSUM )
		{
			READB( ISS, &Garbage1, 1 );

			if( Garbage1 != 4 )
			{
				CONSOLE_Print( "[REPLAY] invalid replay (5.0 checksum unknown mismatch)" );
				m_Valid = false;
				return;
			}

			uint32_t CheckSum;
			READB( ISS, &CheckSum, 4 );
			m_CheckSums.push( CheckSum );
		}
		else
		{
			// it's not necessarily an error if we encounter an unknown block ID since replays can contain extra data

			break;
		}
	}

	if( m_ReplayLength != ActualReplayLength )
		CONSOLE_Print( "[REPLAY] warning - replay length mismatch (" + UTIL_ToString( m_ReplayLength ) + "ms/" + UTIL_ToString( ActualReplayLength ) + "ms)" );

	m_Valid = true;
}
Beispiel #6
0
string CSocket :: GetErrorString( )
{
    if( !m_HasError )
        return "NO ERROR";

    switch( m_Error )
    {
    case EWOULDBLOCK:
        return "EWOULDBLOCK";
    case EINPROGRESS:
        return "EINPROGRESS";
    case EALREADY:
        return "EALREADY";
    case ENOTSOCK:
        return "ENOTSOCK";
    case EDESTADDRREQ:
        return "EDESTADDRREQ";
    case EMSGSIZE:
        return "EMSGSIZE";
    case EPROTOTYPE:
        return "EPROTOTYPE";
    case ENOPROTOOPT:
        return "ENOPROTOOPT";
    case EPROTONOSUPPORT:
        return "EPROTONOSUPPORT";
    case ESOCKTNOSUPPORT:
        return "ESOCKTNOSUPPORT";
    case EOPNOTSUPP:
        return "EOPNOTSUPP";
    case EPFNOSUPPORT:
        return "EPFNOSUPPORT";
    case EAFNOSUPPORT:
        return "EAFNOSUPPORT";
    case EADDRINUSE:
        return "EADDRINUSE";
    case EADDRNOTAVAIL:
        return "EADDRNOTAVAIL";
    case ENETDOWN:
        return "ENETDOWN";
    case ENETUNREACH:
        return "ENETUNREACH";
    case ENETRESET:
        return "ENETRESET";
    case ECONNABORTED:
        return "ECONNABORTED";
    case ECONNRESET:
        return "ECONNRESET";
    case ENOBUFS:
        return "ENOBUFS";
    case EISCONN:
        return "EISCONN";
    case ENOTCONN:
        return "ENOTCONN";
    case ESHUTDOWN:
        return "ESHUTDOWN";
    case ETOOMANYREFS:
        return "ETOOMANYREFS";
    case ETIMEDOUT:
        return "ETIMEDOUT";
    case ECONNREFUSED:
        return "ECONNREFUSED";
    case ELOOP:
        return "ELOOP";
    case ENAMETOOLONG:
        return "ENAMETOOLONG";
    case EHOSTDOWN:
        return "EHOSTDOWN";
    case EHOSTUNREACH:
        return "EHOSTUNREACH";
    case ENOTEMPTY:
        return "ENOTEMPTY";
    case EUSERS:
        return "EUSERS";
    case EDQUOT:
        return "EDQUOT";
    case ESTALE:
        return "ESTALE";
    case EREMOTE:
        return "EREMOTE";
    }

    return "UNKNOWN ERROR (" + UTIL_ToString( m_Error ) + ")";
}
Beispiel #7
0
void CReplay :: BuildReplay( string gameName, string statString )
{
	CONSOLE_Print( "[REPLAY] building replay" );

	uint32_t LanguageID = 0x0012F8B0;

	BYTEARRAY Replay;
	Replay.push_back( 16 );															// Unknown (4.0)
	Replay.push_back( 1 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Host RecordID (4.1)
	Replay.push_back( m_HostPID );													// Host PlayerID (4.1)
	UTIL_AppendByteArray( Replay, m_HostName );										// Host PlayerName (4.1)
	Replay.push_back( 1 );															// Host AdditionalSize (4.1)
	Replay.push_back( 0 );															// Host AdditionalData (4.1)
	UTIL_AppendByteArray( Replay, gameName );										// GameName (4.2)
	Replay.push_back( 0 );															// Null (4.0)
	UTIL_AppendByteArray( Replay, statString );										// StatString (4.3)
	UTIL_AppendByteArray( Replay, (uint32_t)m_Slots.size( ), false );				// PlayerCount (4.6)
	Replay.push_back( m_MapGameType );												// GameType (4.7)
	Replay.push_back( 32 );															// GameType (4.7)
	Replay.push_back( 73 );															// GameType (4.7)
	Replay.push_back( 0 );															// GameType (4.7)
	UTIL_AppendByteArray( Replay, LanguageID, false );								// LanguageID (4.8)

	// PlayerList (4.9)

	for( vector<ReplayPlayer> :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ )
	{
		if( (*i).first != m_HostPID )
		{
			Replay.push_back( 22 );													// Player RecordID (4.1)
			Replay.push_back( (*i).first );											// Player PlayerID (4.1)
			UTIL_AppendByteArray( Replay, (*i).second );							// Player PlayerName (4.1)
			Replay.push_back( 1 );													// Player AdditionalSize (4.1)
			Replay.push_back( 0 );													// Player AdditionalData (4.1)
			UTIL_AppendByteArray( Replay, (uint32_t)0, false );						// Unknown
		}
	}

	// GameStartRecord (4.10)

	Replay.push_back( 25 );															// RecordID (4.10)
	UTIL_AppendByteArray( Replay, (uint16_t)( 7 + m_Slots.size( ) * 9 ), false );	// Size (4.10)
	Replay.push_back( m_Slots.size( ) );											// NumSlots (4.10)

	for( unsigned char i = 0; i < m_Slots.size( ); i++ )
		UTIL_AppendByteArray( Replay, m_Slots[i].GetByteArray( ) );

	UTIL_AppendByteArray( Replay, m_RandomSeed, false );							// RandomSeed (4.10)
	Replay.push_back( m_SelectMode );												// SelectMode (4.10)
	Replay.push_back( m_StartSpotCount );											// StartSpotCount (4.10)

	// ReplayData (5.0)

	Replay.push_back( REPLAY_FIRSTSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );
	Replay.push_back( REPLAY_SECONDSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );

	// leavers during loading need to be stored between the second and third start blocks

	while( !m_LoadingBlocks.empty( ) )
	{
		UTIL_AppendByteArray( Replay, m_LoadingBlocks.front( ) );
		m_LoadingBlocks.pop( );
	}

	Replay.push_back( REPLAY_THIRDSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );

	// initialize replay length to zero
	// we'll accumulate the replay length as we iterate through the timeslots
	// this is necessary because we might be discarding some timeslots due to not enough checksums and the replay length needs to be accurate

	m_ReplayLength = 0;
	uint32_t TimeSlotsDiscarded = 0;

	while( !m_Blocks.empty( ) )
	{
		BYTEARRAY Block = m_Blocks.front( );
		m_Blocks.pop( );

		if( Block.size( ) >= 5 && Block[0] == REPLAY_TIMESLOT )
		{
			if( m_CheckSums.empty( ) )
			{
				TimeSlotsDiscarded++;
				continue;
			}

			// append timeslot

			UTIL_AppendByteArray( Replay, Block );

			// append checksum

			BYTEARRAY CheckSum;
			CheckSum.push_back( REPLAY_CHECKSUM );
			CheckSum.push_back( 4 );
			UTIL_AppendByteArray( CheckSum, m_CheckSums.front( ), false );
			m_CheckSums.pop( );
			UTIL_AppendByteArray( Replay, CheckSum );

			// accumulate replay length

			m_ReplayLength += UTIL_ByteArrayToUInt16( Block, false, 3 );
		}
		else
			UTIL_AppendByteArray( Replay, Block );
	}

	if( TimeSlotsDiscarded > 0 )
		CONSOLE_Print( "[REPLAY] ran out of checksums, discarded " + UTIL_ToString( TimeSlotsDiscarded ) + " timeslots" );

	// done

	m_Decompressed = string( Replay.begin( ), Replay.end( ) );
}
Beispiel #8
0
bool MySQLBanAdd( void *conn, string *error, uint32_t botid, string server, string user, string ip, string gamename, string admin, string reason )
{
	transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower );
	string EscServer = MySQLEscapeString( conn, server );
	string EscUser = MySQLEscapeString( conn, user );
	string EscIP = MySQLEscapeString( conn, ip );
	string EscGameName = MySQLEscapeString( conn, gamename );
	string EscAdmin = MySQLEscapeString( conn, admin );
	string EscReason = MySQLEscapeString( conn, reason );
	bool Success = false;
	string Query = "INSERT INTO bans ( botid, server, name, ip, date, gamename, admin, reason ) VALUES ( " + UTIL_ToString( botid ) + ", '" + EscServer + "', '" + EscUser + "', '" + EscIP + "', CURDATE( ), '" + EscGameName + "', '" + EscAdmin + "', '" + EscReason + "' )";

	if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 )
		*error = mysql_error( (MYSQL *)conn );
	else
		Success = true;

	return Success;
}
Beispiel #9
0
uint32_t MySQLW3MMDPlayerAdd( void *conn, string *error, uint32_t botid, string category, uint32_t gameid, uint32_t pid, string name, string flag, uint32_t leaver, uint32_t practicing )
{
	transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower );
	uint32_t RowID = 0;
	string EscCategory = MySQLEscapeString( conn, category );
	string EscName = MySQLEscapeString( conn, name );
	string EscFlag = MySQLEscapeString( conn, flag );
	string Query = "INSERT INTO w3mmdplayers ( botid, category, gameid, pid, name, flag, leaver, practicing ) VALUES ( " + UTIL_ToString( botid ) + ", '" + EscCategory + "', " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( pid ) + ", '" + EscName + "', '" + EscFlag + "', " + UTIL_ToString( leaver ) + ", " + UTIL_ToString( practicing ) + " )";

	if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 )
		*error = mysql_error( (MYSQL *)conn );
	else
		RowID = mysql_insert_id( (MYSQL *)conn );

	return RowID;
}
bool CGamePlayer :: Update( void *fd )
{
	// wait 4 seconds after joining before sending the /whois or /w
	// if we send the /whois too early battle.net may not have caught up with where the player is and return erroneous results

	if( m_WhoisShouldBeSent && !m_Spoofed && !m_WhoisSent && !m_JoinedRealm.empty( ) && GetTime( ) - m_JoinTime >= 4 )
	{
		// todotodo: we could get kicked from battle.net for sending a command with invalid characters, do some basic checking

		// check if we have this ip in our spoofed cached ip list
		bool isspoofed = m_Game->m_GHost->IsSpoofedIP(GetName(), GetExternalIPString());

		if (isspoofed)
		{
			CONSOLE_Print("[OPT] Player "+GetName()+" is in the cached spoof checked list");
			m_Game->AddToSpoofed(m_Game->m_Server, GetName(), false);
		}

		if (!isspoofed && GetExternalIPString()!="127.0.0.1")
		for( vector<CBNET *> :: iterator i = m_Game->m_GHost->m_BNETs.begin( ); i != m_Game->m_GHost->m_BNETs.end( ); i++ )
		{
			if( (*i)->GetServer( ) == m_JoinedRealm )
			{
				if( m_Game->GetGameState( ) == GAME_PUBLIC )
				{
					if ((*i)->GetWhereis() || (*i)->GetPasswordHashType( ) == "pvpgn" )
						(*i)->QueueChatCommand( "/whereis " + m_Name );
					else
						(*i)->QueueChatCommand( "/whois " + m_Name );
				}
				else if( m_Game->GetGameState( ) == GAME_PRIVATE )
					(*i)->QueueChatCommand( m_Game->m_GHost->m_Language->SpoofCheckByReplying( ), m_Name, true );
			}
		}

		m_WhoisSent = true;
	}

	// check for socket timeouts
	// if we don't receive anything from a player for 30 seconds we can assume they've dropped
	// this works because in the lobby we send pings every 5 seconds and expect a response to each one
	// and in the game the Warcraft 3 client sends keepalives frequently (at least once per second it looks like)

	if( m_Socket && GetTime( ) - m_Socket->GetLastRecv( ) >= 30 )
		m_Game->EventPlayerDisconnectTimedOut( this );
	// make sure we're not waiting too long for the first MAPSIZE packet
	
	if( m_ConnectionState == 1 && GetTicks( ) - m_ConnectionTime > m_Game->m_GHost->m_DenyMaxMapsizeTime && !m_Game->GetGameLoaded() && !m_Game->GetGameLoading() )
	{
		CONSOLE_Print( "[DENY] Kicking player: MAPSIZE not received within a few seconds" );
		m_DeleteMe = true;
		SetLeftReason( "MAPSIZE not received within a few seconds" );
		SetLeftCode( PLAYERLEAVE_LOBBY );
		m_Game->OpenSlot( m_Game->GetSIDFromPID( GetPID( ) ), false );
		m_Game->m_GHost->DenyIP( GetExternalIPString( ), m_Game->m_GHost->m_DenyMapsizeDuration, "MAPSIZE not received within a few seconds" );
	}
	
	// disconnect if the player is downloading too slowly
	
	if( m_DownloadStarted && !m_DownloadFinished && !m_Game->GetGameLoaded() && !m_Game->GetGameLoading() && GetLastMapPartSent( ) != 0 )
	{
		uint32_t downloadingTime = GetTicks( ) - m_StartedDownloadingTicks;
		uint32_t Seconds = downloadingTime / 1000;
		uint32_t Rate = GetLastMapPartSent( ) / 1024; // Rate in miliseconds
		if (Seconds>0)
			Rate /= Seconds;
		
		if(!(m_Game->IsSafe(GetName()) || m_Game->IsAdmin(GetName()) || m_Game->IsRootAdmin(GetName()) || m_Game->IsOwner(GetName()) )){			
		//	uint32_t iRate = (uint32_t)Rate;
			if ( m_Game->m_GHost->m_DLRateLimit != 0 )
			if ( GetLastMapPartSent( ) <= 102400 )
			if ( 0 < Rate && Rate < m_Game->m_GHost->m_DLRateLimit ){
				m_Game->DelTempOwner( GetName() );
				m_Game->SendAllChat( m_Game->m_GHost->m_Language->KickMsgForSlowDL( GetName( ) , UTIL_ToString( Rate ), UTIL_ToString(m_Game->m_GHost->m_DLRateLimit) ) );							
				m_Game->m_GHost->m_Callables.push_back( m_Game->m_GHost->m_DB->ThreadedBanAdd( GetJoinedRealm( ), GetName( ), GetExternalIPString(), m_Game->GetGameName( ), "AUTOBAN", "Slow internet", 1, 0 ));
				if ( m_Game->m_GHost->m_BlacklistSlowDLder && !m_Game->IsBlacklisted(m_Game->GetBannedNames( ),GetName( )) )
					m_Game->AddBannedNames(GetName( ));
				m_DeleteMe = true;				
				SetLeftReason( "kicked for downloading too slowly " + UTIL_ToString( Rate ) + " KB/s" );				
				SetLeftCode( PLAYERLEAVE_LOBBY );
				m_Game->OpenSlot( m_Game->GetSIDFromPID( GetPID( ) ), false );
			}
			
			if( downloadingTime > m_Game->m_GHost->m_DenyMaxDownloadTime )
			{
				m_Game->DelTempOwner( GetName() );
				m_Game->SendAllChat( m_Game->m_GHost->m_Language->KickMsgForSlowDL( GetName( ),"","" ) );
				m_DeleteMe = true;
				SetLeftReason( "download time is too long" );
				SetLeftCode( PLAYERLEAVE_LOBBY );
				m_Game->OpenSlot( m_Game->GetSIDFromPID( GetPID( ) ), false );
				m_Game->m_GHost->DenyIP( GetExternalIPString( ), m_Game->m_GHost->m_DenyDownloadDuration, "("+ GetName( ) +") rejected because download time is too long" );
			}
		}
	}
	
	// unmute player
	if( GetMuted( ) && ( GetTicks( ) - m_MutedTicks > 60000 || ( m_MutedAuto && GetTicks( ) - m_MutedTicks > 15000 ) ) )
	{
		SetMuted( false );
		m_Game->SendAllChat( "[" + m_Name + "] has been automatically unmuted. (Don't spam or you'll be muted again!)" );
		m_MuteMessages.clear( );
	}

	// GProxy++ acks

	if( m_GProxy && GetTime( ) - m_LastGProxyAckTime >= 10 )
	{
		if( m_Socket )
			m_Socket->PutBytes( m_Game->m_GHost->m_GPSProtocol->SEND_GPSS_ACK( m_TotalPacketsReceived ) );

		m_LastGProxyAckTime = GetTime( );
	}

	// base class update

	CPotentialPlayer :: Update( fd );
	bool Deleting;

	if( m_GProxy && m_Game->GetGameLoaded( ) )
		Deleting = m_DeleteMe || m_Error;
	else
		Deleting = m_DeleteMe || m_Error || m_Socket->HasError( ) || !m_Socket->GetConnected( );

	// try to find out why we're requesting deletion
	// in cases other than the ones covered here m_LeftReason should have been set when m_DeleteMe was set

	if( m_Error ){
		m_Game->m_GHost->DenyIP( GetExternalIPString( ), 180000, "player error" );
		m_Game->EventPlayerDisconnectPlayerError( this );
		m_Socket->Reset( );
		return Deleting;
	}
	if( m_Socket )
	{
		if( m_Socket->HasError( ) ){
			m_Game->EventPlayerDisconnectSocketError( this );
			if( !m_GProxy )
				m_Game->m_GHost->DenyIP( GetExternalIPString( ), 20000, "socket error" );
		}
		else if( !m_Socket->GetConnected( ) ){
			m_Game->EventPlayerDisconnectConnectionClosed( this );
			if( !m_GProxy )
				m_Game->m_GHost->DenyIP( GetExternalIPString( ), 30000, "connection closed" );
		}
	}

	return Deleting;
}
Beispiel #11
0
inline void CIRC :: ExtractPackets( )
{
	string Token, PreviousToken, Recv = *( m_Socket->GetBytes( ) );
        uint32_t Time = GetTime( );
        unsigned int i;

        /* loop through whole recv buffer */

        for( i = 0; i < Recv.size( ); ++i )
        {
            // add chars to token

            if( Recv[i] != ' ' && Recv[i] != CR && Recv[i] != LF )
            {
                Token += Recv[i];
            }
            else if( Recv[i] == ' ' || Recv[i] == LF )
            {
                // end of token, examine

                if( Token == "PRIVMSG" )
                {
                    // parse the PreviousToken as it holds the user info and then the Token for the message itself

                    string Nickname, Hostname, Message, Command, Payload;
                    bool IsCommand = true;

                    unsigned int j = 1;

                    // get nickname

                    for( ; PreviousToken[j] != '!'; ++j )
                        Nickname += PreviousToken[j];

                    // skip username

                    for( j += 2; PreviousToken[j] != '@'; ++j );

                    // get hostname

                    for( ++j; j < PreviousToken.size( ); ++j )
                        Hostname += PreviousToken[j];

                    // skip channel

                    for( i += 3; Recv[i] != ':'; ++i );

                    // process message

                    for( ++i; Recv[i] != CR; ++i )
                    {
                        Message += Recv[i];

                        if( Recv[i] == ' ' && IsCommand )
                        {
                            IsCommand = false;
                            continue;
                        }

                        if( Message.size( ) != 1 )
                        {
                            if( IsCommand )
                                Command += tolower( Recv[i] );
                            else
                                Payload += Recv[i];
                        }
                    }

                    // move position after the \n

                    i += 2;

                    if( Message.empty( ) )
                    {
                        PreviousToken = Token;
                        Token.clear( );
                        continue;
                    }

                    if( Message[0] != SOH )
                    {
                            for( vector<CBNET *> :: iterator i = m_Aura->m_BNETs.begin( ); i != m_Aura->m_BNETs.end( ); ++i )
                            {
                                    if( Message[0] == (*i)->GetCommandTrigger( ) )
                                    {
                                        CIncomingChatEvent event = CIncomingChatEvent( CBNETProtocol :: EID_IRC, Nickname, Message );
					(*i)->ProcessChatEvent( &event );
					break;
                                    }
                            }

                            if( Message[0] == m_CommandTrigger[0] )
                            {
                                bool Root = Hostname.substr( 0, 6 ) == "Aurani" || Hostname.substr( 0, 8 ) == "h4x0rz88";

                                if( Command == "nick" && Root )
				{
                                        SendIRC( "NICK :" + Payload );
                                        m_Nickname = Payload;
                                        m_OriginalNick= false;
                                }
                                else if( Command == "dcclist" )
                                {
                                        string on, off;

                                        for( vector<CDCC *> :: iterator i = m_DCC.begin( ); i != m_DCC.end( ); ++i )
                                        {
                                                if( (*i)->m_Socket->GetConnected( ) )
                                                        on += (*i)->m_Nickname + "[" + UTIL_ToString( (*i)->m_Port ) +"] ";
                                                else
                                                        off += (*i)->m_Nickname + "[" + UTIL_ToString( (*i)->m_Port ) +"] ";
                                        }

                                        SendMessageIRC( "ON: " + on, string( ) );
                                        SendMessageIRC( "OFF: " + off, string( ) );
                                }
                                else if( Command == "bnetoff" )
                                {
                                        if( Payload.empty( ) )
                                        {
                                                for( vector<CBNET *> :: iterator i = m_Aura->m_BNETs.begin( ); i != m_Aura->m_BNETs.end( ); ++i )
                                                {
                                                        (*i)->Deactivate( );
                                                        SendMessageIRC( "[BNET: " + (*i)->GetServerAlias( ) + "] deactivated.", string( ) );
                                                }
                                        }
                                        else
                                        {
                                                for( vector<CBNET *> :: iterator i = m_Aura->m_BNETs.begin( ); i != m_Aura->m_BNETs.end( ); ++i )
                                                {
                                                        if( (*i)->GetServerAlias( ) == Payload )
                                                        {
                                                                (*i)->Deactivate( );
                                                                SendMessageIRC( "[BNET: " + (*i)->GetServerAlias( ) + "] deactivated.", string( ) );
                                                                break;
                                                        }
                                                }
                                        }
                                }
                                else if( Command == "bneton" )
                                {
                                        if( Payload.empty( ) )
                                        {
                                                for( vector<CBNET *> :: iterator i = m_Aura->m_BNETs.begin( ); i != m_Aura->m_BNETs.end( ); ++i )
                                                {
                                                        (*i)->Activate( );
                                                        SendMessageIRC( "[BNET: " + (*i)->GetServerAlias( ) + "] activated.", string( ) );
                                                }
                                        }
                                        else
                                        {
                                                for( vector<CBNET *> :: iterator i = m_Aura->m_BNETs.begin( ); i != m_Aura->m_BNETs.end( ); ++i )
                                                {
                                                        if( (*i)->GetServerAlias( ) == Payload )
                                                        {
                                                                (*i)->Activate( );
                                                                SendMessageIRC( "[BNET: " + (*i)->GetServerAlias( ) + "] activated.", string( ) );
                                                                break;
                                                        }
                                                }
                                        }
                                 }
                          }
                    }
                    else if( Payload.size( ) > 12 && Payload.substr( 0, 4 ) == "CHAT" )
                    {
                            // CHAT chat 3162588924 1025

                            string strIP, strPort;
                            bool IsPort = false;

                            for( unsigned int j = 10; j < ( Payload.size( ) - 1 ); ++j )
                            {
                                if( !IsPort && Payload[j] == ' ' )
                                {
                                    IsPort = true;
                                    continue;
                                }

                                if( !IsPort )
                                    strIP += Payload[j];
                                else
                                    strPort += Payload[j];
                            }

                            unsigned int Port = UTIL_ToUInt16( strPort );

                            if( Port < 1024 || 1026 < Port )
                                Port = 1024;

                            bool Local = false;

                            for( vector<string> :: iterator i = m_Locals.begin( ); i != m_Locals.end( ); ++i )
                            {
                                    if( Nickname == (*i) )
                                    {
                                            strIP = "127.0.0.1";
                                            Local = true;
                                            break;
                                    }
                            }

                            if( !Local )
                            {
                                    unsigned long IP = UTIL_ToUInt32( strIP ), divider = 16777216UL;
                                    strIP = "";

                                    for( int i = 0; i <= 3; ++i )
                                    {
                                            stringstream ss;
                                            ss << (unsigned long) IP / divider;

                                            IP %= divider;
                                            divider /= 256;
                                            strIP += ss.str( );

                                            if( i != 3 )
                                                    strIP += '.';
                                    }
                            }

                            bool Existing = false;

                            for( vector<CDCC *> :: iterator i = m_DCC.begin( ); i != m_DCC.end( ); ++i )
                            {
                                    if( (*i)->m_Nickname == Nickname )
                                    {
                                            (*i)->Connect( strIP, Port );
                                            Existing = true;
                                            break;
                                    }
                            }

                            if( !Existing )
                                m_DCC.push_back( new CDCC( this, strIP, Port, Nickname ) );
                    }

                    // remember last packet time

                    m_LastPacketTime = Time;
                }
                else if( Token == "391" )
                {
                    // move position after the \n (next packet)

                    for( ++i; Recv[i] != CR; ++i );

                    i += 2;

                    // remember last packet time

                    m_LastPacketTime = Time;
                }
                 else if( Token == "PING" )
                {
                    string Packet;

                    // PING :blabla

                    // skip until :

                    for( ++i; Recv[i] != ':'; ++i );

                    for( ++i; Recv[i] != CR; ++i )
                        Packet += Recv[i];

                    SendIRC( "PONG :" + Packet );

                    // move position after the \n

                    i += 2;

                    // remember last packet time

                    m_LastPacketTime = Time;
                }
                else if( Token == "NOTICE" )
                {
                    // move position after the \n

                    for( ++i; Recv[i] != CR; ++i );
                    
                    i += 2;

                    // remember last packet time

                    m_LastPacketTime = Time;
                }
                else if( Token == "221" )
                {
                    // Q auth if the server is QuakeNet

                    if( m_Server.find( "quakenet.org" ) != string :: npos && !m_Password.empty( ) )
                    {
                            SendMessageIRC( "AUTH " + m_Username + " " + m_Password, "*****@*****.**" );
                            SendIRC( "MODE " + m_Nickname + " +x" );
                    }

                    // join channels

                    for( vector<string> :: iterator j = m_Channels.begin( ); j != m_Channels.end( ); ++j )
                    {
                            SendIRC( "JOIN " + (*j) );
                    }

                    // move position after the \n

                    for( ++i; Recv[i] != CR; ++i );

                    i += 2;

                    // remember last packet time

                    m_LastPacketTime = Time;
                }
                else if( Token == "433" )
                {
                    // nick taken, append _

                    m_OriginalNick = false;
                    m_Nickname += '_';

                    SendIRC( "NICK " + m_Nickname );

                    // move position after the \n (next packet)

                    for( ++i; Recv[i] != CR; ++i );

                    i += 2;

                    // remember last packet time

                    m_LastPacketTime = Time;
                }
                else if( Token == "353" )
                {
                    // move position after the \n (next packet)

                    for( ++i; Recv[i] != CR; ++i );

                    i += 2;

                    // remember last packet time

                    m_LastPacketTime = Time;
                }
                else if( Token == "KICK" )
                {
                    string Channel, Victim;
                    bool Space = false;

                    // get channel

                    for( ++i; Recv[i] != ' '; ++i )
                            Channel += Recv[i];

                    // get the victim

                    for( ++i ; i < Recv.size( ); ++i )
                    {
                        if( Recv[i] == ' ' )
                            Space = true;
                        else if( Recv[i] == CR )
                            break;
                        else if( Space && Recv[i] != ':' )
                            Victim += Recv[i];
                    }

                    // we're the victim here! rejoin

                    if( Victim == m_Nickname )
                    {
                        SendIRC( "JOIN " + Channel );
                    }

                    // move position after the \n

                    i += 2;

                    // remember last packet time

                    m_LastPacketTime = Time;
                }

                // empty the token

                PreviousToken = Token;
                Token.clear( );
            }
        }

        m_Socket->ClearRecvBuffer( );
}
Beispiel #12
0
void CBNET :: ProcessChatEvent( CIncomingChatEvent *chatEvent )
{
	CBNETProtocol :: IncomingChatEvent Event = chatEvent->GetChatEvent( );
	string User = chatEvent->GetUser( ), lowerUser = chatEvent->GetUser( ), Message = chatEvent->GetMessage( );
	transform( lowerUser.begin( ), lowerUser.end( ), lowerUser.begin( ), (int(*)(int))tolower );
	
	unsigned char Access = m_CCBot->m_DB->AccessCheck( m_Server, lowerUser );
	
	if( Access == 255 )
		Access = 0;
	
	bool Output = ( Event == CBNETProtocol :: CONSOLE_INPUT );			
	bool Whisper = ( Event == CBNETProtocol :: EID_WHISPER );
        bool ClanMember = IsClanMember( m_UserName );

	if( Event == CBNETProtocol :: EID_TALK )
			CONSOLE_Print( "[LOCAL: " + m_ServerAlias + ":" + m_CurrentChannel + "][" + User + "] " + Message );
	else if( Event == CBNETProtocol :: EID_WHISPER )
			CONSOLE_Print( "[WHISPER: " + m_ServerAlias + "][" + User + "] " + Message );
	else if( Event == CBNETProtocol :: EID_EMOTE )
			CONSOLE_Print( "[EMOTE: " + m_ServerAlias + ":" + m_CurrentChannel + "][" + User + "] " + Message );

	if( Event == CBNETProtocol :: EID_TALK || Event == CBNETProtocol :: EID_WHISPER  || Event == CBNETProtocol :: EID_EMOTE || Event == CBNETProtocol :: CONSOLE_INPUT )
	{
		// Anti-Spam
		// TODO: improve this to be more robust and efficient

		if( m_AntiSpam && !Message.empty( ) && Message[0] != m_CommandTrigger[0] && Access < 5 && IsInChannel( User ) && User != m_UserName )
		{
			string message = Message;
			transform( message.begin( ), message.end( ), message.begin( ), (int(*)(int))tolower );
			uint32_t SpamCacheSize = m_Channel.size( ) * 3;

			if( m_SpamCache.size( ) > SpamCacheSize )
				m_SpamCache.erase( m_SpamCache.begin( ) );

			m_SpamCache.insert( pair<string, string>( lowerUser, message ) );

			int mesgmatches = 0, nickmatches = 0;

			for( multimap<string, string> :: iterator i = m_SpamCache.begin( ); i != m_SpamCache.end( ); ++i )
			{
				if( (*i).first == lowerUser )
					++nickmatches;

				if( (*i).second.find( message ) )
					++mesgmatches;
			}

			if( mesgmatches > 2 || nickmatches > 3 )
				SendChatCommand( "/kick " + User + " Anti-Spam", Output );
		}

		// Swearing kick

		if ( m_SwearingKick && !Message.empty( ) && !Match( User, m_HostbotName ) && !m_CCBot->m_DB->SafelistCheck( m_Server, User ) && IsInChannel( User ) && Access < 5 ) 
		{
			string message = Message;
			transform( message.begin( ), message.end( ), message.begin( ), (int(*)(int))tolower );

			for( uint32_t i = 0; i < m_CCBot->m_SwearList.size( ); ++i )
			{
				if( message.find( m_CCBot->m_SwearList[i] ) != string :: npos )
					QueueChatCommand( m_CCBot->m_Language->SwearKick( User, m_CCBot->m_SwearList[i] ), Output );
			}
		}
		
		// ?TRIGGER
		
		if( Match( Message, "?trigger" ) )
		{
			QueueChatCommand( m_CCBot->m_Language->CommandTrigger( m_CommandTrigger ), User, Whisper, Output );	
		}		
		else if( !Message.empty( ) && Message[0] == m_CommandTrigger[0] && Event != CBNETProtocol :: EID_EMOTE )
		{
			// extract the command trigger, the command, and the payload
			// e.g. "!say hello world" -> command: "say", payload: "hello world"

			string Command, Payload;
			string :: size_type PayloadStart = Message.find( " " );

			if( PayloadStart != string :: npos )
			{
				Command = Message.substr( 1, PayloadStart - 1 );
				Payload = Message.substr( PayloadStart + 1 );
			}
			else
				Command = Message.substr( 1 );

			transform( Command.begin( ), Command.end( ), Command.begin( ), (int(*)(int))tolower );
			

			/********************************
			************ COMMANDS ***********
			********************************/

			//
			// !ACCEPT
			//

			if( Command == "accept" && Payload.empty( ) && Access >= m_CCBot->m_DB->CommandAccess( "accept" ) && m_ActiveInvitation )
			{
				m_Socket->PutBytes( m_Protocol->SEND_SID_CLANINVITATIONRESPONSE( m_Protocol->GetClanTag( ), m_Protocol->GetInviter( ), true ) );
				QueueChatCommand( m_CCBot->m_Language->InvitationAccepted( ), User, Whisper, Output );
				SendGetClanList( );
				m_ActiveInvitation = false;
			}

			//
			// !ACCESS
			//

			else if( Command == "access" && Payload.empty( ) && Access >= m_CCBot->m_DB->CommandAccess( "access" ) )
			{
				SendChatCommand( "/w " + User + " " + m_CCBot->m_Language->HasFollowingAccess( UTIL_ToString( Access ) ), Output );
				
				for( unsigned char n = 0; n <= Access; ++n )
				{
					string Commands;

					vector<string> m_CommandList = m_CCBot->m_DB->CommandList( n );

					for( vector<string> :: iterator i = m_CommandList.begin( ); i != m_CommandList.end( ); ++i )
						Commands = Commands + m_CommandTrigger + (*i) + ", ";

					Commands = Commands.substr( 0, Commands.size( ) -2 );

					if( m_CommandList.size ( ) )
						SendChatCommand( "/w " + User + " [" + UTIL_ToString( n ) + "]: " + Commands, Output );
					else
						break;
				}
			}

			//
			// !ADDSAFELIST
			// !ADDS
			//
				
			else if( ( Command == "addsafelist" || Command == "adds" ) && !Payload.empty( ) && Access >= m_CCBot->m_DB->CommandAccess( "addsafelist" ) )
			{					
				if( m_CCBot->m_DB->SafelistCheck( m_Server, Payload ) )
					QueueChatCommand( m_CCBot->m_Language->UserAlreadySafelisted( Payload ), User, Whisper, Output );
				else
				{
					if( m_CCBot->m_DB->SafelistAdd( m_Server, Payload ) )
						QueueChatCommand( m_CCBot->m_Language->UserSafelisted( Payload ), User, Whisper, Output );
					else
						QueueChatCommand( m_CCBot->m_Language->ErrorSafelisting( Payload ), User, Whisper, Output );
				}					
			}
				
			//
			// !ANNOUNCE
			//

			else if( Command == "announce" && !Payload.empty( ) && Access >= m_CCBot->m_DB->CommandAccess( "announce" ) )
			{					
				string Interval, AnnounceMessage;
				stringstream SS;
				SS << Payload;
				SS >> Interval;
				if( !SS.eof( ) )
				{
					getline( SS, AnnounceMessage );
					string :: size_type Start = AnnounceMessage.find_first_not_of( " " );

					if( Start != string :: npos )
						AnnounceMessage = AnnounceMessage.substr( Start );
				}

				if( ( UTIL_ToInt32( Interval ) > 0 ) && AnnounceMessage.size( ) )
				{
					m_Announce = true;
					m_AnnounceMsg = AnnounceMessage;
					m_AnnounceInterval = UTIL_ToInt32( Interval );

					if( m_AnnounceInterval < 3 )
						m_AnnounceInterval = 4;

					QueueChatCommand( m_CCBot->m_Language->AnnounceEnabled( Interval ), User, Whisper, Output );				
				}
				else if( Interval == "off" && m_Announce == true )
				{
					m_Announce = false;
					QueueChatCommand( m_CCBot->m_Language->AnnounceDisabled( ), User, Whisper, Output );
				}
			}

			//
			// !BAN
			// !ADDBAN
			//

			else if( ( Command == "ban" || Command == "addban" ) && !Payload.empty( ) && Access >= m_CCBot->m_DB->CommandAccess( "ban" ) )
Beispiel #13
0
bool MySQLDownloadAdd( void *conn, string *error, uint32_t botid, string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime )
{
	bool Success = false;
	string EscMap = MySQLEscapeString( conn, map );
	string EscName = MySQLEscapeString( conn, name );
	string EscIP = MySQLEscapeString( conn, ip );
	string EscSpoofedRealm = MySQLEscapeString( conn, spoofedrealm );
	string Query = "INSERT INTO downloads ( botid, map, mapsize, datetime, name, ip, spoofed, spoofedrealm, downloadtime ) VALUES ( " + UTIL_ToString( botid ) + ", '" + EscMap + "', " + UTIL_ToString( mapsize ) + ", NOW( ), '" + EscName + "', '" + EscIP + "', " + UTIL_ToString( spoofed ) + ", '" + EscSpoofedRealm + "', " + UTIL_ToString( downloadtime ) + " )";

	if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 )
		*error = mysql_error( (MYSQL *)conn );
	else
		Success = true;

	return Success;
}
Beispiel #14
0
void CMap :: Load( CConfig *CFG, string nCFGFile )
{
	m_Valid = true;
	m_CFGFile = nCFGFile;

	// load the map data

	m_MapLocalPath = CFG->GetString( "map_localpath", string( ) );
	m_MapData.clear( );

	if( !m_MapLocalPath.empty( ) )
		m_MapData = UTIL_FileRead( m_GHost->m_MapPath + m_MapLocalPath );

	// load the map MPQ

	string MapMPQFileName = m_GHost->m_MapPath + m_MapLocalPath;
	HANDLE MapMPQ;
	bool MapMPQReady = false;

	if( SFileOpenArchive( MapMPQFileName.c_str( ), 0, MPQ_OPEN_FORCE_MPQ_V1, &MapMPQ ) )
	{
		CONSOLE_Print( "[MAP] loading MPQ file [" + MapMPQFileName + "]" );
		MapMPQReady = true;
	}
	else
		CONSOLE_Print( "[MAP] warning - unable to load MPQ file [" + MapMPQFileName + "]" );

	// try to calculate map_size, map_info, map_crc, map_sha1

	BYTEARRAY MapSize;
	BYTEARRAY MapInfo;
	BYTEARRAY MapCRC;
	BYTEARRAY MapSHA1;

	if( !m_MapData.empty( ) )
	{
		m_GHost->m_SHA->Reset( );

		// calculate map_size

		MapSize = UTIL_CreateByteArray( (uint32_t)m_MapData.size( ), false );
		CONSOLE_Print( "[MAP] calculated map_size = " + UTIL_ByteArrayToDecString( MapSize ) );

		// calculate map_info (this is actually the CRC)

		MapInfo = UTIL_CreateByteArray( (uint32_t)m_GHost->m_CRC->FullCRC( (unsigned char *)m_MapData.c_str( ), m_MapData.size( ) ), false );
		CONSOLE_Print( "[MAP] calculated map_info = " + UTIL_ByteArrayToDecString( MapInfo ) );

		// calculate map_crc (this is not the CRC) and map_sha1
		// a big thank you to Strilanc for figuring the map_crc algorithm out

		string CommonJ = UTIL_FileRead( m_GHost->m_MapCFGPath + "common.j" );

		if( CommonJ.empty( ) )
			CONSOLE_Print( "[MAP] unable to calculate map_crc/sha1 - unable to read file [" + m_GHost->m_MapCFGPath + "common.j]" );
		else
		{
			string BlizzardJ = UTIL_FileRead( m_GHost->m_MapCFGPath + "blizzard.j" );

			if( BlizzardJ.empty( ) )
				CONSOLE_Print( "[MAP] unable to calculate map_crc/sha1 - unable to read file [" + m_GHost->m_MapCFGPath + "blizzard.j]" );
			else
			{
				uint32_t Val = 0;

				// update: it's possible for maps to include their own copies of common.j and/or blizzard.j
				// this code now overrides the default copies if required

				bool OverrodeCommonJ = false;
				bool OverrodeBlizzardJ = false;

				if( MapMPQReady )
				{
					HANDLE SubFile;

					// override common.j

					if( SFileOpenFileEx( MapMPQ, "Scripts\\common.j", 0, &SubFile ) )
					{
						uint32_t FileLength = SFileGetFileSize( SubFile, NULL );

						if( FileLength > 0 && FileLength != 0xFFFFFFFF )
						{
							char *SubFileData = new char[FileLength];
							DWORD BytesRead = 0;

							if( SFileReadFile( SubFile, SubFileData, FileLength, &BytesRead ) )
							{
								CONSOLE_Print( "[MAP] overriding default common.j with map copy while calculating map_crc/sha1" );
								OverrodeCommonJ = true;
								Val = Val ^ XORRotateLeft( (unsigned char *)SubFileData, BytesRead );
								m_GHost->m_SHA->Update( (unsigned char *)SubFileData, BytesRead );
							}

							delete [] SubFileData;
						}

						SFileCloseFile( SubFile );
					}
				}

				if( !OverrodeCommonJ )
				{
					Val = Val ^ XORRotateLeft( (unsigned char *)CommonJ.c_str( ), CommonJ.size( ) );
					m_GHost->m_SHA->Update( (unsigned char *)CommonJ.c_str( ), CommonJ.size( ) );
				}

				if( MapMPQReady )
				{
					HANDLE SubFile;

					// override blizzard.j

					if( SFileOpenFileEx( MapMPQ, "Scripts\\blizzard.j", 0, &SubFile ) )
					{
						uint32_t FileLength = SFileGetFileSize( SubFile, NULL );

						if( FileLength > 0 && FileLength != 0xFFFFFFFF )
						{
							char *SubFileData = new char[FileLength];
							DWORD BytesRead = 0;

							if( SFileReadFile( SubFile, SubFileData, FileLength, &BytesRead ) )
							{
								CONSOLE_Print( "[MAP] overriding default blizzard.j with map copy while calculating map_crc/sha1" );
								OverrodeBlizzardJ = true;
								Val = Val ^ XORRotateLeft( (unsigned char *)SubFileData, BytesRead );
								m_GHost->m_SHA->Update( (unsigned char *)SubFileData, BytesRead );
							}

							delete [] SubFileData;
						}

						SFileCloseFile( SubFile );
					}
				}

				if( !OverrodeBlizzardJ )
				{
					Val = Val ^ XORRotateLeft( (unsigned char *)BlizzardJ.c_str( ), BlizzardJ.size( ) );
					m_GHost->m_SHA->Update( (unsigned char *)BlizzardJ.c_str( ), BlizzardJ.size( ) );
				}

				Val = ROTL( Val, 3 );
				Val = ROTL( Val ^ 0x03F1379E, 3 );
				m_GHost->m_SHA->Update( (unsigned char *)"\x9E\x37\xF1\x03", 4 );

				if( MapMPQReady )
				{
					vector<string> FileList;
					FileList.push_back( "war3map.j" );
					FileList.push_back( "scripts\\war3map.j" );
					FileList.push_back( "war3map.w3e" );
					FileList.push_back( "war3map.wpm" );
					FileList.push_back( "war3map.doo" );
					FileList.push_back( "war3map.w3u" );
					FileList.push_back( "war3map.w3b" );
					FileList.push_back( "war3map.w3d" );
					FileList.push_back( "war3map.w3a" );
					FileList.push_back( "war3map.w3q" );
					bool FoundScript = false;

					for( vector<string> :: iterator i = FileList.begin( ); i != FileList.end( ); i++ )
					{
						// don't use scripts\war3map.j if we've already used war3map.j (yes, some maps have both but only war3map.j is used)

						if( FoundScript && *i == "scripts\\war3map.j" )
							continue;

						HANDLE SubFile;

						if( SFileOpenFileEx( MapMPQ, (*i).c_str( ), 0, &SubFile ) )
						{
							uint32_t FileLength = SFileGetFileSize( SubFile, NULL );

							if( FileLength > 0 && FileLength != 0xFFFFFFFF )
							{
								char *SubFileData = new char[FileLength];
								DWORD BytesRead = 0;

								if( SFileReadFile( SubFile, SubFileData, FileLength, &BytesRead ) )
								{
									if( *i == "war3map.j" || *i == "scripts\\war3map.j" )
										FoundScript = true;

									Val = ROTL( Val ^ XORRotateLeft( (unsigned char *)SubFileData, BytesRead ), 3 );
									m_GHost->m_SHA->Update( (unsigned char *)SubFileData, BytesRead );
									// DEBUG_Print( "*** found: " + *i );
								}

								delete [] SubFileData;
							}

							SFileCloseFile( SubFile );
						}
						else
						{
							// DEBUG_Print( "*** not found: " + *i );
						}
					}

					if( !FoundScript )
						CONSOLE_Print( "[MAP] couldn't find war3map.j or scripts\\war3map.j in MPQ file, calculated map_crc/sha1 is probably wrong" );

					MapCRC = UTIL_CreateByteArray( Val, false );
					CONSOLE_Print( "[MAP] calculated map_crc = " + UTIL_ByteArrayToDecString( MapCRC ) );

					m_GHost->m_SHA->Final( );
					unsigned char SHA1[20];
					memset( SHA1, 0, sizeof( unsigned char ) * 20 );
					m_GHost->m_SHA->GetHash( SHA1 );
					MapSHA1 = UTIL_CreateByteArray( SHA1, 20 );
					CONSOLE_Print( "[MAP] calculated map_sha1 = " + UTIL_ByteArrayToDecString( MapSHA1 ) );
				}
				else
					CONSOLE_Print( "[MAP] unable to calculate map_crc/sha1 - map MPQ file not loaded" );
			}
		}
	}
	else
		CONSOLE_Print( "[MAP] no map data available, using config file for map_size, map_info, map_crc, map_sha1" );

	// try to calculate map_width, map_height, map_slot<x>, map_numplayers, map_numteams

	uint32_t MapOptions = 0;
	BYTEARRAY MapWidth;
	BYTEARRAY MapHeight;
	uint32_t MapNumPlayers = 0;
	uint32_t MapNumTeams = 0;
	vector<CGameSlot> Slots;

	if( !m_MapData.empty( ) )
	{
		if( MapMPQReady )
		{
			HANDLE SubFile;

			if( SFileOpenFileEx( MapMPQ, "war3map.w3i", 0, &SubFile ) )
			{
				uint32_t FileLength = SFileGetFileSize( SubFile, NULL );

				if( FileLength > 0 && FileLength != 0xFFFFFFFF )
				{
					char *SubFileData = new char[FileLength];
					DWORD BytesRead = 0;

					if( SFileReadFile( SubFile, SubFileData, FileLength, &BytesRead ) )
					{
						istringstream ISS( string( SubFileData, BytesRead ) );

						// war3map.w3i format found at http://www.wc3campaigns.net/tools/specs/index.html by Zepir/PitzerMike

						string GarbageString;
						uint32_t FileFormat;
						uint32_t RawMapWidth;
						uint32_t RawMapHeight;
						uint32_t RawMapFlags;
						uint32_t RawMapNumPlayers;
						uint32_t RawMapNumTeams;

						ISS.read( (char *)&FileFormat, 4 );				// file format (18 = ROC, 25 = TFT)

						if( FileFormat == 18 || FileFormat == 25 )
						{
							ISS.seekg( 4, ios :: cur );					// number of saves
							ISS.seekg( 4, ios :: cur );					// editor version
							getline( ISS, GarbageString, '\0' );		// map name
							getline( ISS, GarbageString, '\0' );		// map author
							getline( ISS, GarbageString, '\0' );		// map description
							getline( ISS, GarbageString, '\0' );		// players recommended
							ISS.seekg( 32, ios :: cur );				// camera bounds
							ISS.seekg( 16, ios :: cur );				// camera bounds complements
							ISS.read( (char *)&RawMapWidth, 4 );		// map width
							ISS.read( (char *)&RawMapHeight, 4 );		// map height
							ISS.read( (char *)&RawMapFlags, 4 );		// flags
							ISS.seekg( 1, ios :: cur );					// map main ground type

							if( FileFormat == 18 )
								ISS.seekg( 4, ios :: cur );				// campaign background number
							else if( FileFormat == 25 )
							{
								ISS.seekg( 4, ios :: cur );				// loading screen background number
								getline( ISS, GarbageString, '\0' );	// path of custom loading screen model
							}

							getline( ISS, GarbageString, '\0' );		// map loading screen text
							getline( ISS, GarbageString, '\0' );		// map loading screen title
							getline( ISS, GarbageString, '\0' );		// map loading screen subtitle

							if( FileFormat == 18 )
								ISS.seekg( 4, ios :: cur );				// map loading screen number
							else if( FileFormat == 25 )
							{
								ISS.seekg( 4, ios :: cur );				// used game data set
								getline( ISS, GarbageString, '\0' );	// prologue screen path
							}

							getline( ISS, GarbageString, '\0' );		// prologue screen text
							getline( ISS, GarbageString, '\0' );		// prologue screen title
							getline( ISS, GarbageString, '\0' );		// prologue screen subtitle

							if( FileFormat == 25 )
							{
								ISS.seekg( 4, ios :: cur );				// uses terrain fog
								ISS.seekg( 4, ios :: cur );				// fog start z height
								ISS.seekg( 4, ios :: cur );				// fog end z height
								ISS.seekg( 4, ios :: cur );				// fog density
								ISS.seekg( 1, ios :: cur );				// fog red value
								ISS.seekg( 1, ios :: cur );				// fog green value
								ISS.seekg( 1, ios :: cur );				// fog blue value
								ISS.seekg( 1, ios :: cur );				// fog alpha value
								ISS.seekg( 4, ios :: cur );				// global weather id
								getline( ISS, GarbageString, '\0' );	// custom sound environment
								ISS.seekg( 1, ios :: cur );				// tileset id of the used custom light environment
								ISS.seekg( 1, ios :: cur );				// custom water tinting red value
								ISS.seekg( 1, ios :: cur );				// custom water tinting green value
								ISS.seekg( 1, ios :: cur );				// custom water tinting blue value
								ISS.seekg( 1, ios :: cur );				// custom water tinting alpha value
							}

							ISS.read( (char *)&RawMapNumPlayers, 4 );	// number of players
							uint32_t ClosedSlots = 0;

							for( uint32_t i = 0; i < RawMapNumPlayers; i++ )
							{
								CGameSlot Slot( 0, 255, SLOTSTATUS_OPEN, 0, 0, 1, SLOTRACE_RANDOM );
								uint32_t Colour;
								uint32_t Status;
								uint32_t Race;

								ISS.read( (char *)&Colour, 4 );			// colour
								Slot.SetColour( Colour );
								ISS.read( (char *)&Status, 4 );			// status

								if( Status == 1 )
									Slot.SetSlotStatus( SLOTSTATUS_OPEN );
								else if( Status == 2 )
								{
									Slot.SetSlotStatus( SLOTSTATUS_OCCUPIED );
									Slot.SetComputer( 1 );
									Slot.SetComputerType( SLOTCOMP_NORMAL );
								}
								else
								{
									Slot.SetSlotStatus( SLOTSTATUS_CLOSED );
									ClosedSlots++;
								}

								ISS.read( (char *)&Race, 4 );			// race

								if( Race == 1 )
									Slot.SetRace( SLOTRACE_HUMAN );
								else if( Race == 2 )
									Slot.SetRace( SLOTRACE_ORC );
								else if( Race == 3 )
									Slot.SetRace( SLOTRACE_UNDEAD );
								else if( Race == 4 )
									Slot.SetRace( SLOTRACE_NIGHTELF );
								else
									Slot.SetRace( SLOTRACE_RANDOM );

								ISS.seekg( 4, ios :: cur );				// fixed start position
								getline( ISS, GarbageString, '\0' );	// player name
								ISS.seekg( 4, ios :: cur );				// start position x
								ISS.seekg( 4, ios :: cur );				// start position y
								ISS.seekg( 4, ios :: cur );				// ally low priorities
								ISS.seekg( 4, ios :: cur );				// ally high priorities

								if( Slot.GetSlotStatus( ) != SLOTSTATUS_CLOSED )
									Slots.push_back( Slot );
							}

							ISS.read( (char *)&RawMapNumTeams, 4 );		// number of teams

							for( uint32_t i = 0; i < RawMapNumTeams; i++ )
							{
								uint32_t Flags;
								uint32_t PlayerMask;

								ISS.read( (char *)&Flags, 4 );			// flags
								ISS.read( (char *)&PlayerMask, 4 );		// player mask

								for( unsigned char j = 0; j < 12; j++ )
								{
									if( PlayerMask & 1 )
									{
										for( vector<CGameSlot> :: iterator k = Slots.begin( ); k != Slots.end( ); k++ )
										{
											if( (*k).GetColour( ) == j )
												(*k).SetTeam( i );
										}
									}

									PlayerMask >>= 1;
								}

								getline( ISS, GarbageString, '\0' );	// team name
							}

							// the bot only cares about the following options: melee, fixed player settings, custom forces
							// let's not confuse the user by displaying erroneous map options so zero them out now

							MapOptions = RawMapFlags & ( MAPOPT_MELEE | MAPOPT_FIXEDPLAYERSETTINGS | MAPOPT_CUSTOMFORCES );
							CONSOLE_Print( "[MAP] calculated map_options = " + UTIL_ToString( MapOptions ) );
							MapWidth = UTIL_CreateByteArray( (uint16_t)RawMapWidth, false );
							CONSOLE_Print( "[MAP] calculated map_width = " + UTIL_ByteArrayToDecString( MapWidth ) );
							MapHeight = UTIL_CreateByteArray( (uint16_t)RawMapHeight, false );
							CONSOLE_Print( "[MAP] calculated map_height = " + UTIL_ByteArrayToDecString( MapHeight ) );
							MapNumPlayers = RawMapNumPlayers - ClosedSlots;
							CONSOLE_Print( "[MAP] calculated map_numplayers = " + UTIL_ToString( MapNumPlayers ) );
							MapNumTeams = RawMapNumTeams;
							CONSOLE_Print( "[MAP] calculated map_numteams = " + UTIL_ToString( MapNumTeams ) );

							uint32_t SlotNum = 1;

							for( vector<CGameSlot> :: iterator i = Slots.begin( ); i != Slots.end( ); i++ )
							{
								CONSOLE_Print( "[MAP] calculated map_slot" + UTIL_ToString( SlotNum ) + " = " + UTIL_ByteArrayToDecString( (*i).GetByteArray( ) ) );
								SlotNum++;
							}

							if( MapOptions & MAPOPT_MELEE )
							{
								CONSOLE_Print( "[MAP] found melee map, initializing slots" );

								// give each slot a different team and set the race to random

								unsigned char Team = 0;

								for( vector<CGameSlot> :: iterator i = Slots.begin( ); i != Slots.end( ); i++ )
								{
									(*i).SetTeam( Team++ );
									(*i).SetRace( SLOTRACE_RANDOM );
								}
							}

							if( !( MapOptions & MAPOPT_FIXEDPLAYERSETTINGS ) )
							{
								// make races selectable

								for( vector<CGameSlot> :: iterator i = Slots.begin( ); i != Slots.end( ); i++ )
									(*i).SetRace( (*i).GetRace( ) | SLOTRACE_SELECTABLE );
							}
						}
					}
					else
Beispiel #15
0
string CGHostDBMySQL :: GetStatus( )
{
	return "DB STATUS --- Connections: " + UTIL_ToString( m_IdleConnections.size( ) ) + "/" + UTIL_ToString( m_NumConnections ) + " idle. Outstanding callables: " + UTIL_ToString( m_OutstandingCallables ) + ".";
}
Beispiel #16
0
uint32_t MySQLDotAPlayerAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, uint32_t colour, uint32_t kills, uint32_t deaths, uint32_t creepkills, uint32_t creepdenies, uint32_t assists, uint32_t gold, uint32_t neutralkills, string item1, string item2, string item3, string item4, string item5, string item6, string hero, uint32_t newcolour, uint32_t towerkills, uint32_t raxkills, uint32_t courierkills )
{
	uint32_t RowID = 0;
	string EscItem1 = MySQLEscapeString( conn, item1 );
	string EscItem2 = MySQLEscapeString( conn, item2 );
	string EscItem3 = MySQLEscapeString( conn, item3 );
	string EscItem4 = MySQLEscapeString( conn, item4 );
	string EscItem5 = MySQLEscapeString( conn, item5 );
	string EscItem6 = MySQLEscapeString( conn, item6 );
	string EscHero = MySQLEscapeString( conn, hero );
	string Query = "INSERT INTO dotaplayers ( botid, gameid, colour, kills, deaths, creepkills, creepdenies, assists, gold, neutralkills, item1, item2, item3, item4, item5, item6, hero, newcolour, towerkills, raxkills, courierkills ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( colour ) + ", " + UTIL_ToString( kills ) + ", " + UTIL_ToString( deaths ) + ", " + UTIL_ToString( creepkills ) + ", " + UTIL_ToString( creepdenies ) + ", " + UTIL_ToString( assists ) + ", " + UTIL_ToString( gold ) + ", " + UTIL_ToString( neutralkills ) + ", '" + EscItem1 + "', '" + EscItem2 + "', '" + EscItem3 + "', '" + EscItem4 + "', '" + EscItem5 + "', '" + EscItem6 + "', '" + EscHero + "', " + UTIL_ToString( newcolour ) + ", " + UTIL_ToString( towerkills ) + ", " + UTIL_ToString( raxkills ) + ", " + UTIL_ToString( courierkills ) + " )";

	if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 )
		*error = mysql_error( (MYSQL *)conn );
	else
		RowID = mysql_insert_id( (MYSQL *)conn );

	return RowID;
}
Beispiel #17
0
uint32_t MySQLDotAGameAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec )
{
	uint32_t RowID = 0;
	string Query = "INSERT INTO dotagames ( botid, gameid, winner, min, sec ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", " + UTIL_ToString( winner ) + ", " + UTIL_ToString( min ) + ", " + UTIL_ToString( sec ) + " )";

	if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 )
		*error = mysql_error( (MYSQL *)conn );
	else
		RowID = mysql_insert_id( (MYSQL *)conn );

	return RowID;
}
Beispiel #18
0
uint32_t MySQLGamePlayerAdd( void *conn, string *error, uint32_t botid, uint32_t gameid, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t reserved, uint32_t loadingtime, uint32_t left, string leftreason, uint32_t team, uint32_t colour )
{
	transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower );
	uint32_t RowID = 0;
	string EscName = MySQLEscapeString( conn, name );
	string EscIP = MySQLEscapeString( conn, ip );
	string EscSpoofedRealm = MySQLEscapeString( conn, spoofedrealm );
	string EscLeftReason = MySQLEscapeString( conn, leftreason );
	string Query = "INSERT INTO gameplayers ( botid, gameid, name, ip, spoofed, reserved, loadingtime, `left`, leftreason, team, colour, spoofedrealm ) VALUES ( " + UTIL_ToString( botid ) + ", " + UTIL_ToString( gameid ) + ", '" + EscName + "', '" + EscIP + "', " + UTIL_ToString( spoofed ) + ", " + UTIL_ToString( reserved ) + ", " + UTIL_ToString( loadingtime ) + ", " + UTIL_ToString( left ) + ", '" + EscLeftReason + "', " + UTIL_ToString( team ) + ", " + UTIL_ToString( colour ) + ", '" + EscSpoofedRealm + "' )";

	if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 )
		*error = mysql_error( (MYSQL *)conn );
	else
		RowID = mysql_insert_id( (MYSQL *)conn );

	return RowID;
}
Beispiel #19
0
uint32_t MySQLGameAdd( void *conn, string *error, uint32_t botid, string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver )
{
	uint32_t RowID = 0;
	string EscServer = MySQLEscapeString( conn, server );
	string EscMap = MySQLEscapeString( conn, map );
	string EscGameName = MySQLEscapeString( conn, gamename );
	string EscOwnerName = MySQLEscapeString( conn, ownername );
	string EscCreatorName = MySQLEscapeString( conn, creatorname );
	string EscCreatorServer = MySQLEscapeString( conn, creatorserver );
	string Query = "INSERT INTO games ( botid, server, map, datetime, gamename, ownername, duration, gamestate, creatorname, creatorserver ) VALUES ( " + UTIL_ToString( botid ) + ", '" + EscServer + "', '" + EscMap + "', NOW( ), '" + EscGameName + "', '" + EscOwnerName + "', " + UTIL_ToString( duration ) + ", " + UTIL_ToString( gamestate ) + ", '" + EscCreatorName + "', '" + EscCreatorServer + "' )";

	if( mysql_real_query( (MYSQL *)conn, Query.c_str( ), Query.size( ) ) != 0 )
		*error = mysql_error( (MYSQL *)conn );
	else
		RowID = mysql_insert_id( (MYSQL *)conn );

	return RowID;
}
Beispiel #20
0
void CCCBot :: UpdateCommandAccess( )
{
	// load default access values and insert them into database if a access number hasn't already been set
	// format: m_Commands["<command keyword>"] = <value> (must be equal or higher than 0 and lower than 10)
	
	m_Commands[ "accept"]			= 9;
	m_Commands[ "access"]			= 0;
	m_Commands[ "addsafelist" ]		= 6;
	m_Commands[ "announce" ]		= 6;
	m_Commands[ "ban" ]			= 7;
	m_Commands[ "chanlist" ]		= 3;
	m_Commands[ "channel" ]			= 5;
	m_Commands[ "checkaccess" ]		= 5;
	m_Commands[ "checkban" ]		= 3;
	m_Commands[ "checksafelist" ]		= 5;
	m_Commands[ "chieftain" ]		= 9;
	m_Commands[ "clanlist" ]		= 1;
	m_Commands[ "clearqueue" ]		= 3;
	m_Commands[ "command" ]			= 7;
	m_Commands[ "countaccess" ]		= 7;
	m_Commands[ "countbans" ]		= 5;
	m_Commands[ "countsafelist" ]		= 5;
	m_Commands[ "delaccess" ]		= 8;
	m_Commands[ "delsafelist" ]		= 6;
	m_Commands[ "exit" ]			= 9;
	m_Commands[ "games" ]			= 4;
	m_Commands[ "getclan" ]			= 2;
	m_Commands[ "gn8" ]			= 1;
	m_Commands[ "greet" ]			= 6;
	m_Commands[ "grunt" ]			= 7;
	m_Commands[ "invite" ]			= 2;
	m_Commands[ "kick" ]			= 5;
	m_Commands[ "lockdown" ]		= 8;
	m_Commands[ "motd" ]			= 5;
	m_Commands[ "online" ]			= 1;
	m_Commands[ "peon" ]			= 7;
	m_Commands[ "ping" ]			= 0;
	m_Commands[ "rejoin" ]			= 4;
	m_Commands[ "restart" ]			= 9;
	m_Commands[ "remove" ]			= 9;
	m_Commands[ "reload" ]			= 4;
	m_Commands[ "say" ]			= 6;
	m_Commands[ "setaccess" ]		= 8;
	m_Commands[ "setcommand" ]		= 9;
	m_Commands[ "shaman" ]			= 9;
	m_Commands[ "slap" ]			= 0;
	m_Commands[ "spit" ]			= 0;
	m_Commands[ "status" ]			= 2;
	m_Commands[ "squelch" ]			= 5;
	m_Commands[ "topic" ]			= 5;
	m_Commands[ "unban" ]			= 7;
	m_Commands[ "uptime" ]			= 1;	

	for( map<string, unsigned char> :: iterator i = m_Commands.begin( ); i != m_Commands.end( ); ++i )
	{
		if( m_DB->CommandAccess( i->first ) == 255 )
		{
			m_DB->CommandSetAccess( i->first, i->second );
			CONSOLE_Print( "[ACCESS] no value found for command [" + i->first + "] - setting default value of [" + UTIL_ToString( i->second ) + "]" );
		}
	}
}
Beispiel #21
0
void CReplay :: BuildReplay( string gameName, string statString, uint32_t war3Version, uint16_t buildNumber )
{
	m_War3Version = war3Version;
	m_BuildNumber = buildNumber;
	m_Flags = 32768;

	CONSOLE_Print( "[REPLAY] building replay" );

	uint32_t LanguageID = 0x0012F8B0;

	BYTEARRAY Replay;
	Replay.push_back( 16 );															// Unknown (4.0)
	Replay.push_back( 1 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Unknown (4.0)
	Replay.push_back( 0 );															// Host RecordID (4.1)
	Replay.push_back( m_HostPID );													// Host PlayerID (4.1)
	UTIL_AppendByteArrayFast( Replay, m_HostName );									// Host PlayerName (4.1)
	Replay.push_back( 1 );															// Host AdditionalSize (4.1)
	Replay.push_back( 0 );															// Host AdditionalData (4.1)
	UTIL_AppendByteArrayFast( Replay, gameName );									// GameName (4.2)
	Replay.push_back( 0 );															// Null (4.0)
	UTIL_AppendByteArrayFast( Replay, statString );									// StatString (4.3)
	UTIL_AppendByteArray( Replay, (uint32_t)m_Slots.size( ), false );				// PlayerCount (4.6)
	Replay.push_back( m_MapGameType );												// GameType (4.7)
	Replay.push_back( 32 );															// GameType (4.7)
	Replay.push_back( 73 );															// GameType (4.7)
	Replay.push_back( 0 );															// GameType (4.7)
	UTIL_AppendByteArray( Replay, LanguageID, false );								// LanguageID (4.8)

	// PlayerList (4.9)

	for( vector<PIDPlayer> :: iterator i = m_Players.begin( ); i != m_Players.end( ); i++ )
	{
		if( (*i).first != m_HostPID )
		{
			Replay.push_back( 22 );													// Player RecordID (4.1)
			Replay.push_back( (*i).first );											// Player PlayerID (4.1)
			UTIL_AppendByteArrayFast( Replay, (*i).second );						// Player PlayerName (4.1)
			Replay.push_back( 1 );													// Player AdditionalSize (4.1)
			Replay.push_back( 0 );													// Player AdditionalData (4.1)
			UTIL_AppendByteArray( Replay, (uint32_t)0, false );						// Unknown
		}
	}

	// GameStartRecord (4.10)

	Replay.push_back( 25 );															// RecordID (4.10)
	UTIL_AppendByteArray( Replay, (uint16_t)( 7 + m_Slots.size( ) * 9 ), false );	// Size (4.10)
	Replay.push_back( m_Slots.size( ) );											// NumSlots (4.10)

	for( unsigned char i = 0; i < m_Slots.size( ); i++ )
		UTIL_AppendByteArray( Replay, m_Slots[i].GetByteArray( ) );

	UTIL_AppendByteArray( Replay, m_RandomSeed, false );							// RandomSeed (4.10)
	Replay.push_back( m_SelectMode );												// SelectMode (4.10)
	Replay.push_back( m_StartSpotCount );											// StartSpotCount (4.10)

	// ReplayData (5.0)

	Replay.push_back( REPLAY_FIRSTSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );
	Replay.push_back( REPLAY_SECONDSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );

	// leavers during loading need to be stored between the second and third start blocks

	while( !m_LoadingBlocks.empty( ) )
	{
		UTIL_AppendByteArray( Replay, m_LoadingBlocks.front( ) );
		m_LoadingBlocks.pop( );
	}

	Replay.push_back( REPLAY_THIRDSTARTBLOCK );
	UTIL_AppendByteArray( Replay, (uint32_t)1, false );

	// initialize replay length to zero
	// we'll accumulate the replay length as we iterate through the timeslots
	// this is necessary because we might be discarding some timeslots due to not enough checksums and the replay length needs to be accurate

	m_ReplayLength = 0;
	uint32_t TimeSlotsDiscarded = 0;
	bool EndOfTimeSlots = false;

	while( !m_Blocks.empty( ) )
	{
		BYTEARRAY Block = m_Blocks.front( );
		m_Blocks.pop( );

		if( Block.size( ) >= 5 && Block[0] == REPLAY_TIMESLOT )
		{
			uint16_t TimeIncrement = UTIL_ByteArrayToUInt16( Block, false, 3 );

			if( TimeIncrement != 0 && m_CheckSums.empty( ) )
				EndOfTimeSlots = true;

			if( EndOfTimeSlots )
			{
				TimeSlotsDiscarded++;
				continue;
			}

			// append timeslot

			UTIL_AppendByteArrayFast( Replay, Block );

			// append checksum
			// todotodo: after experimenting, Strilanc discovered that checksums are NOT required in replays
			// we could optimize saving of replays by building a complete stream without waiting for checksums as the game progresses
			// alternatively, we could build that stream as the checksums were added if we wanted to keep them
			// rather than building it in one go right now, which might take a few hundred ms and cause a spike in other games

			if( TimeIncrement != 0 )
			{
				BYTEARRAY CheckSum;
				CheckSum.reserve( 6 );
				CheckSum.push_back( REPLAY_CHECKSUM );
				CheckSum.push_back( 4 );
				UTIL_AppendByteArray( CheckSum, m_CheckSums.front( ), false );
				m_CheckSums.pop( );
				UTIL_AppendByteArrayFast( Replay, CheckSum );
			}

			// accumulate replay length

			m_ReplayLength += TimeIncrement;
		}
		else
			UTIL_AppendByteArrayFast( Replay, Block );
	}

	if( TimeSlotsDiscarded > 0 )
		CONSOLE_Print( "[REPLAY] ran out of checksums, discarded " + UTIL_ToString( TimeSlotsDiscarded ) + " timeslots" );

	// done

	m_Decompressed = string( Replay.begin( ), Replay.end( ) );
}
Beispiel #22
0
bool CIRC :: Update( void *fd, void *send_fd )
{
	uint32_t Time = GetTime( );

	if( m_Socket->GetConnected( ) )
	{
		// the socket is connected and everything appears to be working properly

		if( Time - m_LastPacketTime > 210 )
		{
			Print( "[IRC: " + m_Server + "] ping timeout,  reconnecting" );
			m_Socket->Reset( );
			m_WaitingToConnect = true;
			return m_Exiting;
		}

		if( Time - m_LastAntiIdleTime > 60 )
		{
			SendIRC( "TIME" );
			m_LastAntiIdleTime = Time;
		}

		m_Socket->DoRecv( (fd_set *)fd );
		ExtractPackets( );
		m_Socket->DoSend( (fd_set *)send_fd );
		return m_Exiting;
	}

	if( m_Socket->HasError( ) )
	{
		// the socket has an error

		Print( "[IRC: " + m_Server + "] disconnected due to socket error,  waiting 60 seconds to reconnect" );
		m_Socket->Reset( );
		m_WaitingToConnect = true;
		m_LastConnectionAttemptTime = Time;
		return m_Exiting;
	}

	if( !m_Socket->GetConnecting( ) && !m_Socket->GetConnected( ) && !m_WaitingToConnect )
	{
		// the socket was disconnected

		Print( "[IRC: " + m_Server + "] disconnected, waiting 60 seconds to reconnect" );
		m_Socket->Reset( );
		m_WaitingToConnect = true;
		m_LastConnectionAttemptTime = Time;
		return m_Exiting;
	}

	if( m_Socket->GetConnecting( ) )
	{
		// we are currently attempting to connect to irc

		if( m_Socket->CheckConnect( ) )
		{
			// the connection attempt completed

                        if( !m_OriginalNick )
				m_Nickname = m_NicknameCpy;

			SendIRC( "NICK " + m_Nickname );
			SendIRC( "USER " + m_Username + " " +  m_Nickname + " " + m_Username + " :by h4x0rz88" );

			m_Socket->DoSend( (fd_set *)send_fd );

			Print( "[IRC: " + m_Server + "] connected" );

			m_LastPacketTime = Time;
			
			return m_Exiting;
		}
		else if( Time - m_LastConnectionAttemptTime > 15 )
		{
			// the connection attempt timed out (15 seconds)

			Print( "[IRC: " + m_Server + "] connect timed out, waiting 60 seconds to reconnect" );
			m_Socket->Reset( );
			m_LastConnectionAttemptTime = Time;
			m_WaitingToConnect = true;
			return m_Exiting;
		}
	}

	if( !m_Socket->GetConnecting( ) && !m_Socket->GetConnected( ) && ( Time - m_LastConnectionAttemptTime > 60 ) )
	{
		// attempt to connect to irc

		Print( "[IRC: " + m_Server + "] connecting to server [" + m_Server + "] on port " + UTIL_ToString( m_Port ) );

		if( m_ServerIP.empty( ) )
		{
			m_Socket->Connect( string( ), m_Server, m_Port );

			if( !m_Socket->HasError( ) )
			{
				m_ServerIP = m_Socket->GetIPString( );
			}
		}
		else
		{
			// use cached server IP address since resolving takes time and is blocking

			m_Socket->Connect( string( ), m_ServerIP, m_Port );
		}

		m_WaitingToConnect = false;
		m_LastConnectionAttemptTime = Time;
	}

	return m_Exiting;
}
string CPotentialPlayer :: GetExternalIPString( )
{
	BYTEARRAY IP;
	string EIP;
	if( m_Socket )
	{
		if( m_IncomingGarenaUser != NULL ) 
		{
			BYTEARRAY GarenaIP = GetGarenaIP( );
			return UTIL_ToString(GarenaIP[0]) + "." + UTIL_ToString(GarenaIP[1]) + "." + UTIL_ToString(GarenaIP[2]) + "." + UTIL_ToString(GarenaIP[3]);
		} else {	
			bool local=m_LAN;
			if (!m_LANSet)
			{				
				IP=	m_Socket->GetIP( );
				if (IP.size()>=2)
				{
					if (IP[0]==10)
					local=true;
					else if (IP[0]==192 && IP[1]==168)
					local=true;
					else if (IP[0]==169 && IP[1]==254)
					local=true;
					else if (IP[0]==172 && IP[1]==16)
					local=true;
					else if (IP[0]==172 && IP[1]==17)
					local=true;
					else if (IP[0]==172 && IP[1]==18)
					local=true;
					else if (IP[0]==172 && IP[1]==19)
					local=true;
					else if (IP[0]==172 && IP[1]==20)
					local=true;
					else if (IP[0]==172 && IP[1]==21)
					local=true;
					else if (IP[0]==172 && IP[1]==22)
					local=true;
					else if (IP[0]==172 && IP[1]==23)
					local=true;
					else if (IP[0]==172 && IP[1]==24)
					local=true;
					else if (IP[0]==172 && IP[1]==25)
					local=true;
					else if (IP[0]==172 && IP[1]==26)
					local=true;
					else if (IP[0]==172 && IP[1]==27)
					local=true;
					else if (IP[0]==172 && IP[1]==28)
					local=true;
					else if (IP[0]==172 && IP[1]==29)
					local=true;
					else if (IP[0]==172 && IP[1]==30)
					local=true;
					else if (IP[0]==172 && IP[1]==31)
					local=true;
				}
				if (UTIL_IsLocalIP(IP, m_Game->m_GHost->m_LocalAddresses))
					local = true;
				m_LANSet = true;
				m_LAN = local;
			}
			EIP=m_Socket->GetIPString( );
			if (local && m_Game->m_GHost->m_ExternalIP!="")
			{
			EIP=m_Game->m_GHost->m_ExternalIP;
			}
			if( !EIP.empty( ) && EIP != "0.0.0.0" )
				return EIP;
			else
				return m_CachedIP;
		}
	}
	return m_CachedIP;
}
Beispiel #24
0
void CSaveGame :: ParseSaveGame( )
{
	m_MapPath.clear( );
	m_Slots.clear( );
	m_MagicNumber.clear( );

	istringstream ISS( m_Decompressed );

	// savegame format figured out by Varlock:
	// string		-> map path
	// 0 (string?)	-> ??? (no idea what this is)
	// string		-> original game name
	// 0 (string?)	-> ??? (maybe original game password)
	// string		-> stat string
	// 4 bytes		-> ??? (seems to be # of slots)
	// 4 bytes		-> ??? (seems to be 0x01 0x28 0x49 0x00 on both of the savegames examined)
	// 2 bytes		-> ??? (no idea what this is)
	// slot structure
	// 4 bytes		-> magic number

	string GarbageString;
	unsigned char NumSlots;
	uint32_t MagicNumber;

	getline( ISS, m_MapPath, '\0' );		// map path
	getline( ISS, GarbageString, '\0' );	// ???
	getline( ISS, GarbageString, '\0' );	// original game name
	getline( ISS, GarbageString, '\0' );	// ???
	getline( ISS, GarbageString, '\0' );	// stat string
	ISS.seekg( 4, ios :: cur );				// ???
	ISS.seekg( 4, ios :: cur );				// ???
	ISS.seekg( 2, ios :: cur );				// ???
	ISS.read( (char *)&NumSlots, 1 );		// number of slots

	if( NumSlots > 12 )
	{
		CONSOLE_Print( "[SAVEGAME] too many slots in decompressed data" );
		m_Valid = false;
		return;
	}

	CONSOLE_Print( "[SAVEGAME] found " + UTIL_ToString( NumSlots ) + " slots" );

	for( unsigned char i = 0; i < NumSlots; i++ )
	{
		unsigned char SlotData[9];
		ISS.read( (char *)SlotData, 9 );	// slot data
		m_Slots.push_back( CGameSlot( SlotData[0], SlotData[1], SlotData[2], SlotData[3], SlotData[4], SlotData[5], SlotData[6], SlotData[7], SlotData[8] ) );
	}

	ISS.seekg( 4, ios :: cur );				// GetTicks
	ISS.seekg( 1, ios :: cur );				// GameType
	ISS.seekg( 1, ios :: cur );				// number of player slots (non observer)
	ISS.read( (char *)&MagicNumber, 4 );	// magic number

	if( ISS.fail( ) )
	{
		CONSOLE_Print( "[SAVEGAME] failed to parse decompressed data" );
		m_Valid = false;
		return;
	}

	m_MagicNumber = UTIL_CreateByteArray( MagicNumber, false );
	CONSOLE_Print( "[SAVEGAME] found map path [" + m_MapPath + "]" );
	CONSOLE_Print( "[SAVEGAME] found magic number [" + UTIL_ToString( m_MagicNumber[0] ) + " " + UTIL_ToString( m_MagicNumber[1] ) + " " + UTIL_ToString( m_MagicNumber[2] ) + " " + UTIL_ToString( m_MagicNumber[3] ) + "]" );
}
Beispiel #25
0
void CGHostGenie :: LoadIPToCountryData( string file )
{
	ifstream in;
	in.open( file.c_str( ) );
	
	if( in.fail( ) )
		LogWarning( "[GHOST] warning - unable to read file [" + file + "], iptocountry data not loaded" );
	else
	{
		LogInfo( "[GHOST] started loading [" + file + "]" );
		
		// the begin and commit statements are optimizations
		// we're about to insert ~4 MB of data into the database so if we allow the database to treat each insert as a transaction it will take a LONG time
		// todotodo: handle begin/commit failures a bit more gracefully
		
		if( !m_DBLocal->Begin( ) )
			LogWarning( "[GHOST] warning - failed to begin local database transaction, iptocountry data not loaded" );
		else
		{
			unsigned char Percent = 0;
			string Line;
			string IP1;
			string IP2;
			string Country;
			CSVParser parser;
			
			// get length of file for the progress meter
			
			in.seekg( 0, ios :: end );
			uint32_t FileLength = in.tellg( );
			in.seekg( 0, ios :: beg );
			
			while( !in.eof( ) )
			{
				getline( in, Line );
				
				if( Line.empty( ) )
					continue;
				
				parser << Line;
				parser >> IP1;
				parser >> IP2;
				parser >> Country;
				m_DBLocal->FromAdd( UTIL_ToUInt32( IP1 ), UTIL_ToUInt32( IP2 ), Country );
				
				// it's probably going to take awhile to load the iptocountry data (~10 seconds on my 3.2 GHz P4 when using SQLite3)
				// so let's print a progress meter just to keep the user from getting worried
				
				unsigned char NewPercent = (unsigned char)( (float)in.tellg( ) / FileLength * 100 );
				
				if( NewPercent != Percent )
				{
					if( NewPercent % 10 == 0 )
						LogInfo( "[GHOST] iptocountry data: " + UTIL_ToString( NewPercent ) + "% loaded" );
					Percent = NewPercent;
					if( ip2countryCallback )
						ip2countryCallback( callbackObject, NewPercent );
				}
			}
			
			if( !m_DBLocal->Commit( ) )
				LogWarning( "[GHOST] warning - failed to commit local database transaction, iptocountry data not loaded" );
			else
				LogInfo( "[GHOST] finished loading [ip-to-country.csv]" );
		}
		
		in.close( );
	}
}