Index: AuthSocket.h =================================================================== --- AuthSocket.h (révision 5401) +++ AuthSocket.h (copie de travail) @@ -53,6 +53,11 @@ bool _HandleXferCancel(); bool _HandleXferAccept(); + bool _HandleInformationRetrieveAnsw(); + bool _HandleGMLevelAnsw(); + bool _HandleBanIPAnsw(); + bool _HandleRealmCharsAnsw(); + void _SetVSFields(std::string rI); FILE *pPatch; Index: AccountHandler.h =================================================================== --- AccountHandler.h (révision 0) +++ AccountHandler.h (révision 0) @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup realmd +*/ + +#include "Common.h" + +struct Account +{ + uint32 id; + uint8 security; + uint8 locale; + bool tbc; + bool banned; + bool locked; + std::string name; + std::string I; + std::string LastIp; +}; + +struct BanIp +{ + std::string Ip; +}; + +struct RealmCharacter +{ + uint32 realmId; + uint32 acctId; + uint8 numChars; +}; + +class AcctContainer +{ + public: + + AcctContainer(); + Account* FindAccountById(uint32 acctid); + Account* FindAccountByName(std::string name); + bool IpBan(std::string ClientIp); + void LoadAll(); + void ReloadEverythingIfNeed(); + void Initialize(uint32 updateInterval); + void AddAccount(Account* account,uint32 id, uint8 security, uint8 locale, uint8 tbc, bool banned, uint8 locked, std::string name, std::string I, std::string lastip); + void AddCharacter(RealmCharacter* rcharacter, uint32 realmId, uint32 acctId, uint8 numChars); + void AddBan(BanIp* banip, std::string Ip){ banip->Ip = Ip; } + uint8 GetNumChar(uint32 realmId, uint32 accountId); + + private: + + typedef HM_NAMESPACE::hash_map AccountList; + typedef std::map IpBanList; + typedef HM_NAMESPACE::hash_map CharactersList; + + AccountList m_accounts; + IpBanList m_banips; + CharactersList m_characters; + + uint32 m_UpdateInterval; + time_t m_NextUpdateTime; +}; + +#define AcctMgr MaNGOS::Singleton::Instance() Index: SpecialCodes.h =================================================================== --- SpecialCodes.h (révision 0) +++ SpecialCodes.h (révision 0) @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup realmd +*/ + +#ifndef _SPECIALCODES_H +#define _SPECIALCODES_H + +enum eRealmSendCmds +{ + REALM_SEND_ACCT_INFOS = 0x100, + REALM_SEND_BANIP_STATUS = 0x101 +}; + +enum eRealmReceivedCmds +{ + REALM_RECV_ACCT_INFOS_ANSW = 0x102, + REALM_RECV_ACCT_BANIP_ANSW = 0x103, + REALM_RECV_ACCT_MOD_INFOS = 0x104, + REALM_RECV_ACCT_ADD_BANIP = 0x105, + REALM_RECV_ACCT_RM_BANIP = 0x106, + REALM_RECV_ACCT_ADD_BANACCT = 0x107, + REALM_RECV_ACCT_RM_BANACCT = 0x108, + REALM_RECV_ACCT_ADDACCOUNT = 0x109, + REALM_RECV_ACCT_DELACCOUNT = 0x110 +}; +#endif Index: Main.cpp =================================================================== --- Main.cpp (révision 5401) +++ Main.cpp (copie de travail) @@ -31,6 +31,8 @@ #include "SystemConfig.h" #include "Util.h" +#include "AccountHandler.h" + #ifdef WIN32 #include "ServiceWin32.h" char serviceName[] = "realmd"; @@ -182,6 +184,15 @@ return 1; } + // Activate or not account caching system, precache them before launching connection port + if(sConfig.GetIntDefault("AccountCaching", 0) == 1) + { + AcctMgr.Initialize(sConfig.GetIntDefault("AccountReloadingDelay", 300)); + AcctMgr.ReloadEverythingIfNeed(); + sLog.outString(); + sLog.outString("Accounts will be reloaded in %u seconds", sConfig.GetIntDefault("AccountReloadingDelay", 300)); + } + ///- Launch the listening network socket port_t rmport = sConfig.GetIntDefault( "RealmServerPort", DEFAULT_REALMSERVER_PORT ); std::string bind_ip = sConfig.GetStringDefault("BindIP", "0.0.0.0"); Index: realmd.conf =================================================================== --- realmd.conf (révision 0) +++ realmd.conf (révision 0) @@ -0,0 +1,120 @@ +############################################ +# MaNGOS realmd configuration file # +############################################ +ConfVersion=2007062001 + +################################################################################################################### +# REALMD SETTINGS +# +# LoginDatabaseInfo +# Database connection settings for the realm server. +# Default: hostname;port;username;password;database +# .;somenumber;username;password;database - use named pipes at Windows +# Named pipes: mySQL required adding "enable-named-pipe" to [mysqld] section my.ini +# .;/path/to/unix_socket;username;password;database - use Unix sockets at Unix/Linux +# Unix sockets: experimental, not tested +# +# LogsDir +# Logs directory setting. +# Important: Logs dir must exists, or all logs be disable +# Default: "" - no log directory prefix, if used log names isn't absolute path then logs will be +# stored in current directory for run program. +# +# MaxPingTime +# Settings for maximum database-ping interval (minutes between pings) +# +# RealmServerPort +# Default RealmServerPort +# +# BindIP +# Bind Realm Server to IP/hostname +# +# PidFile +# Realmd daemon PID file +# Default: "" - do not create PID file +# "./realmd.pid" - create PID file (recommended name) +# +# LogLevel +# Server console level of logging +# 0 = Minimum; 1 = Error; 2 = Detail; 3 = Full/Debug +# Default: 0 +# +# LogTime +# Include time in server console output [hh:mm:ss] +# Default: 0 (no time) +# 1 (print time) +# +# LogFile +# Logfile name +# Default: "Realmd.log" +# "" - empty name disable creating log file +# +# LogTimestamp +# Logfile with timestamp of server start in name +# Default: 0 - no timestamp in name +# 1 - add timestamp in name in form Logname_YYYY-MM-DD_HH-MM-SS.Ext for Logname.Ext +# +# LogFileLevel +# Server file level of logging +# 0 = Minimum; 1 = Error; 2 = Detail; 3 = Full/Debug +# Default: 0 +# +# LogColors +# Color for messages (format "normal_color details_color debug_color error_color) +# Colors: 0 - BLACK, 1 - RED, 2 - GREEN, 3 - BROWN, 4 - BLUE, 5 - MAGENTA, 6 - CYAN, 7 - GREY, +# 8 - YELLOW, 9 - LRED, 10 - LGREEN, 11 - LBLUE, 12 - LMAGENTA, 13 - LCYAN, 14 - WHITE +# Default: "" - none colors +# "13 7 11 9" - for example :) +# +# UseProcessors +# Used processors mask for multi-processors system (Used only at Windows) +# Default: 0 (selected by OS) +# number (bitmask value of selected processors) +# +# ProcessPriority +# Process proirity setting (Used only at Windows) +# Default: 1 (HIGH) +# 0 (Normal) +# +# RealmsStateUpdateDelay +# Realm list Update up delay (updated at realm list request if delay expired). +# Default: 20 +# 0 (Disabled) +# +# AccountCaching +# Enable or disable accounts caching into memory instead of using database acces (usefull when population is high) +# Default: 0 (Disabled) +# +# AccountReloadingDelay +# Delay before reloading every accounts in seconds (Needed if using AccountCaching) +# Default: 1800 (15 mins) +# +# SecureRealmServerPass +# Securised password for answers between Game Server and Realm Server (Needed if using AccountCaching) +# WARNING : THIS PASSWORD SHOULD BE THE SAME ON EVERY GAME SERVERS AND ON THE REALM SERVER ! +# Default: MaNGOS +# +# +# +# +# +################################################################################################################### + +LoginDatabaseInfo = "127.0.0.1;3306;root;mangos;realmd" +LogsDir = "" +MaxPingTime = 30 +RealmServerPort = 3724 +BindIP = "0.0.0.0" +PidFile = "" +LogLevel = 0 +LogTime = 0 +LogFile = "Realmd.log" +LogTimestamp = 0 +LogFileLevel = 0 +LogColors = "" +UseProcessors = 0 +ProcessPriority = 1 +RealmsStateUpdateDelay = 20 +AccountCaching = 0 +AccountReloadingDelay = 1800 +SecureRealmServerPass = "MaNGOS" Index: Makefile.am =================================================================== --- Makefile.am (révision 5401) +++ Makefile.am (copie de travail) @@ -27,7 +27,10 @@ AuthSocket.h \ Main.cpp \ RealmList.cpp \ - RealmList.h + RealmList.h \ + AccountHandler.cpp \ + AccountHandler.h \ + SpecialCodes.h ## Link realm list daemon against the shared library mangos_realmd_LDADD = ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/zthread/libZThread.la Index: AuthSocket.cpp =================================================================== --- AuthSocket.cpp (révision 5401) +++ AuthSocket.cpp (copie de travail) @@ -30,6 +30,10 @@ #include // needs for towupper #include #include "Auth/Sha1.h" +#include "AccountHandler.h" +#include "Config/ConfigEnv.h" +#include +#include "SpecialCodes.h" extern RealmList m_realmList; @@ -156,6 +160,12 @@ bool (AuthSocket::*handler)(void); }AuthHandler; +typedef struct SpecialCodesHandler +{ + eRealmReceivedCmds cmd; + bool (AuthSocket::*handler)(void); +}SpecialCodesHandler; + // GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some paltform #if defined( __GNUC__ ) #pragma pack() @@ -206,7 +216,24 @@ { XFER_CANCEL, STATUS_CONNECTED, &AuthSocket::_HandleXferCancel } }; +const SpecialCodesHandler sptable[] = +{ + { REALM_RECV_ACCT_INFOS_ANSW, &AuthSocket::_HandleInformationRetrieveAnsw}, + { REALM_RECV_ACCT_BANIP_ANSW, &AuthSocket::_HandleBanIPAnsw } + + // Reserved for future implementation of features like ban without waiting reload time etc + /*{ REALM_RECV_ACCT_MOD_INFOS, + { REALM_RECV_ACCT_ADD_BANIP, + { REALM_RECV_ACCT_RM_BANIP, + { REALM_RECV_ACCT_ADD_BANACCT, + { REALM_RECV_ACCT_RM_BANACCT, + { REALM_RECV_ACCT_MOD_REALMCHARS, + { REALM_RECV_ACCT_ADDACCOUNT, + { REALM_RECV_ACCT_DELACCOUNT,*/ +}; + #define AUTH_TOTAL_COMMANDS sizeof(table)/sizeof(AuthHandler) +#define TOTAL_SPECIAL_COMMANDS sizeof(sptable)/sizeof(SpecialCodesHandler) ///Holds the MD5 hash of client patches present on the server Patcher PatchesCache; @@ -260,6 +287,17 @@ // assert(0); size_t i; + for(i=0;i buf; + buf.resize(2); + + // Verify Packet Size + if(ibuf.GetLength() < 2) + return false; + + ibuf.Read((char *)&buf[0], 2); + + /* + Buf[0] = cmd + Buf[1] = account id + Buf[2] = account name + Buf[3] = Security Code (Prevent abuse by sending this from not allowed computer + */ + + if(strcmp((char*)buf[2],sConfig.GetStringDefault("SecureRealmServerPass", "MaNGOS").c_str()) != 0) + return false; + + Account* acct; + + if(buf[1] != 0) + acct = AcctMgr.FindAccountById(buf[1]); + else + acct = AcctMgr.FindAccountByName((char *)buf[2]); + + ByteBuffer pkt; + + // Packet REALM_SEND_ACCT_INFOS + + // Account ID + // Account name + // Account security level + // Account locale + // Account is tbc or not + // Account is banned or not + // Account is locked or not + // Account I hash + // Account last ip + + // Sending account infos + pkt << REALM_SEND_ACCT_INFOS; + pkt << acct->id; + pkt << acct->name; + pkt << acct->security; + pkt << acct->locale; + pkt << acct->tbc; + pkt << acct->banned; + pkt << acct->locked; + pkt << acct->I; + pkt << acct->LastIp; + + SendBuf((char const*)pkt.contents(), pkt.size()); + return true; +} + +bool AuthSocket::_HandleBanIPAnsw() +{ + std::vector buf; + buf.resize(1); + + // Verify Packet Size + if(ibuf.GetLength() < 1) + return false; + + ibuf.Read((char *)&buf[0], 1); + + /* + Buf[0] = cmd + Buf[1] = IP + Buf[2] = Security Code (Prevent abuse by sending this from not allowed computer + */ + + if(strcmp((char*)buf[2],sConfig.GetStringDefault("SecureRealmServerPass", "MaNGOS").c_str()) != 0) + return false; + + bool IpIsBanned = AcctMgr.IpBan((char *)buf[1]); + + // Packet REALM_SEND_BANIP_STATUS : + + // BanStatus ( 0 not banned, 1 banned ) + // IP + + ByteBuffer pkt; + + pkt << REALM_SEND_BANIP_STATUS; + + if(IpIsBanned) + pkt << (uint8)1; + else + pkt << (uint8)0; + + pkt << buf[1]; + + SendBuf((char const*)pkt.contents(), pkt.size()); + + return true; +} + /// Make the SRP6 calculation from hash in dB void AuthSocket::_SetVSFields(std::string rI) { @@ -320,6 +459,8 @@ /// Logon Challenge command handler bool AuthSocket::_HandleLogonChallenge() { + AcctMgr.ReloadEverythingIfNeed(); + DEBUG_LOG("Entering _HandleLogonChallenge"); if (ibuf.GetLength() < sizeof(sAuthLogonChallenge_C)) return false; @@ -370,6 +511,8 @@ pkt << (uint8) AUTH_LOGON_CHALLENGE; pkt << (uint8) 0x00; + if(sConfig.GetIntDefault("AccountCaching", 0) != 1) + { ///- Verify that this IP is not in the ip_banned table // No SQL injection possible (paste the IP address as passed by the socket) dbRealmServer.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); @@ -484,10 +627,98 @@ { pkt<< (uint8) REALM_AUTH_NO_MATCH; } - } - } //valid version + } + } + else + { + if(AcctMgr.IpBan(GetRemoteAddress())) + { + pkt << (uint8)REALM_AUTH_ACCOUNT_BANNED; + } + else + { + Account* acct = AcctMgr.FindAccountByName(_safelogin); + + if(acct) + { + bool locked = false; + + if(acct->locked == 1) // if ip is locked + { + if ( strcmp(acct->LastIp.c_str(),GetRemoteAddress().c_str()) ) + { + pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED; + locked=true; + } + } + + if (!locked) + { + if(acct->banned) + { + pkt << (uint8) REALM_AUTH_ACCOUNT_BANNED; + } + else + { + ///- Get the password from the account table, upper it, and make the SRP6 calculation + std::string rI = acct->I; + _SetVSFields(rI); + b.SetRand(19 * 8); + BigNumber gmod=g.ModExp(b, N); + B = ((v * 3) + gmod) % N; + + if (B.GetNumBytes() < 32) + sLog.outDetail("Interesting, calculation of B in realmd is < 32."); + + ASSERT(gmod.GetNumBytes() <= 32); + + BigNumber unk3; + unk3.SetRand(16*8); + + ///- Fill the response packet with the result + pkt << (uint8)REALM_AUTH_SUCCESS; + pkt.append(B.AsByteArray(), B.GetNumBytes()); + pkt << (uint8)1; + pkt.append(g.AsByteArray(), 1); + pkt << (uint8)32; + pkt.append(N.AsByteArray(), 32); + pkt.append(s.AsByteArray(), s.GetNumBytes()); + pkt.append(unk3.AsByteArray(), 16); + pkt << (uint8)0; // Added in 1.12.x client branch + + uint8 secLevel = acct->security; + _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR; + + // There isn't many differents locale so i think we can hardcode them all + + char charbuffer[3]; + charbuffer[0] = ch->country[3]; + charbuffer[1] = ch->country[2]; + charbuffer[2] = '\0'; + + if(strcmp (charbuffer,"fr") == 0) + _localization = 2; + else if(strcmp (charbuffer,"de") == 0) + _localization = 3; + else + _localization = 0; + + } + } + else + { + pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED; + } + } + else //no account + { + pkt<< (uint8) REALM_AUTH_NO_MATCH; + } + } + } + } //valid version else - ///
  • else + ///
  • else { ///- Check if we have the apropriate patch on the disk char tmp[64]; @@ -535,7 +766,7 @@ } /// SendBuf((char const*)pkt.contents(), pkt.size()); - return true; + return true; } /// Logon Proof command handler @@ -661,9 +892,13 @@ ibuf.Remove(5); + std::string rI; + uint32 id; + + if(sConfig.GetIntDefault("AccountCaching", 0) != 1) + { ///- Get the user id (else close the connection) // No SQL injection (escaped user name) - QueryResult *result = dbRealmServer.PQuery("SELECT id,sha_pass_hash FROM account WHERE UPPER(username) = '%s'",_safelogin.c_str()); if(!result) { @@ -672,9 +907,16 @@ return false; } - uint32 id = (*result)[0].GetUInt32(); - std::string rI = (*result)[1].GetCppString(); + id = (*result)[0].GetUInt32(); + rI = (*result)[1].GetCppString(); delete result; + } + else + { + Account* acct = AcctMgr.FindAccountByName(_safelogin); + id = acct->id; + rI = acct->I; + } ///- Update realm list if need m_realmList.UpdateIfNeed(); @@ -687,17 +929,22 @@ for( i = m_realmList.begin(); i != m_realmList.end(); i++ ) { uint8 AmountOfCharacters; - - // No SQL injection. id of realm is controlled by the database. - result = dbRealmServer.PQuery( "SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'",i->second.m_ID,id); - if( result ) - { - Field *fields = result->Fetch(); - AmountOfCharacters = fields[0].GetUInt8(); - delete result; - } - else + if(sConfig.GetIntDefault("AccountCaching", 0) != 1) + { + // No SQL injection. id of realm is controlled by the database. + QueryResult* result = dbRealmServer.PQuery( "SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'",i->second.m_ID,id); + if( result ) + { + Field *fields = result->Fetch(); + AmountOfCharacters = fields[0].GetUInt8(); + delete result; + } + else AmountOfCharacters = 0; + } + else + AmountOfCharacters = AcctMgr.GetNumChar(i->second.m_ID, id); + uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; Index: AccountHandler.cpp =================================================================== --- AccountHandler.cpp (révision 0) +++ AccountHandler.cpp (révision 0) @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup realmd +*/ + +#include "Database/DatabaseEnv.h" +#include "Policies/SingletonImp.h" +#include "AccountHandler.h" +#include "ProgressBar.h" + +#ifdef DO_POSTGRESQL +extern DatabasePostgre dbRealmServer; +#else +extern DatabaseMysql dbRealmServer; +#endif + +INSTANTIATE_SINGLETON_1( AcctContainer); + +AcctContainer::AcctContainer( ) : m_UpdateInterval(0), m_NextUpdateTime(time(NULL)) +{ +} + +void AcctContainer::Initialize(uint32 updateInterval) +{ + m_UpdateInterval = updateInterval; +} + +void AcctContainer::AddAccount(Account* account,uint32 id, uint8 security, uint8 locale, uint8 tbc, bool banned, uint8 locked, std::string name, std::string I, std::string lastip) +{ + account->id = id; + account->security = security; + account->locale = locale; + account->tbc = tbc; + account->banned = banned; + account->locked = locked; + account->name = name; + account->I = I; + account->LastIp = lastip; +} + +void AcctContainer::AddCharacter(RealmCharacter* rcharacter, uint32 realmId, uint32 acctId, uint8 numChars) +{ + rcharacter->realmId = realmId; + rcharacter->acctId = acctId; + rcharacter->numChars = numChars; +} + +void AcctContainer::ReloadEverythingIfNeed() +{ + if(!m_UpdateInterval || m_NextUpdateTime > time(NULL)) + return; + + m_NextUpdateTime = time(NULL) + m_UpdateInterval; + + // Clear maps + m_characters.clear(); + m_banips.clear(); + m_accounts.clear(); + + LoadAll(); +} + +void AcctContainer::LoadAll() +{ + // Load accounts + QueryResult* result = dbRealmServer.PQuery("SELECT id,username,sha_pass_hash,gmlevel,last_ip,locked,tbc,locale FROM account"); + + uint32 count = 0; + + if(!result) + return; + + sLog.outString(); + + sLog.outString("Loading Accounts In Progress..."); + + barGoLink bar( result->GetRowCount()); + + // Periodic Database Update ... + dbRealmServer.Execute("UPDATE account_banned SET active = 0 WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate <> bandate"); + dbRealmServer.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate <> bandate"); + + Account *acct; + + do + { + Field *fields = result->Fetch(); + bool banned = false; + + bar.step(); + + QueryResult* banresult = dbRealmServer.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = %u AND active = 1", fields[0].GetUInt32()); + + if(banresult) + { + banned = true; + delete banresult; + } + + // Create the account + acct = new Account(); + + AddAccount(acct, fields[0].GetUInt32(), fields[3].GetUInt8(), fields[7].GetUInt8(), fields[6].GetUInt8(), banned, fields[5].GetUInt8(), fields[1].GetCppString(), fields[2].GetCppString(), fields[4].GetCppString()); + + m_accounts[acct->id] = acct; + + count++; + + }while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u accounts", count); + + delete result; + + // Now load Ban by ip + + result = dbRealmServer.PQuery("SELECT * FROM ip_banned"); + + BanIp* ban; + + // If there is no ban don't load + if(result) + { + sLog.outString(); + + count = 0; + + sLog.outString("Loading Ban Ip In Progress..."); + + barGoLink bar( result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + ban = new BanIp(); + AddBan(ban, fields[0].GetCppString()); + m_banips[ban->Ip] = ban; + count++; + + }while (result->NextRow()); + + delete result; + sLog.outString(); + + sLog.outString(">> Loaded %u ip banned", count); + + count = 0; + } + + // Now load Realm Characters + + result = dbRealmServer.PQuery("SELECT * FROM realmcharacters"); + + RealmCharacter *realmcharacter; + + // If there is no ban don't load + if(result) + { + sLog.outString(); + + count = 0; + + sLog.outString("Loading Realm Characters In Progress..."); + + barGoLink bar( result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + + bar.step(); + + realmcharacter = new RealmCharacter(); + + AddCharacter(realmcharacter, fields[0].GetUInt32(), fields[1].GetUInt32(), fields[2].GetUInt8()); + + // Since nothing on this table is unique, order it by increment count value + m_characters[count] = realmcharacter; + + count++; + + }while (result->NextRow()); + + delete result; + + sLog.outString(); + + sLog.outString(">> Loaded %u realm characters", count); + } + + +} + +Account* AcctContainer::FindAccountById(uint32 acctid) +{ + AccountList::const_iterator itr = m_accounts.find(acctid); + + if(itr != m_accounts.end()) + return itr->second; +} + +Account* AcctContainer::FindAccountByName(std::string name) +{ + for(AccountList::const_iterator itr = m_accounts.begin(); itr != m_accounts.end(); itr++) + { + if(!stricmp(itr->second->name.c_str(), name.c_str())) + return itr->second; + } + + return NULL; +} + +bool AcctContainer::IpBan(std::string ClientIp) +{ + for(IpBanList::const_iterator itr = m_banips.begin(); itr != m_banips.end(); itr++) + { + if(!stricmp(itr->second->Ip.c_str(), ClientIp.c_str())) + return true; + } + + return false; +} + +uint8 AcctContainer::GetNumChar(uint32 realmId, uint32 accountId) +{ + for(CharactersList::const_iterator itr = m_characters.begin(); itr != m_characters.end(); itr++) + { + if(itr->second->realmId == realmId && itr->second->acctId == accountId) + return itr->second->numChars; + } + + return 0; +}