Date: Mon, 16 Mar 2009 12:42:08 GMT From: Dmitry Yashin <yashin.dm@gmail.com> To: freebsd-gnats-submit@FreeBSD.org Subject: ports/132691: New port Message-ID: <200903161242.n2GCg8BL083024@www.freebsd.org> Resent-Message-ID: <200903161250.n2GCo1c1078176@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 132691 >Category: ports >Synopsis: New port >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: update >Submitter-Id: current-users >Arrival-Date: Mon Mar 16 12:50:01 UTC 2009 >Closed-Date: >Last-Modified: >Originator: Dmitry Yashin >Release: FreeBSD 7.0-RELEASE >Organization: >Environment: FreeBSD python.rosnet.ru 7.0-RELEASE FreeBSD 7.0-RELEASE #0: Sun Feb 24 19:59:52 UTC 2008 root@logan.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386 >Description: GHost++ is a Warcraft 3 game hosting bot. Some features include: * run on Windows and Linux * connect to official battle.net and PVPGN realms * connect to multiple realms at the same time * host battle.net games and LAN games * host battle.net games across realms (players from different realms can play in the same game) * auto refresh games on battle.net * auto host and start games without admin interaction * can be controlled via LAN (you only need one set of CD keys) * host multiple games at the same time * host melee maps and custom maps * high speed map downloads (with adjustable maximum download speed) * host saved games * record complete replays of hosted games (including allied and private chat from all players) * determine player pings and countries of origin * player bans * player statistics * kick players from games * adjustable game latency * adjustable lag screen * mute global chat in games * mute individual players in lobbies and games * and much more... >How-To-Repeat: >Fix: Patch attached with submission follows: # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # /root/free/ # /root/free/files # /root/free/files/patch-StormPortLinux.cpp # /root/free/files/patch-bncsutil_makefile # /root/free/files/patch-ghostdb.h # /root/free/files/patch-ghost.cpp # /root/free/files/patch-ghostdbmysql.cpp # /root/free/files/patch-ghostdbmysql.h # /root/free/files/patch-ghost.cfg # /root/free/files/patch-ghost_makefile # /root/free/Makefile # /root/free/distinfo # /root/free/pkg-descr # /root/free/pkg-plist # echo c - /root/free/ mkdir -p /root/free/ > /dev/null 2>&1 echo c - /root/free/files mkdir -p /root/free/files > /dev/null 2>&1 echo x - /root/free/files/patch-StormPortLinux.cpp sed 's/^X//' >/root/free/files/patch-StormPortLinux.cpp << 'END-of-/root/free/files/patch-StormPortLinux.cpp' X*** StormLib/stormlib/StormPortLinux.cpp.orig Fri Mar 13 21:34:36 2009 X--- StormLib/stormlib/StormPortLinux.cpp Fri Mar 13 21:36:36 2009 X*************** X*** 24,29 **** X--- 24,30 ---- X * X ********************************************************************/ X X+ #define O_LARGEFILE 0100000 X #ifndef _WIN32 X #include "StormPort.h" X X*************** X*** 104,111 **** X return 0xffffffff; X } X X! struct stat64 fileinfo; X! fstat64((intptr_t)hFile, &fileinfo); X X // Fix by Ladik: If "ulOffSetHigh" is not NULL, it needs to be set X // to higher 32 bits of a file size. X--- 105,112 ---- X return 0xffffffff; X } X X! struct stat fileinfo; X! fstat((intptr_t)hFile, &fileinfo); X X // Fix by Ladik: If "ulOffSetHigh" is not NULL, it needs to be set X // to higher 32 bits of a file size. X*************** X*** 118,129 **** X X DWORD SetFilePointer(HANDLE hFile, LONG lOffSetLow, LONG *pOffSetHigh, DWORD ulMethod) X { X! off64_t nFileOffset = (DWORD)lOffSetLow; X X if(pOffSetHigh != NULL) X! nFileOffset |= (*(off64_t *)pOffSetHigh) << 32; X X! return lseek64((intptr_t)hFile, nFileOffset, ulMethod); X } X X BOOL SetEndOfFile(HANDLE hFile) X--- 119,130 ---- X X DWORD SetFilePointer(HANDLE hFile, LONG lOffSetLow, LONG *pOffSetHigh, DWORD ulMethod) X { X! off_t nFileOffset = (DWORD)lOffSetLow; X X if(pOffSetHigh != NULL) X! nFileOffset |= (*(off_t *)pOffSetHigh) << 32; X X! return lseek((intptr_t)hFile, nFileOffset, ulMethod); X } X X BOOL SetEndOfFile(HANDLE hFile) END-of-/root/free/files/patch-StormPortLinux.cpp echo x - /root/free/files/patch-bncsutil_makefile sed 's/^X//' >/root/free/files/patch-bncsutil_makefile << 'END-of-/root/free/files/patch-bncsutil_makefile' X*** bncsutil/src/bncsutil/Makefile.orig Fri Mar 13 21:21:48 2009 X--- bncsutil/src/bncsutil/Makefile Fri Mar 13 21:22:27 2009 X*************** X*** 6,12 **** X CCFLAGS = -Wall -O3 -I ../ -Wno-multichar -fPIC X CCOBJ = nls.o pe.o sha1.o stack.o X X! LDFLAGS = -shared -lgmp X X TARGET = libbncsutil.so X X--- 6,12 ---- X CCFLAGS = -Wall -O3 -I ../ -Wno-multichar -fPIC X CCOBJ = nls.o pe.o sha1.o stack.o X X! LDFLAGS = -shared -lgmp -L/usr/local/lib X X TARGET = libbncsutil.so X END-of-/root/free/files/patch-bncsutil_makefile echo x - /root/free/files/patch-ghostdb.h sed 's/^X//' >/root/free/files/patch-ghostdb.h << 'END-of-/root/free/files/patch-ghostdb.h' X*** ghost/ghostdb.h.orig Fri Mar 13 22:01:25 2009 X--- ghost/ghostdb.h Fri Mar 13 22:04:39 2009 X*************** X*** 66,71 **** X--- 66,73 ---- X virtual string FromCheck( uint32_t ip ); X virtual bool FromAdd( uint32_t ip1, uint32_t ip2, string country ); X virtual bool DownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ); X+ virtual bool LoadIPData( ) { return true; } X+ virtual void Update( ) { } X }; X X // END-of-/root/free/files/patch-ghostdb.h echo x - /root/free/files/patch-ghost.cpp sed 's/^X//' >/root/free/files/patch-ghost.cpp << 'END-of-/root/free/files/patch-ghost.cpp' X*** ghost/ghost.cpp.orig Fri Mar 13 21:49:45 2009 X--- ghost/ghost.cpp Fri Mar 13 21:57:53 2009 X*************** X*** 27,32 **** X--- 27,33 ---- X #include "socket.h" X #include "ghostdb.h" X #include "ghostdbsqlite.h" X+ #include "ghostdbmysql.h" X #include "bnet.h" X #include "map.h" X #include "packed.h" X*************** X*** 249,258 **** X m_CRC = new CCRC32( ); X m_CRC->Initialize( ); X m_CurrentGame = NULL; X! m_DB = new CGHostDBSQLite( CFG ); X m_Exiting = false; X m_Enabled = true; X! m_Version = "11.5"; X m_HostCounter = 1; X m_AutoHostMaximumGames = 0; X m_AutoHostAutoStartPlayers = 0; X--- 250,262 ---- X m_CRC = new CCRC32( ); X m_CRC->Initialize( ); X m_CurrentGame = NULL; X! if( CFG->GetString( "db_type", "sqlite3" ) == "mysql" ) X! m_DB = new CGHostDBMySQL( CFG ); X! else X! m_DB = new CGHostDBSQLite( CFG ); X m_Exiting = false; X m_Enabled = true; X! m_Version = "11.5 MySQL (FreeBSD)"; X m_HostCounter = 1; X m_AutoHostMaximumGames = 0; X m_AutoHostAutoStartPlayers = 0; X*************** X*** 397,403 **** X X // load the iptocountry data X X! LoadIPToCountryData( ); X X // create the admin game X X--- 401,411 ---- X X // load the iptocountry data X X! // We must check if the DB has an error, if it does calling LoadIPData( ) X! // using MySQL will crash as the connection object does not exist. X! if( !m_DB->HasError( ) ) X! if( m_DB->LoadIPData( ) ) X! LoadIPToCountryData( ); X X // create the admin game X X*************** X*** 449,454 **** X--- 457,465 ---- X return true; X } X X+ if( m_DB ) X+ m_DB->Update( ); X+ X unsigned int NumFDs = 0; X X // take every socket we own and throw it in one giant select statement so we can block on all sockets END-of-/root/free/files/patch-ghost.cpp echo x - /root/free/files/patch-ghostdbmysql.cpp sed 's/^X//' >/root/free/files/patch-ghostdbmysql.cpp << 'END-of-/root/free/files/patch-ghostdbmysql.cpp' X*** ghost/ghostdbmysql.cpp.orig Fri Mar 13 22:23:01 2009 X--- ghost/ghostdbmysql.cpp Fri Feb 13 16:08:00 2009 X*************** X*** 0 **** X--- 1,841 ---- X+ /* X+ X+ Copyright 2009 Scott Gillespie X+ X+ Licensed under the Apache License, Version 2.0 (the "License"); X+ you may not use this file except in compliance with the License. X+ You may obtain a copy of the License at X+ X+ http://www.apache.org/licenses/LICENSE-2.0 X+ X+ Unless required by applicable law or agreed to in writing, software X+ distributed under the License is distributed on an "AS IS" BASIS, X+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. X+ See the License for the specific language governing permissions and X+ limitations under the License. X+ X+ X+ */ X+ X+ #include "ghost.h" X+ #include "util.h" X+ #include "config.h" X+ #include "ghostdb.h" X+ #include "ghostdbmysql.h" X+ X+ #include <mysqld_error.h> X+ X+ // X+ // CMySQL X+ // X+ X+ CMySQL :: CMySQL( string db, string server, string user, string pass, int port ) X+ { X+ m_DB = db; X+ m_Server = server; X+ m_User = user; X+ m_Pass = pass; X+ m_Port = port; X+ X+ m_Conn = new mysqlpp::Connection(false); X+ Connect( ); X+ } X+ X+ CMySQL :: ~CMySQL( ) X+ { X+ Disconnect( ); X+ } X+ X+ bool CMySQL :: Connect( ) X+ { X+ CONSOLE_Print( "[MySQL++] Connecting to database." ); X+ X+ // It is necessary to destroy the connection object and recreate it X+ // to re-establish a connection, a quirk of mysql++ X+ // This is not necessary the first time but we use the same function X+ delete m_Conn; X+ m_Conn = new mysqlpp::Connection(false); X+ X+ if( m_Conn->connect( m_DB.c_str( ), m_Server.c_str( ), m_User.c_str( ), m_Pass.c_str( ), m_Port ) ) X+ return true; X+ else X+ { X+ m_ConnError = m_Conn->error( ); X+ return false; X+ } X+ } X+ X+ void CMySQL :: Disconnect( ) X+ { X+ CONSOLE_Print( "[MySQL++] Disconnecting from database." ); X+ X+ m_Conn->disconnect( ); X+ } X+ X+ bool CMySQL :: Exec( string query ) X+ { X+ X+ bool Success = false; X+ if( Connected( ) ) X+ { X+ mysqlpp::Query m_Query = m_Conn->query( query.c_str( ) ); X+ X+ if( m_Query.exec( ) ) X+ Success = true; X+ else X+ { X+ m_Error = m_Query.error( ); X+ m_Errnum = m_Query.errnum( ); X+ } X+ } X+ X+ return Success; X+ } X+ X+ bool CMySQL :: Store( string query ) X+ { X+ if( Connected( ) ) X+ { X+ mysqlpp::Query m_Query = m_Conn->query( query.c_str( ) ); X+ X+ if( m_Result = m_Query.store( ) ) X+ return true; X+ else X+ { X+ m_Error = m_Query.error( ); X+ m_Errnum = m_Query.errnum( ); X+ return false; X+ } X+ } X+ return false; X+ } X+ X+ bool CMySQL :: LoadIPData( ) X+ { X+ if( Store( "SELECT COUNT(*) FROM iptocountry" ) ) X+ { X+ mysqlpp::StoreQueryResult result = GetResult( ); X+ if( atoi( result[0][0].c_str( ) ) == 0 ) X+ return true; X+ else X+ return false; X+ } X+ else X+ return false; X+ } X+ X+ // X+ // CGHostDBMySQL X+ // X+ X+ CGHostDBMySQL :: CGHostDBMySQL( CConfig *CFG ) : CGHostDB( CFG ) X+ { X+ m_NextPing = GetTime( ) + 5; X+ m_ServerError = false; X+ string db = CFG->GetString( "db_mysql_database", "MYSQL_ERROR" ); X+ string hostname = CFG->GetString( "db_mysql_hostname", "MYSQL_ERROR" ); X+ string username = CFG->GetString( "db_mysql_username", "MYSQL_ERROR" ); X+ string password = CFG->GetString( "db_mysql_password", "MYSQL_ERROR" ); X+ string port = CFG->GetString( "db_mysql_port", "MYSQL_ERROR" ); X+ X+ if( db == "MYSQL_ERROR" || hostname == "MYSQL_ERROR" || username == "MYSQL_ERROR" || password == "MYSQL_ERROR" || port == "MYSQL_ERROR" ) X+ { X+ CONSOLE_Print( "[MySQL++] One of/all MySQL config values are not set; fix config file." ); X+ m_HasError = true; X+ m_Error = "error getting MySQL config values"; X+ return; X+ } X+ X+ m_DB = new CMySQL( db, hostname, username, password, atoi( port.c_str( ) ) ); X+ X+ // Establish the connection X+ X+ if( m_DB->Connected( ) ) X+ CONSOLE_Print( "[MySQL++] Database connection successful." ); X+ else X+ { X+ CONSOLE_Print( "[MySQL++] Database connection failed: " + string( m_DB->GetConnError( ) ) ); X+ m_HasError = true; X+ m_Error = "error connecting to database"; X+ return; X+ } X+ X+ int schemaNumber = 0; X+ // Attempt to get the schema number from the database X+ X+ if( m_DB->Store( "SELECT value FROM config WHERE name='schema_number'" ) ) X+ { X+ CONSOLE_Print( "[MySQL++] Found schema number." ); X+ mysqlpp::StoreQueryResult res = m_DB->GetResult( ); X+ schemaNumber = res[0][0]; X+ } X+ else if( m_DB->GetErrnum( ) == ER_NO_SUCH_TABLE ) X+ CONSOLE_Print( "[MySQL++] Database is empty, creating tables." ); X+ else X+ { X+ CONSOLE_Print( "[MySQL++] Failed to get schema number: " + string( m_DB->GetError( ) ) ); X+ m_HasError = true; X+ m_Error = "unable to determine if database exists"; X+ return; X+ } X+ X+ if( schemaNumber == 0 ) X+ { X+ // Create the config table X+ X+ if( m_DB->Exec( "CREATE TABLE `config` ( `name` VARCHAR( 13 ) NOT NULL, `value` TINYINT NOT NULL, PRIMARY KEY( `name` ) )" ) ) X+ CONSOLE_Print( "[MySQL++] Created table `config` successfully." ); X+ else X+ { X+ m_HasError = true; X+ m_Error = "error creating `config` table"; X+ CONSOLE_Print( "[MySQL++] Failed to create table `config`: " + string( m_DB->GetError( ) ) ); X+ return; X+ } X+ X+ // Insert the Schema Number in the config table X+ X+ if( m_DB->Exec( "INSERT INTO `config` ( `name`, `value` ) VALUES ( 'schema_number', 1 )" ) ) X+ { X+ CONSOLE_Print( "[MySQL++] Successfully inserted schema number." ); X+ schemaNumber = 1; X+ } X+ else X+ { X+ m_HasError = true; X+ m_Error = "error inserting schema number"; X+ CONSOLE_Print( "[MySQL++] Failed to insert schema number: " + string( m_DB->GetError( ) ) ); X+ return; X+ } X+ X+ // Create the admins table X+ X+ if( m_DB->Exec( "CREATE TABLE `admins` ( `id` INTEGER AUTO_INCREMENT, `name` VARCHAR( 15 ) NOT NULL, `server` VARCHAR( 40 ) NOT NULL DEFAULT '', PRIMARY KEY( `id` ) )" ) ) X+ CONSOLE_Print( "[MySQL++] Created table `admins` successfully." ); X+ else X+ { X+ m_HasError = true; X+ m_Error = "error creating `admins` table"; X+ CONSOLE_Print( "[MySQL++] Failed to create table `admins`: " + string( m_DB->GetError( ) ) ); X+ return; X+ } X+ X+ // Create the bans table X+ X+ if( m_DB->Exec( "CREATE TABLE `bans` ( `id` INTEGER AUTO_INCREMENT, `server` VARCHAR( 40 ) NOT NULL, `name` VARCHAR( 15 ) NOT NULL, `ip` VARCHAR( 15 ), `date` DATE NOT NULL, `gamename` VARCHAR( 32 ), `admin` VARCHAR( 15 ) NOT NULL, `reason` VARCHAR( 100 ), PRIMARY KEY( `id` ) )" ) ) X+ CONSOLE_Print( "[MySQL++] Created table `bans` successfully." ); X+ else X+ { X+ m_HasError = true; X+ m_Error = "error creating `bans` table"; X+ CONSOLE_Print( "[MySQL++] Failed to create table `bans`: " + string( m_DB->GetError( ) ) ); X+ return; X+ } X+ X+ // Create the games table X+ X+ if( m_DB->Exec( "CREATE TABLE `games` ( `id` INTEGER AUTO_INCREMENT, `server` VARCHAR( 40 ) NOT NULL, `map` VARCHAR( 40 ) NOT NULL, `datetime` DATETIME NOT NULL, `gamename` VARCHAR( 32 ), `ownername` VARCHAR( 15 ), `duration` INTEGER NOT NULL, `gamestate` TINYINT NOT NULL DEFAULT 0, `creatorname` VARCHAR( 15 ) NOT NULL DEFAULT '', `creatorserver` VARCHAR( 40 ) NOT NULL DEFAULT '', PRIMARY KEY( `id` ) )" ) ) X+ CONSOLE_Print( "[MySQL++] Created table `games` successfully." ); X+ else X+ { X+ m_HasError = true; X+ m_Error = "error creating `games` table"; X+ CONSOLE_Print( "[MySQL++] Failed to create table `games`: " + string( m_DB->GetError( ) ) ); X+ return; X+ } X+ X+ // Create the gameplayers table X+ X+ if( m_DB->Exec( "CREATE TABLE `gameplayers` ( `id` INTEGER AUTO_INCREMENT, `gameid` INTEGER NOT NULL, `name` VARCHAR( 15 ) NOT NULL, `ip` VARCHAR( 15 ) NOT NULL, `spoofed` INTEGER NOT NULL, `reserved` INTEGER NOT NULL, `loadingtime` INTEGER NOT NULL, `left` INTEGER NOT NULL, `leftreason` VARCHAR( 100 ) NOT NULL, `team` TINYINT NOT NULL, `colour` TINYINT NOT NULL, `spoofedrealm` VARCHAR( 40 ) NOT NULL DEFAULT '', PRIMARY KEY( `id` ) )" ) ) X+ CONSOLE_Print( "[MySQL++] Created table `gameplayers` successfully." ); X+ else X+ { X+ m_HasError = true; X+ m_Error = "error creating `gameplayers` table"; X+ CONSOLE_Print( "[MySQL++] Failed to create table `gameplayers`: " + string( m_DB->GetError( ) ) ); X+ return; X+ } X+ X+ // Create the dotagames table X+ X+ if( m_DB->Exec( "CREATE TABLE `dotagames` ( `id` INTEGER AUTO_INCREMENT, `gameid` INTEGER NOT NULL, `winner` TINYINT NOT NULL, `min` INTEGER NOT NULL DEFAULT 0, `sec` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY( `id` ) )" ) ) X+ CONSOLE_Print( "[MySQL++] Created table `dotagames` successfully." ); X+ else X+ { X+ m_HasError = true; X+ m_Error = "error creating `dotagames` table"; X+ CONSOLE_Print( "[MySQL++] Failed to create table `dotagames`: " + string( m_DB->GetError( ) ) ); X+ return; X+ } X+ X+ // Create the dotaplayers table X+ X+ if( m_DB->Exec( "CREATE TABLE `dotaplayers` ( `id` INTEGER AUTO_INCREMENT, `gameid` INTEGER NOT NULL, `colour` TINYINT NOT NULL, `kills` INTEGER NOT NULL, `deaths` INTEGER NOT NULL, `creepkills` INTEGER NOT NULL, `creepdenies` INTEGER NOT NULL, `assists` INTEGER NOT NULL, `gold` INTEGER NOT NULL, `neutralkills` INTEGER NOT NULL, `item1` VARCHAR( 6 ), `item2` VARCHAR( 6 ), `item3` VARCHAR( 6 ), `item4` VARCHAR( 6 ), `item5` VARCHAR( 6 ), `item6` VARCHAR( 6 ), `hero` VARCHAR( 6 ) NOT NULL DEFAULT '', `newcolour` INTEGER NOT NULL DEFAULT 0, `towerkills` INTEGER NOT NULL DEFAULT 0, `raxkills` INTEGER NOT NULL DEFAULT 0, `courierkills` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY( `id` ) )" ) ) X+ CONSOLE_Print( "[MySQL++] Created table `dotaplayers` successfully." ); X+ else X+ { X+ m_HasError = true; X+ m_Error = "error creating `dotaplayers` table"; X+ CONSOLE_Print( "[MySQL++] Failed to create table `dotaplayers`: " + string( m_DB->GetError( ) ) ); X+ return; X+ } X+ X+ // Create the downloads table X+ X+ if( m_DB->Exec( "CREATE TABLE `downloads` ( `id` INTEGER AUTO_INCREMENT, `map` VARCHAR( 40 ) NOT NULL, `mapsize` INTEGER NOT NULL, `datetime` DATETIME NOT NULL, `name` VARCHAR( 15 ) NOT NULL, `ip` VARCHAR( 15 ) NOT NULL, `spoofed` INTEGER( 1 ) NOT NULL, `spoofedrealm` VARCHAR( 40 ) NOT NULL, `downloadtime` INTEGER NOT NULL, PRIMARY KEY( `id` ) )" ) ) X+ CONSOLE_Print( "[MySQL++] Created table `downloads` successfully." ); X+ else X+ { X+ m_HasError = true; X+ m_Error = "error creating `downloads` table"; X+ CONSOLE_Print( "[MySQL++] Failed to create table `downloads`: " + string( m_DB->GetError( ) ) ); X+ return; X+ } X+ X+ // Create the iptocountry table X+ X+ if( m_DB->Exec( "CREATE TABLE `iptocountry` ( `ip1` INTEGER UNSIGNED NOT NULL, `ip2` INTEGER UNSIGNED NOT NULL, `country` VARCHAR( 4 ) NOT NULL, PRIMARY KEY( `ip1`, `ip2` ) )" ) ) X+ CONSOLE_Print( "[MySQL++] Successfully created iptocountry table." ); X+ else X+ CONSOLE_Print( "[MySQL++] Failed to create iptocountry table: " + string( m_DB->GetError( ) ) ); X+ X+ // Create index idx_gameid X+ X+ if( m_DB->Exec( "CREATE INDEX idx_gameid ON gameplayers ( gameid )" ) ) X+ CONSOLE_Print( "[MySQL++] Successfully created index idx_gameid." ); X+ else X+ CONSOLE_Print( "[MySQL++] Failed to create index idx_gameid: " + string( m_DB->GetError( ) ) ); X+ X+ // Create index idx_gameid_colour X+ X+ if( m_DB->Exec( "CREATE INDEX idx_gameid_colour ON dotaplayers ( gameid, colour )" ) ) X+ CONSOLE_Print( "[MySQL++] Successfully created index idx_gameid_colour." ); X+ else X+ CONSOLE_Print( "[MySQL++] Failed to create index idx_gameid_colour: " + string( m_DB->GetError( ) ) ); X+ } X+ } X+ X+ CGHostDBMySQL :: ~CGHostDBMySQL( ) X+ { X+ if( !m_HasError ) X+ { X+ delete m_DB; X+ } X+ } X+ X+ bool CGHostDBMySQL :: FromAdd( uint32_t ip1, uint32_t ip2, string country ) X+ { X+ bool Success = false; X+ X+ if( m_DB->Exec( "INSERT INTO `iptocountry` ( `ip1`, `ip2`, `country` ) VALUES ( '" + UTIL_ToString( ip1 ) + "', '" + UTIL_ToString( ip2 ) + "', '" + country + "' )" ) ) X+ Success = true; X+ else X+ CONSOLE_Print( "[MySQL++] Error adding iptocountry [" + UTIL_ToString( ip1 ) + " : " + UTIL_ToString( ip2 ) + " : " + country + "] - " + string( m_DB->GetError( ) ) ); X+ X+ return Success; X+ } X+ X+ bool CGHostDBMySQL :: Begin( ) X+ { X+ if( m_DB->Connected( ) ) X+ { X+ if( m_DB->Exec( "START TRANSACTION" ) ) X+ return true; X+ else X+ { X+ CONSOLE_Print( "[MySQL++] Error starting transaction: " + string( m_DB->GetError( ) ) ); X+ return false; X+ } X+ } X+ else X+ { X+ CONSOLE_Print( "[MySQL++] Not connected." ); X+ return false; X+ } X+ } X+ X+ bool CGHostDBMySQL :: Commit( ) X+ { X+ if( m_DB->Connected( ) ) X+ { X+ if( m_DB->Exec( "COMMIT" ) ) X+ return true; X+ else X+ { X+ CONSOLE_Print( "[MySQL++] Error committing transaction: " + string( m_DB->GetError( ) ) ); X+ return false; X+ } X+ } X+ else X+ { X+ CONSOLE_Print( "[MySQL++] Not connected." ); X+ return false; X+ } X+ } X+ X+ string CGHostDBMySQL :: FromCheck( uint32_t ip ) X+ { X+ string From = "??"; X+ if( m_DB->Store( "SELECT country FROM iptocountry WHERE `ip1`<='" + UTIL_ToString( ip ) + "' AND `ip2`>='" + UTIL_ToString( ip ) + "'" ) ) X+ { X+ mysqlpp::StoreQueryResult res = m_DB->GetResult( ); X+ if( !res.empty( ) ) X+ From = string( res[0][0] ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error looking up IP: " + string( m_DB->GetError( ) ) ); X+ X+ return From; X+ } X+ X+ uint32_t CGHostDBMySQL :: AdminCount( string server ) X+ { X+ uint32_t Count = 0; X+ X+ if( m_DB->Store( "SELECT COUNT(*) FROM admins WHERE server='" + server + "'" ) ) X+ { X+ mysqlpp::StoreQueryResult result = m_DB->GetResult( ); X+ X+ Count = atoi( result[0][0] ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error counting admins: " + string( m_DB->GetError( ) ) ); X+ X+ return Count; X+ } X+ X+ bool CGHostDBMySQL :: AdminCheck( string server, string user ) X+ { X+ user = sEscape( user ); X+ transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); X+ bool IsAdmin = false; X+ X+ if( m_DB->Store( "SELECT * FROM admins WHERE server='" + server + "' AND name='" + user + "'" ) ) X+ { X+ mysqlpp::StoreQueryResult result = m_DB->GetResult( ); X+ X+ if( !result.empty( ) ) X+ IsAdmin = true; X+ } X+ X+ return IsAdmin; X+ } X+ X+ bool CGHostDBMySQL :: AdminAdd( string server, string user ) X+ { X+ user = sEscape( user ); X+ transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); X+ bool Success = false; X+ X+ if( m_DB->Exec( "INSERT INTO admins ( server, name ) VALUES ( '" + server + "', '" + user + "' )" ) ) X+ Success = true; X+ else X+ CONSOLE_Print( "[MySQL++] Error inserting row in admins: " + string( m_DB->GetError( ) ) ); X+ X+ return Success; X+ } X+ X+ bool CGHostDBMySQL :: AdminRemove( string server, string user ) X+ { X+ user = sEscape( user ); X+ transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); X+ bool Success = false; X+ X+ if( m_DB->Exec( "DELETE FROM admins WHERE server='" + server + "' AND name='" + user + "'" ) ) X+ Success = true; X+ else X+ CONSOLE_Print( "[MySQL++] Error deleting row in admins: " + string( m_DB->GetError( ) ) ); X+ X+ return Success; X+ } X+ X+ uint32_t CGHostDBMySQL :: BanCount( string server ) X+ { X+ uint32_t Count = 0; X+ X+ if( m_DB->Store( "SELECT COUNT(*) FROM bans WHERE server='" + server + "'" ) ) X+ { X+ mysqlpp::StoreQueryResult result = m_DB->GetResult( ); X+ X+ Count = atoi( result[0][0] ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error counting bans: " + string( m_DB->GetError( ) ) ); X+ X+ return Count; X+ } X+ X+ CDBBan *CGHostDBMySQL :: BanCheck( string server, string user ) X+ { X+ user = sEscape( user ); X+ transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); X+ CDBBan *Ban = NULL; X+ X+ if( m_DB->Store( "SELECT ip, date, gamename, admin, reason FROM bans WHERE server='" + server + "' AND name='" + user + "'" ) ) X+ { X+ mysqlpp::StoreQueryResult result = m_DB->GetResult( ); X+ X+ if( !result.empty( ) ) X+ { X+ Ban = new CDBBan( server, user, string( result[0][0] ), string( result[0][1] ), string( result[0][2] ), string( result[0][3] ), string( result[0][4] ) ); X+ } X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error checking a ban: " + string( m_DB->GetError( ) ) ); X+ X+ return Ban; X+ } X+ X+ bool CGHostDBMySQL :: BanAdd( string server, string user, string ip, string gamename, string admin, string reason ) X+ { X+ user = sEscape( user ); X+ ip = sEscape( ip ); X+ gamename = sEscape( gamename ); X+ admin = sEscape( admin ); X+ reason = sEscape( reason ); X+ transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); X+ bool Success = false; X+ X+ if( m_DB->Exec( "INSERT INTO bans ( server, name, ip, date, gamename, admin, reason ) VALUES ( '" + server + "', '" + user + "', '" + ip + "', CURDATE( ), '" + gamename + "', '" + admin + "', '" + reason + "' )" ) ) X+ Success = true; X+ else X+ CONSOLE_Print( "[MySQL++] Error inserting row in bans: " + string( m_DB->GetError( ) ) ); X+ X+ return Success; X+ } X+ X+ bool CGHostDBMySQL :: BanRemove( string server, string user ) X+ { X+ user = sEscape( user ); X+ transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); X+ bool Success = false; X+ X+ if( m_DB->Exec( "DELETE FROM bans WHERE server='" + server + "' AND name='" + user + "'" ) ) X+ Success = true; X+ else X+ CONSOLE_Print( "[MySQL++] Error deleting row in bans: " + string( m_DB->GetError( ) ) ); X+ X+ return Success; X+ } X+ X+ bool CGHostDBMySQL :: BanRemove( string user ) X+ { X+ user = sEscape( user ); X+ transform( user.begin( ), user.end( ), user.begin( ), (int(*)(int))tolower ); X+ bool Success = false; X+ X+ if( m_DB->Exec( "DELETE FROM bans WHERE name='" + user + "'" ) ) X+ Success = true; X+ else X+ CONSOLE_Print( "[MySQL++] Error deleting row in bans: " + string( m_DB->GetError( ) ) ); X+ X+ return Success; X+ } X+ X+ uint32_t CGHostDBMySQL :: GameAdd( string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ) X+ { X+ gamename = sEscape( gamename ); X+ ownername = sEscape( ownername ); X+ creatorname = sEscape( creatorname ); X+ creatorserver = sEscape( creatorserver ); X+ uint32_t RowID = 0; X+ X+ if( m_DB->Exec( "INSERT INTO games ( server, map, datetime, gamename, ownername, duration, gamestate, creatorname, creatorserver ) VALUES ( '" + server + "', '" + map + "', UTC_TIMESTAMP( ), '" + gamename + "', '" + ownername + "', '" + UTIL_ToString( duration ) + "', '" + UTIL_ToString( gamestate ) + "', '" + creatorname + "', '" + creatorserver + "' )" ) ) X+ { X+ if( m_DB->Store( "SELECT LAST_INSERT_ID( )" ) ) X+ { X+ mysqlpp::StoreQueryResult result = m_DB->GetResult( ); X+ X+ if( !result.empty( ) ) X+ RowID = atoi( result[0][0] ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error getting last insert ID: " + string( m_DB->GetError( ) ) ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error inserting row in games: " + string( m_DB->GetError( ) ) ); X+ X+ return RowID; X+ } X+ X+ uint32_t CGHostDBMySQL :: GamePlayerAdd( 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 ) X+ { X+ name = sEscape( name ); X+ spoofedrealm = sEscape( spoofedrealm ); X+ leftreason = sEscape( leftreason ); X+ transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); X+ uint32_t RowID = 0; X+ X+ // Turns out MySQL does not recognise "left" in the column list as a column name, instead the command LEFT therefore we need to backtick it X+ X+ if( m_DB->Exec( "INSERT INTO gameplayers ( gameid, name, ip, spoofed, reserved, loadingtime, `left`, leftreason, team, colour, spoofedrealm ) VALUES ( '" + UTIL_ToString( gameid ) + "', '" + name + "', '" + ip + "', '" + UTIL_ToString( spoofed ) + "', '" + UTIL_ToString( reserved ) + "', '" + UTIL_ToString( loadingtime ) + "', '" + UTIL_ToString( left ) + "', '" + leftreason + "', '" + UTIL_ToString( team ) + "', '" + UTIL_ToString( colour ) + "', '" + spoofedrealm + "' )" ) ) X+ { X+ if( m_DB->Store( "SELECT LAST_INSERT_ID( )" ) ) X+ { X+ mysqlpp::StoreQueryResult result = m_DB->GetResult( ); X+ X+ if( !result.empty( ) ) X+ RowID = atoi( result[0][0] ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error getting last insert ID: " + string( m_DB->GetError( ) ) ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error inserting row in gameplayers: " + string( m_DB->GetError( ) ) ); X+ X+ return RowID; X+ } X+ X+ uint32_t CGHostDBMySQL :: GamePlayerCount( string name ) X+ { X+ name = sEscape( name ); X+ uint32_t Count = 0; X+ X+ if( m_DB->Store( "SELECT COUNT(*) FROM gameplayers LEFT JOIN games ON games.id=gameid WHERE name='" + name + "'" ) ) X+ { X+ mysqlpp::StoreQueryResult result = m_DB->GetResult( ); X+ X+ Count = atoi( result[0][0] ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error counting gameplayers: " + string( m_DB->GetError( ) ) ); X+ X+ return Count; X+ } X+ X+ CDBGamePlayerSummary *CGHostDBMySQL :: GamePlayerSummaryCheck( string name ) X+ { X+ if( GamePlayerCount( name ) == 0 ) X+ return NULL; X+ name = sEscape( name ); X+ X+ transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); X+ CDBGamePlayerSummary *GamePlayerSummary = NULL; X+ X+ if( m_DB->Store( "SELECT MIN(datetime), MAX(datetime), COUNT(*), MIN(loadingtime), AVG(loadingtime), MAX(loadingtime), MIN(`left`/duration)*100, AVG(`left`/duration)*100, MAX(`left`/duration)*100, MIN(duration), AVG(duration), MAX(duration) FROM gameplayers LEFT JOIN games ON games.id=gameid WHERE name='" + name + "'" ) ) X+ { X+ mysqlpp::StoreQueryResult result = m_DB->GetResult( ); X+ X+ if( !result.empty( ) ) X+ { X+ string FirstGameDateTime = string( result[0][0] ); X+ string LastGameDateTime = string( result[0][1] ); X+ X+ uint32_t TotalGames = atoi( result[0][2] ); X+ uint32_t MinLoadingTime = atoi( result[0][3] ); X+ uint32_t AvgLoadingTime = atoi( result[0][4] ); X+ uint32_t MaxLoadingTime = atoi( result[0][5] ); X+ uint32_t MinLeftPercent = atoi( result[0][6] ); X+ uint32_t AvgLeftPercent = atoi( result[0][7] ); X+ uint32_t MaxLeftPercent = atoi( result[0][8] ); X+ uint32_t MinDuration = atoi( result[0][9] ); X+ uint32_t AvgDuration = atoi( result[0][10] ); X+ uint32_t MaxDuration = atoi( result[0][11] ); X+ GamePlayerSummary = new CDBGamePlayerSummary( string( ), name, FirstGameDateTime, LastGameDateTime, TotalGames, MinLoadingTime, AvgLoadingTime, MaxLoadingTime, MinLeftPercent, AvgLeftPercent, MaxLeftPercent, MinDuration, AvgDuration, MaxDuration ); X+ } X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error getting gameplayersummary: " + string( m_DB->GetError( ) ) ); X+ X+ return GamePlayerSummary; X+ } X+ X+ uint32_t CGHostDBMySQL :: DotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ) X+ { X+ uint32_t RowID = 0; X+ X+ if( m_DB->Exec( "INSERT INTO dotagames ( gameid, winner, min, sec ) VALUES ( '" + UTIL_ToString( gameid ) + "', '" + UTIL_ToString( winner ) + "', '" + UTIL_ToString( min ) + "', '" + UTIL_ToString( sec ) + "' )" ) ) X+ { X+ if( m_DB->Store( "SELECT LAST_INSERT_ID( )" ) ) X+ { X+ mysqlpp::StoreQueryResult result = m_DB->GetResult( ); X+ X+ if( !result.empty( ) ) X+ RowID = atoi( result[0][0] ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error getting last insert ID: " + string( m_DB->GetError( ) ) ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error inserting row in dotagames: " + string( m_DB->GetError( ) ) ); X+ X+ return RowID; X+ } X+ X+ uint32_t CGHostDBMySQL :: DotAPlayerAdd( 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 ) X+ { X+ uint32_t RowID = 0; X+ X+ // We need to convert item1-6 and hero to an empty string if it's contents aren't an item code X+ // We do this because what it contains is " ", with the spaces being a non-space whitespace character for some reason X+ // MySQL does not like this X+ X+ string alphaNum = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; X+ if( !( item1.find_first_not_of( alphaNum ) == string::npos ) ) X+ item1 = ""; X+ if( !( item2.find_first_not_of( alphaNum ) == string::npos ) ) X+ item2 = ""; X+ if( !( item3.find_first_not_of( alphaNum ) == string::npos ) ) X+ item3 = ""; X+ if( !( item4.find_first_not_of( alphaNum ) == string::npos ) ) X+ item4 = ""; X+ if( !( item5.find_first_not_of( alphaNum ) == string::npos ) ) X+ item5 = ""; X+ if( !( item6.find_first_not_of( alphaNum ) == string::npos ) ) X+ item6 = ""; X+ if( !( hero.find_first_not_of( alphaNum ) == string::npos ) ) X+ hero = ""; X+ X+ if( m_DB->Exec( "INSERT INTO dotaplayers ( gameid, colour, kills, deaths, creepkills, creepdenies, assists, gold, neutralkills, item1, item2, item3, item4, item5, item6, hero, newcolour, towerkills, raxkills, courierkills ) VALUES ( '" + 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 ) + "', '" + item1 + "', '" + item2 + "', '" + item3 + "', '" + item4 + "', '" + item5 + "', '" + item6 + "', '" + hero + "', '" + UTIL_ToString( newcolour ) + "', '" + UTIL_ToString( towerkills ) + "', '" + UTIL_ToString( raxkills ) + "', '" + UTIL_ToString( courierkills ) + "' )" ) ) X+ { X+ if( m_DB->Store( "SELECT LAST_INSERT_ID( )" ) ) X+ { X+ mysqlpp::StoreQueryResult result = m_DB->GetResult( ); X+ X+ if( !result.empty( ) ) X+ RowID = atoi( result[0][0] ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error getting last insert ID: " + string( m_DB->GetError( ) ) ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error inserting row in dotaplayers: " + string( m_DB->GetError( ) ) ); X+ X+ return RowID; X+ } X+ X+ uint32_t CGHostDBMySQL :: DotAPlayerCount( string name ) X+ { X+ name = sEscape( name ); X+ uint32_t Count = 0; X+ X+ if( m_DB->Store( "SELECT COUNT(dotaplayers.id) FROM gameplayers LEFT JOIN games ON games.id=gameplayers.gameid LEFT JOIN dotaplayers ON dotaplayers.gameid=games.id AND dotaplayers.colour=gameplayers.colour WHERE name='" + name + "'" ) ) X+ { X+ mysqlpp::StoreQueryResult result = m_DB->GetResult( ); X+ X+ Count = atoi( result[0][0] ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error counting dotaplayers: " + string( m_DB->GetError( ) ) ); X+ X+ return Count; X+ } X+ X+ CDBDotAPlayerSummary *CGHostDBMySQL :: DotAPlayerSummaryCheck( string name ) X+ { X+ if( DotAPlayerCount( name ) == 0 ) X+ return NULL; X+ X+ name = sEscape( name ); X+ transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); X+ CDBDotAPlayerSummary *DotAPlayerSummary = NULL; X+ X+ if( m_DB->Store( "SELECT COUNT(dotaplayers.id), SUM(kills), SUM(deaths), SUM(creepkills), SUM(creepdenies), SUM(assists), SUM(neutralkills), SUM(towerkills), SUM(raxkills), SUM(courierkills) FROM gameplayers LEFT JOIN games ON games.id=gameplayers.gameid LEFT JOIN dotaplayers ON dotaplayers.gameid=games.id AND dotaplayers.colour=gameplayers.colour WHERE name='" + name + "'" ) ) X+ { X+ mysqlpp::StoreQueryResult result = m_DB->GetResult( ); X+ X+ if( !result.empty( ) ) X+ { X+ uint32_t TotalGames = atoi( result[0][0] ); X+ uint32_t TotalWins = 0; X+ uint32_t TotalLosses = 0; X+ uint32_t TotalKills = atoi( result[0][1] ); X+ uint32_t TotalDeaths = atoi( result[0][2] ); X+ uint32_t TotalCreepKills = atoi( result[0][3] ); X+ uint32_t TotalCreepDenies = atoi( result[0][4] ); X+ uint32_t TotalAssists = atoi( result[0][5] ); X+ uint32_t TotalNeutralKills = atoi( result[0][6] ); X+ uint32_t TotalTowerKills = atoi( result[0][7] ); X+ uint32_t TotalRaxKills = atoi( result[0][8] ); X+ uint32_t TotalCourierKills = atoi( result[0][9] ); X+ X+ if( m_DB->Store( "SELECT COUNT(*) FROM gameplayers LEFT JOIN games ON games.id=gameplayers.gameid LEFT JOIN dotaplayers ON dotaplayers.gameid=games.id AND dotaplayers.colour=gameplayers.colour LEFT JOIN dotagames ON games.id=dotagames.gameid WHERE name='" + name + "' AND ((winner=1 AND dotaplayers.newcolour>=1 AND dotaplayers.newcolour<=5) OR (winner=2 AND dotaplayers.newcolour>=7 AND dotaplayers.newcolour<=11))" ) ) X+ { X+ mysqlpp::StoreQueryResult resultwins = m_DB->GetResult( ); X+ X+ if( !resultwins.empty( ) ) X+ TotalWins = atoi( resultwins[0][0] ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error counting dotaplayersummary wins: " + string( m_DB->GetError( ) ) ); X+ X+ if( m_DB->Store( "SELECT COUNT(*) FROM gameplayers LEFT JOIN games ON games.id=gameplayers.gameid LEFT JOIN dotaplayers ON dotaplayers.gameid=games.id AND dotaplayers.colour=gameplayers.colour LEFT JOIN dotagames ON games.id=dotagames.gameid WHERE name='" + name + "' AND ((winner=2 AND dotaplayers.newcolour>=1 AND dotaplayers.newcolour<=5) OR (winner=1 AND dotaplayers.newcolour>=7 AND dotaplayers.newcolour<=11))" ) ) X+ { X+ mysqlpp::StoreQueryResult resultlosses = m_DB->GetResult( ); X+ X+ if( !resultlosses.empty( ) ) X+ TotalLosses = atoi( resultlosses[0][0] ); X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error counting dotaplayersummary losses: " + string( m_DB->GetError( ) ) ); X+ X+ DotAPlayerSummary = new CDBDotAPlayerSummary( string( ), name, TotalGames, TotalWins, TotalLosses, TotalKills, TotalDeaths, TotalCreepKills, TotalCreepDenies, TotalAssists, TotalNeutralKills, TotalTowerKills, TotalRaxKills, TotalCourierKills ); X+ } X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error getting dotaplayersummary: " + string( m_DB->GetError( ) ) ); X+ X+ return DotAPlayerSummary; X+ } X+ X+ bool CGHostDBMySQL :: DownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ) X+ { X+ name = sEscape( name ); X+ ip = sEscape( ip ); X+ spoofedrealm = sEscape( spoofedrealm ); X+ bool Success = false; X+ X+ if( m_DB->Exec( "INSERT INTO downloads ( map, mapsize, datetime, name, ip, spoofed, spoofedrealm, downloadtime ) VALUES ( '" + map + "', '" + UTIL_ToString( mapsize ) + "', UTC_TIMESTAMP( ), '" + name + "', '" + ip + "', '" + UTIL_ToString( spoofed ) + "', '" + spoofedrealm + "', '" + UTIL_ToString( downloadtime ) + "' )" ) ) X+ Success = true; X+ else X+ CONSOLE_Print( "[MySQL++] Error inserting row in downloads: " + string( m_DB->GetError( ) ) ); X+ X+ return Success; X+ } X+ X+ void CGHostDBMySQL :: Update( ) X+ { X+ uint32_t cTime = GetTime( ); X+ X+ if( cTime >= m_NextPing ) X+ { X+ m_NextPing = cTime + 5; X+ if( !m_ServerError ) X+ { X+ if( !m_DB->Ping( ) ) X+ { X+ CONSOLE_Print( "[MySQL++] Database server not responding, disconnecting..." ); X+ m_ServerError = true; X+ } X+ } X+ if( m_ServerError ) // We do not use else as we want to immediately reconnect if the above if sets m_ServerError to true X+ { X+ if( m_DB->Connect( ) ) X+ { X+ CONSOLE_Print( "[MySQL++] Connected." ); X+ m_ServerError = false; X+ } X+ else X+ CONSOLE_Print( "[MySQL++] Error reconnecting to database server: [" + string( m_DB->GetConnError( ) ) + "]\nRetrying in 5 seconds..." ); X+ } X+ X+ } X+ } X+ X+ string CGHostDBMySQL :: sEscape( string s ) X+ { X+ for( unsigned int i = 0; i != s.length( ); i++ ) X+ { X+ if( s.at( i ) == '\'' || s.at( i ) == '\"' ) X+ { X+ s.insert( i, "\\" ); X+ i++; X+ } X+ if( s.at( i ) == '\n' || s.at( i ) == ';' ) X+ { X+ s.erase( i, 1 ); X+ i--; X+ } X+ } X+ return s; X+ } END-of-/root/free/files/patch-ghostdbmysql.cpp echo x - /root/free/files/patch-ghostdbmysql.h sed 's/^X//' >/root/free/files/patch-ghostdbmysql.h << 'END-of-/root/free/files/patch-ghostdbmysql.h' X*** ghost/ghostdbmysql.h.orig Fri Mar 13 22:22:52 2009 X--- ghost/ghostdbmysql.h Fri Feb 13 15:21:00 2009 X*************** X*** 0 **** X--- 1,107 ---- X+ /* X+ X+ Copyright 2009 Scott Gillespie X+ X+ Licensed under the Apache License, Version 2.0 (the "License"); X+ you may not use this file except in compliance with the License. X+ You may obtain a copy of the License at X+ X+ http://www.apache.org/licenses/LICENSE-2.0 X+ X+ Unless required by applicable law or agreed to in writing, software X+ distributed under the License is distributed on an "AS IS" BASIS, X+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. X+ See the License for the specific language governing permissions and X+ limitations under the License. X+ X+ X+ */ X+ X+ #ifndef GHOSTDBMYSQL_H X+ #define GHOSTDBMYSQL_H X+ X+ #include <mysql++.h> X+ X+ // X+ // CMySQL X+ // X+ X+ class CMySQL X+ { X+ private: X+ string m_DB; X+ string m_Server; X+ string m_User; X+ string m_Pass; X+ int m_Port; X+ mysqlpp::Connection *m_Conn; X+ const char* m_Error; X+ int m_Errnum; X+ const char* m_ConnError; X+ mysqlpp::StoreQueryResult m_Result; X+ X+ public: X+ CMySQL( string db, string server, string user, string pass, int port); X+ ~CMySQL( ); X+ X+ bool Connect( ); X+ void Disconnect( ); X+ bool Connected( ) { return m_Conn->connected( ); } X+ const char* GetError( ) { return m_Error; } X+ const char* GetConnError( ) { return m_ConnError; } X+ int GetErrnum( ) { return m_Errnum; } X+ mysqlpp::StoreQueryResult GetResult( ) { return m_Result; } X+ bool LoadIPData( ); X+ bool Ping( ) { return m_Conn->ping( ); } X+ X+ bool Exec( string query ); X+ bool Store( string query ); X+ X+ }; X+ X+ // X+ // CGHostDBMySQL X+ // X+ X+ class CGHostDBMySQL : public CGHostDB X+ { X+ private: X+ CMySQL *m_DB; X+ uint32_t m_NextPing; X+ bool m_ServerError; X+ string sEscape( string s ); X+ X+ public: X+ CGHostDBMySQL( CConfig *CFG ); X+ virtual ~CGHostDBMySQL( ); X+ X+ virtual bool Connected( ) { return m_DB->Connected( ); } X+ X+ virtual bool FromAdd( uint32_t ip1, uint32_t ip2, string country ); X+ virtual bool Begin( ); X+ virtual bool Commit( ); X+ virtual string FromCheck( uint32_t ip ); X+ virtual bool LoadIPData( ) { return m_DB->LoadIPData( ); } X+ virtual uint32_t AdminCount( string server ); X+ virtual bool AdminCheck( string server, string user ); X+ virtual bool AdminAdd( string server, string user ); X+ virtual bool AdminRemove( string server, string user ); X+ virtual uint32_t BanCount( string server ); X+ virtual CDBBan *BanCheck( string server, string user ); X+ virtual bool BanAdd( string server, string user, string ip, string gamename, string admin, string reason ); X+ virtual bool BanRemove( string server, string user ); X+ virtual bool BanRemove( string user ); X+ virtual uint32_t GameAdd( string server, string map, string gamename, string ownername, uint32_t duration, uint32_t gamestate, string creatorname, string creatorserver ); X+ virtual uint32_t GamePlayerAdd( 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 ); X+ virtual uint32_t GamePlayerCount( string name ); X+ virtual CDBGamePlayerSummary *GamePlayerSummaryCheck( string name ); X+ virtual uint32_t DotAGameAdd( uint32_t gameid, uint32_t winner, uint32_t min, uint32_t sec ); X+ virtual uint32_t DotAPlayerAdd( 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 ); X+ virtual uint32_t DotAPlayerCount( string name ); X+ virtual CDBDotAPlayerSummary *DotAPlayerSummaryCheck( string name ); X+ virtual bool DownloadAdd( string map, uint32_t mapsize, string name, string ip, uint32_t spoofed, string spoofedrealm, uint32_t downloadtime ); X+ virtual void Update( ); X+ }; X+ X+ #endif X+ END-of-/root/free/files/patch-ghostdbmysql.h echo x - /root/free/files/patch-ghost.cfg sed 's/^X//' >/root/free/files/patch-ghost.cfg << 'END-of-/root/free/files/patch-ghost.cfg' X*** ghost.cfg.orig Fri Jan 30 01:18:22 2009 X--- ghost.cfg Thu Feb 12 11:01:00 2009 X*************** X*** 192,205 **** X # DATABASE CONFIGURATION # X ########################## X X! ### database type (this config value is ignored for now since we only support one type of database) X X! db_type = sqlite3 X X ### sqlite3 database file X X db_sqlite3_file = ghost.dbs X X ############################ X # BATTLE.NET CONFIGURATION # X ############################ X--- 192,222 ---- X # DATABASE CONFIGURATION # X ########################## X X! ### database type: sqlite3 or mysql X X! db_type = mysql X X ### sqlite3 database file X X db_sqlite3_file = ghost.dbs X X+ ### MySQL connection details X+ X+ ### The database to use X+ db_mysql_database = ghost X+ X+ ### the server to connect to X+ db_mysql_hostname = localhost X+ X+ ### the port to connect to (default port is 3306) X+ db_mysql_port = 3306 X+ X+ ### the user to connect as X+ db_mysql_username = X+ X+ ### the password to use X+ db_mysql_password = X+ X ############################ X # BATTLE.NET CONFIGURATION # X ############################ END-of-/root/free/files/patch-ghost.cfg echo x - /root/free/files/patch-ghost_makefile sed 's/^X//' >/root/free/files/patch-ghost_makefile << 'END-of-/root/free/files/patch-ghost_makefile' X*** ghost/Makefile.orig Fri Mar 13 22:06:24 2009 X--- ghost/Makefile Fri Mar 13 22:11:09 2009 X*************** X*** 4,10 **** X CC = gcc X DFLAGS = X OFLAGS = -O3 X! LFLAGS = -L. -L../bncsutil/src/bncsutil/ -L../StormLib/stormlib/ -lbncsutil -lpthread -ldl -lz -lStorm X CFLAGS = X X ifeq ($(SYSTEM),Darwin) X--- 4,10 ---- X CC = gcc X DFLAGS = X OFLAGS = -O3 X! LFLAGS = -L. -L../bncsutil/src/bncsutil/ -L../StormLib/stormlib/ -L/usr/local/lib/ -L/usr/local/lib/mysql -lmysqlclient -lbncsutil -lc -lpthread -lltdl -lStorm -lmysqlpp X CFLAGS = X X ifeq ($(SYSTEM),Darwin) X*************** X*** 21,29 **** X LFLAGS += -lresolv -lsocket -lnsl X endif X X! CFLAGS += $(OFLAGS) $(DFLAGS) -I. -I../bncsutil/src/ -I../StormLib/ X X! OBJS = bncsutilinterface.o bnet.o bnetprotocol.o commandpacket.o config.o crc32.o csvparser.o game.o gameplayer.o gameprotocol.o gameslot.o ghost.o ghostdb.o ghostdbsqlite.o language.o map.o packed.o replay.o savegame.o socket.o stats.o statsdota.o util.o X COBJS = sqlite3.o X PROGS = ./ghost++ X X--- 21,29 ---- X LFLAGS += -lresolv -lsocket -lnsl X endif X X! CFLAGS += $(OFLAGS) $(DFLAGS) -I. -I../bncsutil/src/ -I../StormLib/ -I/usr/local/include/mysql -I/usr/local/include/mysql++ X X! OBJS = bncsutilinterface.o bnet.o bnetprotocol.o commandpacket.o config.o crc32.o csvparser.o game.o gameplayer.o gameprotocol.o gameslot.o ghost.o ghostdb.o ghostdbmysql.o ghostdbsqlite.o language.o map.o packed.o replay.o savegame.o socket.o stats.o statsdota.o util.o X COBJS = sqlite3.o X PROGS = ./ghost++ X X*************** X*** 58,63 **** X--- 58,64 ---- X gameslot.o: ghost.h gameslot.h X ghost.o: ghost.h util.h crc32.h csvparser.h config.h language.h socket.h ghostdb.h ghostdbsqlite.h bnet.h map.h packed.h savegame.h gameprotocol.h game.h X ghostdb.o: ghost.h config.h ghostdb.h X+ ghostdbmysql.o: ghost.h util.h config.h ghostdb.h ghostdbmysql.h X ghostdbsqlite.o: ghost.h util.h config.h ghostdb.h ghostdbsqlite.h X language.o: ghost.h config.h language.h X packed.o: ghost.h util.h crc32.h packed.h END-of-/root/free/files/patch-ghost_makefile echo x - /root/free/Makefile sed 's/^X//' >/root/free/Makefile << 'END-of-/root/free/Makefile' X# New ports collection makefile for: GHost++ X# Date created: 16 March 2009 X# Whom: Yashin Dmitry <yashin.dm@gmail.com> X# X# $FreeBSD$ X# X XPORTNAME= GHost++ XPORTVERSION= 11.5 XCATEGORIES= games XMASTER_SITES= http://ghostplusplus.googlecode.com/files/ X XMAINTAINER= ports@FreeBSD.org XCOMMENT= Unofficial Unix version of the GHost++ Warcraft 3 hosting bot with MySql. X XDISTNAME= ghostplusplus_11.5 XUSE_ZIP= yes XUSE_GMAKE= yes X XWRKSRC= ${WRKDIR}/ghost X XLIB_DEPENDS= bz2.3:${PORTSDIR}/archivers/bzip2:install \ X gmp.7:${PORTSDIR}/math/libgmp4:install \ X mysqlclient.15:${PORTSDIR}/databases/mysql50-client:install \ X mysqlclient_r.15:${PORTSDIR}/databases/mysql50-client:install \ X mysqlpp.3:${PORTSDIR}/databases/mysql++3:install X Xdo-build: X @${ECHO_MSG} "===> Building for libbncsutil.so" X @(cd ${WRKSRC}/bncsutil/src/bncsutil && ${GMAKE}) X @${ECHO_MSG} "===> Building for libStorm.so" X @(cd ${WRKSRC}/StormLib/stormlib/ && ${GMAKE}) X @${ECHO_MSG} "===> Building for ${PKGNAME}" X @(cd ${WRKSRC}/ghost/ && ${GMAKE}) X Xdo-install: X mkdir -p /usr/local/include/bncsutil X cp ${WRKSRC}/bncsutil/src/bncsutil/*.h /usr/local/include/bncsutil X cp ${WRKSRC}/bncsutil/src/bncsutil/libbncsutil.so /usr/local/lib X mkdir -p /usr/local/include/StormLib X cp ${WRKSRC}/StormLib/stormlib/StormLib.h /usr/local/include/StormLib X cp ${WRKSRC}/StormLib/stormlib/StormPort.h /usr/local/include/StormLib X cp ${WRKSRC}/StormLib/stormlib/libStorm.so /usr/local/lib X mkdir -p /usr/local/etc/ghost++ X cp ${WRKSRC}/ghost.cfg /usr/local/etc/ghost++/ghost.cfg.simple X cp ${WRKSRC}/ghost/ghost++ /usr/local/etc/ghost++ X @${ECHO_MSG} "===> Post-installation informations for ${PKGNAME}" X @${ECHO_MSG} " You can find the configuration files and binaries for" X @${ECHO_MSG} " this package in the directory /usr/local/etc/ghost++." X @${ECHO_MSG} " Simple config files is ghost.cfg.simple" X X.include <bsd.port.mk> END-of-/root/free/Makefile echo x - /root/free/distinfo sed 's/^X//' >/root/free/distinfo << 'END-of-/root/free/distinfo' XMD5 (ghostplusplus_11.5.zip) = 840167b9946c1ad51a7fd1913051ea1e XSHA256 (ghostplusplus_11.5.zip) = 5302da6e0c1ec5a3671224570bfdb201d99c02d8704e09cbfb0fa1dc0b8a0ae0 XSIZE (ghostplusplus_11.5.zip) = 4364025 END-of-/root/free/distinfo echo x - /root/free/pkg-descr sed 's/^X//' >/root/free/pkg-descr << 'END-of-/root/free/pkg-descr' XGHost++ is a Warcraft 3 game hosting bot. Some features include: X - connect to official battle.net and PVPGN realms X - connect to multiple realms at the same time X - auto host and start games without admin interaction X - host saved games X - player statistics X - and much more... X XWWW: http://code.google.com/p/ghostplusplus/ X XThx valindar to MySql patch (http://forum.codelain.com/index.php?topic=3429) X XUnofficial Unix version of the GHost++ Warcraft 3 hosting bot with MySql. XThx FreeBSD Russian Community in http://forum.lissayra.su END-of-/root/free/pkg-descr echo x - /root/free/pkg-plist sed 's/^X//' >/root/free/pkg-plist << 'END-of-/root/free/pkg-plist' Xinclude/bncsutil/bncsutil.h Xinclude/bncsutil/bsha1.h Xinclude/bncsutil/buffer.h Xinclude/bncsutil/cdkeydecoder.h Xinclude/bncsutil/checkrevision.h Xinclude/bncsutil/debug.h Xinclude/bncsutil/decodekey.h Xinclude/bncsutil/file.h Xinclude/bncsutil/gmp.h Xinclude/bncsutil/keytables.h Xinclude/bncsutil/libinfo.h Xinclude/bncsutil/ms_stdint.h Xinclude/bncsutil/mutil.h Xinclude/bncsutil/mutil_types.h Xinclude/bncsutil/nls.h Xinclude/bncsutil/oldauth.h Xinclude/bncsutil/pe.h Xinclude/bncsutil/sha1.h Xinclude/bncsutil/stack.h Xlib/libbncsutil.so Xinclude/StormLib/StormLib.h Xinclude/StormLib/StormPort.h Xlib/libStorm.so Xetc/ghost++/ghost.cfg.simple Xetc/ghost++/ghost.log Xetc/ghost++/ghost++ X@dirrm include/bncsutil X@dirrm include/StormLib X@dirrm etc/ghost++ X@exec /sbin/ldconfig -m /usr/local/lib X@unexec /sbin/ldconfig -R END-of-/root/free/pkg-plist exit >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903161242.n2GCg8BL083024>