mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-11 03:31:08 +00:00
[Bug Fix] Fix IP Exemptions. (#2189)
* [Bug Fix] Fix IP Exemptions. - IP Exemptions were broken due to GetAccountID() returning 0 in logic somehow, resolved this by setting a variable to GetAccountID() at the beginning of the method. - Fixed weird IP messages where the long form of IP was displayed instead of the string form. - Fixes edge case where IP rule may be set to -1 and this will make anyone get instantly kicked if IP Exemptions were enabled as their IP Count would always be greater than -1. * Update client.cpp * Update client.cpp * Update clientlist.cpp * Update clientlist.cpp
This commit is contained in:
+110
-109
@@ -721,38 +721,40 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
|
||||
}
|
||||
|
||||
bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
if (GetAccountID() == 0) {
|
||||
LogInfo("Enter world with no logged in account");
|
||||
auto account_id = GetAccountID();
|
||||
if (!account_id) {
|
||||
LogInfo("Enter world with no logged in account.");
|
||||
eqs->Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(GetAdmin() < 0)
|
||||
{
|
||||
LogInfo("Account banned or suspended");
|
||||
if (GetAdmin() < 0) {
|
||||
LogInfo("Account [{}] is banned or suspended.", account_id);
|
||||
eqs->Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (RuleB(World, EnableIPExemptions) || RuleI(World, MaxClientsPerIP) >= 0) {
|
||||
if (
|
||||
RuleB(World, EnableIPExemptions) ||
|
||||
RuleI(World, MaxClientsPerIP) > 0
|
||||
) {
|
||||
client_list.GetCLEIP(GetIP()); //Check current CLE Entry IPs against incoming connection
|
||||
}
|
||||
|
||||
EnterWorld_Struct *ew=(EnterWorld_Struct *)app->pBuffer;
|
||||
strn0cpy(char_name, ew->name, 64);
|
||||
auto ew = (EnterWorld_Struct *) app->pBuffer;
|
||||
strn0cpy(char_name, ew->name, sizeof(char_name));
|
||||
|
||||
EQApplicationPacket *outapp;
|
||||
uint32 tmpaccid = 0;
|
||||
charid = database.GetCharacterInfo(char_name, &tmpaccid, &zone_id, &instance_id);
|
||||
if (charid == 0) {
|
||||
uint32 temporary_account_id = 0;
|
||||
charid = database.GetCharacterInfo(char_name, &temporary_account_id, &zone_id, &instance_id);
|
||||
if (!charid) {
|
||||
LogInfo("Could not get CharInfo for [{}]", char_name);
|
||||
eqs->Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Make sure this account owns this character
|
||||
if (tmpaccid != GetAccountID()) {
|
||||
LogInfo("This account does not own the character named [{}]", char_name);
|
||||
if (temporary_account_id != account_id) {
|
||||
LogInfo("Account [{}] does not own the character named [{}] from account [{}]", account_id, char_name, temporary_account_id);
|
||||
eqs->Close();
|
||||
return true;
|
||||
}
|
||||
@@ -761,25 +763,26 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
// (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration)
|
||||
if (!is_player_zoning) {
|
||||
size_t character_limit = EQ::constants::StaticLookup(eqs->ClientVersion())->CharacterCreationLimit;
|
||||
if (character_limit > EQ::constants::CHARACTER_CREATION_LIMIT) { character_limit = EQ::constants::CHARACTER_CREATION_LIMIT; }
|
||||
if (eqs->ClientVersion() == EQ::versions::ClientVersion::Titanium) { character_limit = Titanium::constants::CHARACTER_CREATION_LIMIT; }
|
||||
if (character_limit > EQ::constants::CHARACTER_CREATION_LIMIT) {
|
||||
character_limit = EQ::constants::CHARACTER_CREATION_LIMIT;
|
||||
}
|
||||
|
||||
std::string tgh_query = StringFormat(
|
||||
"SELECT "
|
||||
"`id`, "
|
||||
"name, "
|
||||
"`level`, "
|
||||
"last_login "
|
||||
"FROM "
|
||||
"character_data "
|
||||
"WHERE `account_id` = %i ORDER BY `name` LIMIT %u", GetAccountID(), character_limit);
|
||||
auto tgh_results = database.QueryDatabase(tgh_query);
|
||||
if (eqs->ClientVersion() == EQ::versions::ClientVersion::Titanium) {
|
||||
character_limit = Titanium::constants::CHARACTER_CREATION_LIMIT;
|
||||
}
|
||||
|
||||
auto query = fmt::format(
|
||||
"SELECT `id`, `name`, `level`, `last_login` FROM character_data WHERE `account_id` = {} ORDER BY `name` LIMIT {}",
|
||||
account_id,
|
||||
character_limit
|
||||
);
|
||||
auto results = database.QueryDatabase(query);
|
||||
|
||||
/* Check GoHome */
|
||||
if (ew->return_home && !ew->tutorial) {
|
||||
bool home_enabled = false;
|
||||
for (auto row = tgh_results.begin(); row != tgh_results.end(); ++row) {
|
||||
if (strcasecmp(row[1], char_name) == 0) {
|
||||
for (auto row : results) {
|
||||
if (!strcasecmp(row[1], char_name)) {
|
||||
if (RuleB(World, EnableReturnHomeButton)) {
|
||||
int now = time(nullptr);
|
||||
if ((now - atoi(row[3])) >= RuleI(World, MinOfflineTimeToReturnHome)) {
|
||||
@@ -792,9 +795,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
|
||||
if (home_enabled) {
|
||||
zone_id = database.MoveCharacterToBind(charid, 4);
|
||||
}
|
||||
else {
|
||||
LogInfo("[{}] is trying to go home before they're able", char_name);
|
||||
} else {
|
||||
LogInfo("[{}] is trying to go home before they're able.", char_name);
|
||||
database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able.");
|
||||
eqs->Close();
|
||||
return true;
|
||||
@@ -804,9 +806,12 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
/* Check Tutorial*/
|
||||
if (RuleB(World, EnableTutorialButton) && (ew->tutorial || StartInTutorial)) {
|
||||
bool tutorial_enabled = false;
|
||||
for (auto row = tgh_results.begin(); row != tgh_results.end(); ++row) {
|
||||
if (strcasecmp(row[1], char_name) == 0) {
|
||||
if (RuleB(World, EnableTutorialButton) && ((uint8)atoi(row[2]) <= RuleI(World, MaxLevelForTutorial))) {
|
||||
for (auto row : results) {
|
||||
if (!strcasecmp(row[1], char_name)) {
|
||||
if (
|
||||
RuleB(World, EnableTutorialButton) &&
|
||||
std::stoi(row[2]) <= RuleI(World, MaxLevelForTutorial)
|
||||
) {
|
||||
tutorial_enabled = true;
|
||||
break;
|
||||
}
|
||||
@@ -816,9 +821,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
if (tutorial_enabled) {
|
||||
zone_id = RuleI(World, TutorialZoneID);
|
||||
database.MoveCharacterToZone(charid, zone_id);
|
||||
}
|
||||
else {
|
||||
LogInfo("[{}] is trying to go to tutorial but are not allowed", char_name);
|
||||
} else {
|
||||
LogInfo("[{}] is trying to go to the Tutorial but they are not allowed.", char_name);
|
||||
database.SetHackerFlag(GetAccountName(), char_name, "MQTutorial: player tried to enter the tutorial without having tutorial enabled for this character.");
|
||||
eqs->Close();
|
||||
return true;
|
||||
@@ -826,17 +830,17 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
}
|
||||
}
|
||||
|
||||
if (zone_id == 0 || !ZoneName(zone_id)) {
|
||||
if (!zone_id || !ZoneName(zone_id)) {
|
||||
// This is to save people in an invalid zone, once it's removed from the DB
|
||||
database.MoveCharacterToZone(charid, ZoneID("arena"));
|
||||
LogInfo("Zone not found in database zone_id=[{}], moveing char to arena character:[{}]", zone_id, char_name);
|
||||
LogInfo("Zone [{}] not found, moving [{}] to Arena.", zone_id, char_name);
|
||||
}
|
||||
|
||||
if(instance_id > 0)
|
||||
{
|
||||
if (!database.VerifyInstanceAlive(instance_id, GetCharID()) ||
|
||||
!database.VerifyZoneInstance(zone_id, instance_id))
|
||||
{
|
||||
if (instance_id) {
|
||||
if (
|
||||
!database.VerifyInstanceAlive(instance_id, GetCharID()) ||
|
||||
!database.VerifyZoneInstance(zone_id, instance_id)
|
||||
) {
|
||||
zone_id = database.MoveCharacterToInstanceSafeReturn(charid, zone_id, instance_id);
|
||||
instance_id = 0;
|
||||
}
|
||||
@@ -845,83 +849,80 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
if(!is_player_zoning) {
|
||||
database.SetGroupID(char_name, 0, charid);
|
||||
database.SetLoginFlags(charid, false, false, 1);
|
||||
}
|
||||
else{
|
||||
uint32 groupid = database.GetGroupID(char_name);
|
||||
if(groupid > 0){
|
||||
char* leader = 0;
|
||||
char leaderbuf[64] = {0};
|
||||
if((leader = database.GetGroupLeaderForLogin(char_name, leaderbuf)) && strlen(leader)>1){
|
||||
auto outapp3 = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct));
|
||||
GroupJoin_Struct* gj=(GroupJoin_Struct*)outapp3->pBuffer;
|
||||
} else {
|
||||
auto group_id = database.GetGroupID(char_name);
|
||||
if (group_id) {
|
||||
auto leader_name = database.GetGroupLeaderForLogin(char_name);
|
||||
if (!leader_name.empty()) {
|
||||
auto pack = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct));
|
||||
auto gj = (GroupJoin_Struct*) pack->pBuffer;
|
||||
gj->action=8;
|
||||
strcpy(gj->yourname, char_name);
|
||||
strcpy(gj->membername, leader);
|
||||
QueuePacket(outapp3);
|
||||
safe_delete(outapp3);
|
||||
strn0cpy(gj->yourname, char_name, sizeof(gj->yourname));
|
||||
strn0cpy(gj->membername, leader_name.c_str(), sizeof(gj->membername));
|
||||
QueuePacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outapp = new EQApplicationPacket(OP_MOTD);
|
||||
std::string tmp;
|
||||
if (database.GetVariable("MOTD", tmp)) {
|
||||
outapp->size = tmp.length() + 1;
|
||||
auto outapp = new EQApplicationPacket(OP_MOTD);
|
||||
std::string motd_message;
|
||||
if (database.GetVariable("MOTD", motd_message)) {
|
||||
outapp->size = motd_message.length() + 1;
|
||||
outapp->pBuffer = new uchar[outapp->size];
|
||||
memset(outapp->pBuffer,0,outapp->size);
|
||||
strcpy((char*)outapp->pBuffer, tmp.c_str());
|
||||
|
||||
} else {
|
||||
// Null Message of the Day. :)
|
||||
memset(outapp->pBuffer, 0, outapp->size);
|
||||
strcpy((char*)outapp->pBuffer, motd_message.c_str());
|
||||
} else { // Null Message of the Day. :)
|
||||
outapp->size = 1;
|
||||
outapp->pBuffer = new uchar[outapp->size];
|
||||
outapp->pBuffer[0] = 0;
|
||||
}
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
// set mailkey - used for duration of character session
|
||||
int MailKey = emu_random.Int(1, INT_MAX);
|
||||
int mail_key = emu_random.Int(1, INT_MAX);
|
||||
|
||||
database.SetMailKey(charid, GetIP(), MailKey);
|
||||
database.SetMailKey(charid, GetIP(), mail_key);
|
||||
if (UCSServerAvailable_) {
|
||||
const WorldConfig *Config = WorldConfig::get();
|
||||
auto config = WorldConfig::get();
|
||||
std::string buffer;
|
||||
|
||||
EQ::versions::UCSVersion ConnectionType = EQ::versions::ucsUnknown;
|
||||
auto connection_type = EQ::versions::ucsUnknown;
|
||||
|
||||
// chat server packet
|
||||
switch (GetClientVersion()) {
|
||||
case EQ::versions::ClientVersion::Titanium:
|
||||
ConnectionType = EQ::versions::ucsTitaniumChat;
|
||||
break;
|
||||
case EQ::versions::ClientVersion::SoF:
|
||||
ConnectionType = EQ::versions::ucsSoFCombined;
|
||||
break;
|
||||
case EQ::versions::ClientVersion::SoD:
|
||||
ConnectionType = EQ::versions::ucsSoDCombined;
|
||||
break;
|
||||
case EQ::versions::ClientVersion::UF:
|
||||
ConnectionType = EQ::versions::ucsUFCombined;
|
||||
break;
|
||||
case EQ::versions::ClientVersion::RoF:
|
||||
ConnectionType = EQ::versions::ucsRoFCombined;
|
||||
break;
|
||||
case EQ::versions::ClientVersion::RoF2:
|
||||
ConnectionType = EQ::versions::ucsRoF2Combined;
|
||||
break;
|
||||
default:
|
||||
ConnectionType = EQ::versions::ucsUnknown;
|
||||
break;
|
||||
case EQ::versions::ClientVersion::Titanium:
|
||||
connection_type = EQ::versions::ucsTitaniumChat;
|
||||
break;
|
||||
case EQ::versions::ClientVersion::SoF:
|
||||
connection_type = EQ::versions::ucsSoFCombined;
|
||||
break;
|
||||
case EQ::versions::ClientVersion::SoD:
|
||||
connection_type = EQ::versions::ucsSoDCombined;
|
||||
break;
|
||||
case EQ::versions::ClientVersion::UF:
|
||||
connection_type = EQ::versions::ucsUFCombined;
|
||||
break;
|
||||
case EQ::versions::ClientVersion::RoF:
|
||||
connection_type = EQ::versions::ucsRoFCombined;
|
||||
break;
|
||||
case EQ::versions::ClientVersion::RoF2:
|
||||
connection_type = EQ::versions::ucsRoF2Combined;
|
||||
break;
|
||||
default:
|
||||
connection_type = EQ::versions::ucsUnknown;
|
||||
break;
|
||||
}
|
||||
|
||||
buffer = StringFormat("%s,%i,%s.%s,%c%08X",
|
||||
Config->ChatHost.c_str(),
|
||||
Config->ChatPort,
|
||||
Config->ShortName.c_str(),
|
||||
buffer = fmt::format("{},{},{}.{},{}{:08X}",
|
||||
config->ChatHost,
|
||||
config->ChatPort,
|
||||
config->ShortName,
|
||||
GetCharName(),
|
||||
ConnectionType,
|
||||
MailKey
|
||||
static_cast<char>(connection_type),
|
||||
mail_key
|
||||
);
|
||||
|
||||
outapp = new EQApplicationPacket(OP_SetChatServer, (buffer.length() + 1));
|
||||
@@ -933,21 +934,21 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
|
||||
|
||||
// mail server packet
|
||||
switch (GetClientVersion()) {
|
||||
case EQ::versions::ClientVersion::Titanium:
|
||||
ConnectionType = EQ::versions::ucsTitaniumMail;
|
||||
break;
|
||||
default:
|
||||
// retain value from previous switch
|
||||
break;
|
||||
case EQ::versions::ClientVersion::Titanium:
|
||||
connection_type = EQ::versions::ucsTitaniumMail;
|
||||
break;
|
||||
default:
|
||||
// retain value from previous switch
|
||||
break;
|
||||
}
|
||||
|
||||
buffer = StringFormat("%s,%i,%s.%s,%c%08X",
|
||||
Config->MailHost.c_str(),
|
||||
Config->MailPort,
|
||||
Config->ShortName.c_str(),
|
||||
buffer = fmt::format("{},{},{}.{},{}{:08X}",
|
||||
config->MailHost,
|
||||
config->MailPort,
|
||||
config->ShortName,
|
||||
GetCharName(),
|
||||
ConnectionType,
|
||||
MailKey
|
||||
static_cast<char>(connection_type),
|
||||
mail_key
|
||||
);
|
||||
|
||||
outapp = new EQApplicationPacket(OP_SetChatServer2, (buffer.length() + 1));
|
||||
|
||||
Reference in New Issue
Block a user