void WorldSession::SaveTutorialsData() { static SqlStatementID updTutorial ; static SqlStatementID insTutorial ; switch(m_tutorialState) { case TUTORIALDATA_CHANGED: { SqlStatement stmt = CharacterDatabase.CreateStatement(updTutorial, "UPDATE character_tutorial SET tut0=?, tut1=?, tut2=?, tut3=?, tut4=?, tut5=?, tut6=?, tut7=? WHERE account = ?"); for (int i = 0; i < 8; ++i) stmt.addUInt32(m_Tutorials[i]); stmt.addUInt32(GetAccountId()); stmt.Execute(); } break; case TUTORIALDATA_NEW: { SqlStatement stmt = CharacterDatabase.CreateStatement(insTutorial, "INSERT INTO character_tutorial (account,tut0,tut1,tut2,tut3,tut4,tut5,tut6,tut7) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); stmt.addUInt32(GetAccountId()); for (int i = 0; i < 8; ++i) stmt.addUInt32(m_Tutorials[i]); stmt.Execute(); } break; case TUTORIALDATA_UNCHANGED: break; } m_tutorialState = TUTORIALDATA_UNCHANGED; }
void Corpse::SaveToDB() { // prevent DB data inconsistence problems and duplicates RealmDataDatabase.BeginTransaction(); DeleteFromDB(); static SqlStatementID saveCorpse; SqlStatement stmt = RealmDataDatabase.CreateStatement(saveCorpse, "INSERT INTO corpse (guid,player,position_x,position_y,position_z,orientation,zone,map,data,time,corpse_type,instance) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); stmt.addUInt64(GetGUIDLow()); stmt.addUInt64(GUID_LOPART(GetOwnerGUID())); stmt.addFloat(GetPositionX()); stmt.addFloat(GetPositionY()); stmt.addFloat(GetPositionZ()); stmt.addFloat(GetOrientation()); stmt.addUInt32(GetZoneId()); stmt.addUInt32(GetMapId()); stmt.addString(GetUInt32ValuesString()); stmt.addUInt64(m_time); stmt.addUInt32(GetType()); stmt.addInt32(GetInstanceId()); stmt.Execute(); RealmDataDatabase.CommitTransaction(); }
void GuildFinderMgr::RemoveAllMembershipRequestsFromPlayer(uint32 playerId) { CharacterDatabase.BeginTransaction(); for (MembershipRequestStore::iterator itr = m_membershipRequests.begin(); itr != m_membershipRequests.end(); ++itr) { std::vector<MembershipRequest>::iterator itr2 = itr->second.begin(); for(; itr2 != itr->second.end(); ++itr2) if (itr2->GetPlayerGuid() == playerId) break; if (itr2 == itr->second.end()) continue; static SqlStatementID deleteFinderApplicant; CharacterDatabase.BeginTransaction(); SqlStatement stmt = CharacterDatabase.CreateStatement(deleteFinderApplicant, "DELETE FROM guild_finder_applicant WHERE guildId = ? AND playerGuid = ?"); stmt.addUInt32(itr2->GetGuildId()); stmt.addUInt32(itr2->GetPlayerGuid()); stmt.Execute(); CharacterDatabase.CommitTransaction(); itr->second.erase(itr2); // Notify the guild master and officers the list changed if (Guild* guild = sGuildMgr.GetGuildById(itr->first)) SendApplicantListUpdate(*guild); } CharacterDatabase.CommitTransaction(); }
void GuildFinderMgr::RemoveMembershipRequest(uint32 playerId, uint32 guildId) { std::vector<MembershipRequest>::iterator itr = m_membershipRequests[guildId].begin(); for(; itr != m_membershipRequests[guildId].end(); ++itr) if (itr->GetPlayerGuid() == playerId) break; if (itr == m_membershipRequests[guildId].end()) return; static SqlStatementID deleteFinderApplicant; SqlStatement stmt = CharacterDatabase.CreateStatement(deleteFinderApplicant, "DELETE FROM guild_finder_applicant WHERE guildId = ? AND playerGuid = ?"); stmt.addUInt32(itr->GetGuildId()); stmt.addUInt32(itr->GetPlayerGuid()); stmt.Execute(); m_membershipRequests[guildId].erase(itr); // Notify the applicant his submittion has been removed if (Player* player = sObjectAccessor.FindPlayer(ObjectGuid(HIGHGUID_PLAYER, playerId))) SendMembershipRequestListUpdate(*player); // Notify the guild master and officers the list changed if (Guild* guild = sGuildMgr.GetGuildById(guildId)) SendApplicantListUpdate(*guild); }
void GuildFinderMgr::AddMembershipRequest(uint32 guildGuid, MembershipRequest const& request) { m_membershipRequests[guildGuid].push_back(request); static SqlStatementID insertFinderApplicant; CharacterDatabase.BeginTransaction(); SqlStatement stmt = CharacterDatabase.CreateStatement(insertFinderApplicant, "REPLACE INTO guild_finder_applicant (guildId, playerGuid, availability, classRole, interests, comment, submitTime) VALUES(?, ?, ?, ?, ?, ?, ?)"); stmt.addUInt32(request.GetGuildId()); stmt.addUInt32(request.GetPlayerGuid()); stmt.addUInt8(request.GetAvailability()); stmt.addUInt8(request.GetClassRoles()); stmt.addUInt8(request.GetInterests()); stmt.addString(request.GetComment()); stmt.addUInt32(request.GetSubmitTime()); stmt.Execute(); CharacterDatabase.CommitTransaction(); // Notify the applicant his submittion has been added if (Player* player = sObjectAccessor.FindPlayer(ObjectGuid(HIGHGUID_PLAYER, request.GetPlayerGuid()))) SendMembershipRequestListUpdate(*player); // Notify the guild master and officers the list changed if (Guild* guild = sGuildMgr.GetGuildById(guildGuid)) SendApplicantListUpdate(*guild); }
void InstanceData::SaveToDB() { std::string data = GetSaveData(); if (data.empty()) return; static SqlStatementID updateInstance; SqlStatement stmt = RealmDataDatabase.CreateStatement(updateInstance, "UPDATE instance SET data = ? WHERE id = ?"); stmt.addString(data); stmt.addUInt32(instance->GetInstanceId()); stmt.Execute(); }
void Antispam::logSpam(MessageBlock& messageBlock, std::string const& reason) { if (!LogsDatabase || !sWorld.getConfig(CONFIG_BOOL_LOGSDB_CHAT)) return; static SqlStatementID insLogSpam; SqlStatement logStmt = LogsDatabase.CreateStatement(insLogSpam, "INSERT INTO logs_spamdetect SET accountId=?, guid=?, message=?, reason=?"); logStmt.addUInt32(messageBlock.fromAccount); logStmt.addUInt32(messageBlock.fromGuid.GetCounter()); logStmt.addString(messageBlock.msg); logStmt.addString(reason); logStmt.Execute(); }
void GuildFinderMgr::SetGuildSettings(uint32 guildGuid, LFGuildSettings const& settings) { m_guildSettings[guildGuid] = settings; static SqlStatementID replaceGuildFinderSettings; SqlStatement stmt = CharacterDatabase.CreateStatement(replaceGuildFinderSettings, "REPLACE INTO guild_finder_guild_settings (guildId, availability, classRoles, interests, level, listed, comment) VALUES(?, ?, ?, ?, ?, ?, ?)"); stmt.addUInt32(settings.GetGuid()); stmt.addUInt8(settings.GetAvailability()); stmt.addUInt8(settings.GetClassRoles()); stmt.addUInt8(settings.GetInterests()); stmt.addUInt8(settings.GetLevel()); stmt.addUInt8(settings.IsListed()); stmt.addString(settings.GetComment()); stmt.Execute(); }
void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResultAutoPtr result, uint32 accountId, std::string newname) { WorldSession * session = sWorld.FindSession(accountId); if (!session) return; if (!result) { WorldPacket data(SMSG_CHAR_RENAME, 1); data << uint8(CHAR_CREATE_ERROR); session->SendPacket(&data); return; } uint32 guidLow = result->Fetch()[0].GetUInt32(); uint64 guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER); std::string oldname = result->Fetch()[1].GetCppString(); static SqlStatementID changeCharName; static SqlStatementID deleteDeclinedName; RealmDataDatabase.BeginTransaction(); SqlStatement stmt = RealmDataDatabase.CreateStatement(changeCharName, "UPDATE characters set name = ?, at_login = at_login & ~ ? WHERE guid = ?"); stmt.addString(newname); stmt.addUInt32(uint32(AT_LOGIN_RENAME)); stmt.addUInt32(guidLow); stmt.Execute(); stmt = RealmDataDatabase.CreateStatement(deleteDeclinedName, "DELETE FROM character_declinedname WHERE guid = ?"); stmt.PExecute(guidLow); RealmDataDatabase.CommitTransaction(); sLog.outLog(LOG_CHAR, "Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", session->GetAccountId(), session->GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str()); WorldPacket data(SMSG_CHAR_RENAME, 1+8+(newname.size()+1)); data << uint8(RESPONSE_SUCCESS); data << uint64(guid); data << newname; session->SendPacket(&data); }
void GuildFinderMgr::DeleteGuild(uint32 guildId) { std::vector<MembershipRequest>::iterator itr = m_membershipRequests[guildId].begin(); while (itr != m_membershipRequests[guildId].end()) { uint32 applicant = itr->GetPlayerGuid(); CharacterDatabase.BeginTransaction(); static SqlStatementID deleteFinderApplicant; static SqlStatementID deleteGuildFinderSettings; SqlStatement stmt = CharacterDatabase.CreateStatement(deleteFinderApplicant, "DELETE FROM guild_finder_applicant WHERE guildId = ? AND playerGuid = ?"); stmt.addUInt32(itr->GetGuildId()); stmt.addUInt32(itr->GetPlayerGuid()); stmt.Execute(); SqlStatement stmt2 = CharacterDatabase.CreateStatement(deleteGuildFinderSettings, "DELETE FROM guild_finder_guild_settings WHERE guildId = ?"); stmt2.addUInt32(itr->GetGuildId()); stmt2.Execute(); CharacterDatabase.CommitTransaction(); m_membershipRequests[guildId].erase(itr); // Notify the applicant his submition has been removed if (Player* player = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, applicant))) SendMembershipRequestListUpdate(*player); } m_membershipRequests.erase(guildId); m_guildSettings.erase(guildId); // Notify the guild master the list changed (even if he's not a GM any more, not sure if needed) if (Guild* guild = sGuildMgr.GetGuildById(guildId)) SendApplicantListUpdate(*guild); }
bool Item::LoadFromDB(uint32 guidLow, Field *fields, ObjectGuid ownerGuid) { // create item before any checks for store correct guid // and allow use "FSetState(ITEM_REMOVED); SaveToDB();" for deleting item from DB Object::_Create(ObjectGuid(HIGHGUID_ITEM, guidLow)); if (!LoadValues(fields[0].GetString())) { sLog.outError("Item #%d have broken data in `data` field. Can't be loaded.", guidLow); return false; } SetText(fields[1].GetCppString()); bool need_save = false; // need explicit save data at load fixes // overwrite possible wrong/corrupted guid ObjectGuid new_item_guid = ObjectGuid(HIGHGUID_ITEM, guidLow); if (GetGuidValue(OBJECT_FIELD_GUID) != new_item_guid) { SetGuidValue(OBJECT_FIELD_GUID, new_item_guid); need_save = true; } ItemPrototype const* proto = GetProto(); if(!proto) return false; // update max durability (and durability) if need if(proto->MaxDurability!= GetUInt32Value(ITEM_FIELD_MAXDURABILITY)) { SetUInt32Value(ITEM_FIELD_MAXDURABILITY,proto->MaxDurability); if(GetUInt32Value(ITEM_FIELD_DURABILITY) > proto->MaxDurability) SetUInt32Value(ITEM_FIELD_DURABILITY,proto->MaxDurability); need_save = true; } // recalculate suffix factor if(GetItemRandomPropertyId() < 0) { if(UpdateItemSuffixFactor()) need_save = true; } // Remove bind flag for items vs NO_BIND set if (IsSoulBound() && proto->Bonding == NO_BIND) { ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_BINDED, false); need_save = true; } // update duration if need, and remove if not need if ((proto->Duration == 0) != (GetUInt32Value(ITEM_FIELD_DURATION) == 0)) { SetUInt32Value(ITEM_FIELD_DURATION, proto->Duration); need_save = true; } // set correct owner if (!ownerGuid.IsEmpty() && GetOwnerGuid() != ownerGuid) { SetOwnerGuid(ownerGuid); need_save = true; } // set correct wrapped state if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) { // wrapped item must be wrapper (used version that not stackable) if (!(proto->Flags & ITEM_FLAG_WRAPPER) || GetMaxStackCount() > 1) { RemoveFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED); need_save = true; static SqlStatementID delGifts ; // also cleanup for sure gift table SqlStatement stmt = CharacterDatabase.CreateStatement(delGifts, "DELETE FROM character_gifts WHERE item_guid = ?"); stmt.PExecute(GetGUIDLow()); } } if (need_save) // normal item changed state set not work at loading { static SqlStatementID updItem ; SqlStatement stmt = CharacterDatabase.CreateStatement(updItem, "UPDATE item_instance SET data = ?, owner_guid = ? WHERE guid = ?"); std::ostringstream ss; for(uint16 i = 0; i < m_valuesCount; ++i ) ss << GetUInt32Value(i) << " "; stmt.addString(ss); stmt.addUInt32(GetOwnerGuid().GetCounter()); stmt.addUInt32(guidLow); stmt.Execute(); } return true; }
void Item::SaveToDB() { uint32 guid = GetGUIDLow(); switch (uState) { case ITEM_NEW: { static SqlStatementID delItem ; static SqlStatementID insItem ; SqlStatement stmt = CharacterDatabase.CreateStatement(delItem, "DELETE FROM item_instance WHERE guid = ?"); stmt.PExecute(guid); std::ostringstream ss; for (uint16 i = 0; i < m_valuesCount; ++i) ss << GetUInt32Value(i) << " "; stmt = CharacterDatabase.CreateStatement(insItem, "INSERT INTO item_instance (guid,owner_guid,data) VALUES (?, ?, ?)"); stmt.PExecute(guid, GetOwnerGuid().GetCounter(), ss.str().c_str()); } break; case ITEM_CHANGED: { static SqlStatementID updInstance ; static SqlStatementID updGifts ; SqlStatement stmt = CharacterDatabase.CreateStatement(updInstance, "UPDATE item_instance SET data = ?, owner_guid = ? WHERE guid = ?"); std::ostringstream ss; for (uint16 i = 0; i < m_valuesCount; ++i) ss << GetUInt32Value(i) << " "; stmt.PExecute(ss.str().c_str(), GetOwnerGuid().GetCounter(), guid); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) { stmt = CharacterDatabase.CreateStatement(updGifts, "UPDATE character_gifts SET guid = ? WHERE item_guid = ?"); stmt.PExecute(GetOwnerGuid().GetCounter(), GetGUIDLow()); } } break; case ITEM_REMOVED: { static SqlStatementID delItemText; static SqlStatementID delInst ; static SqlStatementID delGifts ; static SqlStatementID delLoot ; if (uint32 item_text_id = GetUInt32Value(ITEM_FIELD_ITEM_TEXT_ID)) { SqlStatement stmt = CharacterDatabase.CreateStatement(delItemText, "DELETE FROM item_text WHERE id = ?"); stmt.PExecute(item_text_id); } SqlStatement stmt = CharacterDatabase.CreateStatement(delInst, "DELETE FROM item_instance WHERE guid = ?"); stmt.PExecute(guid); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) { stmt = CharacterDatabase.CreateStatement(delGifts, "DELETE FROM character_gifts WHERE item_guid = ?"); stmt.PExecute(GetGUIDLow()); } if (HasSavedLoot()) { stmt = CharacterDatabase.CreateStatement(delLoot, "DELETE FROM item_loot WHERE guid = ?"); stmt.PExecute(GetGUIDLow()); } delete this; return; } case ITEM_UNCHANGED: return; } if (m_lootState == ITEM_LOOT_CHANGED || m_lootState == ITEM_LOOT_REMOVED) { static SqlStatementID delLoot ; SqlStatement stmt = CharacterDatabase.CreateStatement(delLoot, "DELETE FROM item_loot WHERE guid = ?"); stmt.PExecute(GetGUIDLow()); } if (loot && (m_lootState == ITEM_LOOT_NEW || m_lootState == ITEM_LOOT_CHANGED)) { if (Player* owner = GetOwner()) { static SqlStatementID saveGold ; static SqlStatementID saveLoot ; // save money as 0 itemid data if (loot->GetGoldAmount()) { SqlStatement stmt = CharacterDatabase.CreateStatement(saveGold, "INSERT INTO item_loot (guid,owner_guid,itemid,amount,property) VALUES (?, ?, 0, ?, 0)"); stmt.PExecute(GetGUIDLow(), owner->GetGUIDLow(), loot->GetGoldAmount()); } SqlStatement stmt = CharacterDatabase.CreateStatement(saveLoot, "INSERT INTO item_loot (guid,owner_guid,itemid,amount,property) VALUES (?, ?, ?, ?, ?)"); // save items and quest items (at load its all will added as normal, but this not important for item loot case) LootItemList lootList; loot->GetLootItemsListFor(owner, lootList); for (LootItemList::const_iterator lootItr = lootList.begin(); lootItr != lootList.end(); ++lootItr) { LootItem* lootItem = *lootItr; stmt.addUInt32(GetGUIDLow()); stmt.addUInt32(owner->GetGUIDLow()); stmt.addUInt32(lootItem->itemId); stmt.addUInt8(lootItem->count); stmt.addInt32(lootItem->randomPropertyId); stmt.Execute(); } } } if (m_lootState != ITEM_LOOT_NONE && m_lootState != ITEM_LOOT_TEMPORARY) SetLootState(ITEM_LOOT_UNCHANGED); SetState(ITEM_UNCHANGED); }
bool PlayerLogger::SaveToDB(PlayerLogMask mask, bool removeSaved, bool insideTransaction) { bool written = false; uint64 serverStart = uint64(sWorld.GetStartTime()); for (uint8 i = 0; i < MAX_PLAYER_LOG_ENTITIES; ++i) { if ((mask & CalcLogMask(PlayerLogEntity(i))) == 0 || data[i] == NULL) continue; if (!insideTransaction) CharacterDatabase.BeginTransaction(); written = true; for (uint8 id = 0; id < data[i]->size(); ++id) { switch (PlayerLogEntity(i)) { case PLAYER_LOG_DAMAGE_GET: { PlayerLogDamage info = *(PlayerLogDamage*)(&data[i]->at(id)); static SqlStatementID dmgGetStmt; SqlStatement stmt = CharacterDatabase.CreateStatement(dmgGetStmt, "INSERT INTO playerlog_damage_get SET guid = ?, `time` = ?, aggressor = ?, isPlayer = ?, damage = ?, spell = ?"); stmt.addUInt32(playerGuid); stmt.addUInt64(info.timestamp + serverStart); stmt.addUInt32(info.GetId()); stmt.addBool(info.IsPlayer()); stmt.addInt32(info.damage); stmt.addUInt16(info.spell); stmt.Execute(); } break; case PLAYER_LOG_DAMAGE_DONE: { PlayerLogDamage info = *(PlayerLogDamage*)(&data[i]->at(id)); static SqlStatementID dmgDoneStmt; SqlStatement stmt = CharacterDatabase.CreateStatement(dmgDoneStmt, "INSERT INTO playerlog_damage_done SET guid = ?, `time` = ?, victim = ?, isPlayer = ?, damage = ?, spell = ?"); stmt.addUInt32(playerGuid); stmt.addUInt64(info.timestamp + serverStart); stmt.addUInt32(info.GetId()); stmt.addBool(info.IsPlayer()); stmt.addInt32(info.damage); stmt.addUInt16(info.spell); stmt.Execute(); } break; case PLAYER_LOG_LOOTING: { PlayerLogLooting info = *(PlayerLogLooting*)(&data[i]->at(id)); static SqlStatementID lootStmt; SqlStatement stmt = CharacterDatabase.CreateStatement(lootStmt, "INSERT INTO playerlog_looting SET guid = ?, `time`= ?, item = ?, sourceType = ?, sourceEntry = ?"); stmt.addUInt32(playerGuid); stmt.addUInt64(info.timestamp + serverStart); stmt.addUInt32(info.GetItemEntry()); stmt.addUInt8(uint8(info.GetLootSourceType())); stmt.addUInt32(info.droppedBy); stmt.Execute(); } break; case PLAYER_LOG_TRADE: { PlayerLogTrading info = *(PlayerLogTrading*)(&data[i]->at(id)); static SqlStatementID tradeStmt; SqlStatement stmt = CharacterDatabase.CreateStatement(tradeStmt, "INSERT INTO playerlog_trading SET guid = ?, `time`= ?, itemEntry = ?, itemGuid = ?, aquired = ?, partner = ?"); stmt.addUInt32(playerGuid); stmt.addUInt64(info.timestamp + serverStart); stmt.addUInt32(info.GetItemEntry()); stmt.addUInt32(info.itemGuid); stmt.addBool(info.IsItemAquired()); stmt.addUInt16(info.partner); stmt.Execute(); } break; case PLAYER_LOG_KILL: { PlayerLogKilling info = *(PlayerLogKilling*)(&data[i]->at(id)); static SqlStatementID killStmt; SqlStatement stmt = CharacterDatabase.CreateStatement(killStmt, "INSERT INTO playerlog_killing SET guid = ?, `time`= ?, iskill = ?, entry = ?, victimGuid = ?"); stmt.addUInt32(playerGuid); stmt.addUInt64(info.timestamp + serverStart); stmt.addBool(info.IsKill()); stmt.addUInt32(info.GetUnitEntry()); stmt.addUInt32(info.unitGuid); stmt.Execute(); } break; case PLAYER_LOG_POSITION: { PlayerLogPosition info = *(PlayerLogPosition*)(&data[i]->at(id)); static SqlStatementID posStmt; SqlStatement stmt = CharacterDatabase.CreateStatement(posStmt, "INSERT INTO playerlog_position SET guid = ?, `time`= ?, map = ?, posx = ?, posy = ?, posz = ?"); stmt.addUInt32(playerGuid); stmt.addUInt64(info.timestamp + serverStart); stmt.addUInt16(info.map); stmt.addFloat(info.x); stmt.addFloat(info.y); stmt.addFloat(info.z); stmt.Execute(); } break; case PLAYER_LOG_PROGRESS: { PlayerLogProgress info = *(PlayerLogProgress*)(&data[i]->at(id)); static SqlStatementID progStmt; SqlStatement stmt = CharacterDatabase.CreateStatement(progStmt, "INSERT INTO playerlog_progress SET guid = ?, `time` = ?, type = ?, level = ?, data = ?, map = ?, posx = ?, posy = ?, posz = ?"); stmt.addUInt32(playerGuid); stmt.addUInt64(info.timestamp + serverStart); stmt.addUInt8(info.progressType); stmt.addUInt8(info.level); stmt.addUInt16(info.data); stmt.addUInt16(info.map); stmt.addFloat(info.x); stmt.addFloat(info.y); stmt.addFloat(info.z); stmt.Execute(); } } } Stop(PlayerLogEntity(i)); if (removeSaved) data[i]->clear(); } if (written && !insideTransaction) CharacterDatabase.CommitTransaction(); return written; }
void WorldSession::HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data) { uint64 guid; CHECK_PACKET_SIZE(recv_data, 8); recv_data >> guid; // not accept declined names for unsupported languages std::string name; if (!sObjectMgr.GetPlayerNameByGUID(guid, name)) { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } std::wstring wname; if (!Utf8toWStr(name, wname)) { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } if (!isCyrillicCharacter(wname[0])) // name already stored as only single alphabet using { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } std::string name2; DeclinedName declinedname; CHECK_PACKET_SIZE(recv_data, recv_data.rpos() + 1); recv_data >> name2; if (name2 != name) // character have different name { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { CHECK_PACKET_SIZE(recv_data, recv_data.rpos() + 1); recv_data >> declinedname.name[i]; if (!normalizePlayerName(declinedname.name[i])) { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } } if (!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname, 0), declinedname)) { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } static SqlStatementID deleteDeclinedName; static SqlStatementID insertDeclinedName; RealmDataDatabase.BeginTransaction(); SqlStatement stmt = RealmDataDatabase.CreateStatement(deleteDeclinedName, "DELETE FROM character_declinedname WHERE guid = ?"); stmt.PExecute(GUID_LOPART(guid)); stmt = RealmDataDatabase.CreateStatement(insertDeclinedName, "INSERT INTO character_declinedname (guid, genitive, dative, accusative, instrumental, prepositional) VALUES (?, ?, ?, ?, ?, ?)"); stmt.addUInt32(GUID_LOPART(guid)); stmt.addString(declinedname.name[0]); stmt.addString(declinedname.name[1]); stmt.addString(declinedname.name[2]); stmt.addString(declinedname.name[3]); stmt.addString(declinedname.name[4]); stmt.Execute(); RealmDataDatabase.CommitTransaction(); WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(0); // OK data << uint64(guid); SendPacket(&data); }
void WorldSession::HandleCharCreateOpcode(WorldPacket & recv_data) { CHECK_PACKET_SIZE(recv_data, 1+1+1+1+1+1+1+1+1+1); std::string name; uint8 race_, class_; recv_data >> name; // recheck with known string size CHECK_PACKET_SIZE(recv_data, (name.size()+1)+1+1+1+1+1+1+1+1+1); recv_data >> race_; recv_data >> class_; WorldPacket data(SMSG_CHAR_CREATE, 1); // returned with diff.values in all cases if (!HasPermissions(PERM_GMT)) { if (uint32 mask = sWorld.getConfig(CONFIG_CHARACTERS_CREATING_DISABLED)) { bool disabled = false; uint32 team = Player::TeamForRace(race_); switch (team) { case ALLIANCE: disabled = mask & (1<<0); break; case HORDE: disabled = mask & (1<<1); break; } if (disabled) { data << uint8(CHAR_CREATE_DISABLED); SendPacket(&data); return; } } } ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_); ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race_); if (!classEntry || !raceEntry) { data << uint8(CHAR_CREATE_FAILED); SendPacket(&data); sLog.outLog(LOG_DEFAULT, "ERROR: Class: %u or Race %u not found in DBC (Wrong DBC files?) or Cheater?", class_, race_); return; } // prevent character creating Expansion race without Expansion account if (raceEntry->addon > Expansion()) { data << uint8(CHAR_CREATE_EXPANSION); sLog.outLog(LOG_DEFAULT, "ERROR: Expansion %u account:[%d] tried to Create character with expansion %u race (%u)",Expansion(),GetAccountId(),raceEntry->addon,race_); SendPacket(&data); return; } // prevent character creating Expansion class without Expansion account // TODO: use possible addon field in ChrClassesEntry in next dbc version if (Expansion() < 2 && class_ == CLASS_DEATH_KNIGHT) { data << uint8(CHAR_CREATE_EXPANSION); sLog.outLog(LOG_DEFAULT, "ERROR: Not Expansion 2 account:[%d] but tried to Create character with expansion 2 class (%u)",GetAccountId(),class_); SendPacket(&data); return; } // prevent character creating with invalid name if (!normalizePlayerName(name)) { data << uint8(CHAR_NAME_INVALID_CHARACTER); SendPacket(&data); sLog.outLog(LOG_DEFAULT, "ERROR: Account:[%d] but tried to Create character with empty [name] ",GetAccountId()); return; } // check name limitations if (!ObjectMgr::IsValidName(name,true)) { data << uint8(CHAR_NAME_INVALID_CHARACTER); SendPacket(&data); return; } if (!HasPermissions(PERM_GMT) && sObjectMgr.IsReservedName(name)) { data << uint8(CHAR_NAME_RESERVED); SendPacket(&data); return; } if (sObjectMgr.GetPlayerGUIDByName(name)) { data << uint8(CHAR_CREATE_NAME_IN_USE); SendPacket(&data); return; } QueryResultAutoPtr resultacct = AccountsDatabase.PQuery("SELECT SUM(characters_count) FROM realm_characters WHERE account_id = '%u'", GetAccountId()); if (resultacct) { Field *fields=resultacct->Fetch(); uint32 acctcharcount = fields[0].GetUInt32(); if (acctcharcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_ACCOUNT)) { data << uint8(CHAR_CREATE_ACCOUNT_LIMIT); SendPacket(&data); return; } } QueryResultAutoPtr result = RealmDataDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%u'", GetAccountId()); uint8 charcount = 0; if (result) { Field *fields=result->Fetch(); charcount = fields[0].GetUInt8(); if (charcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_REALM)) { data << uint8(CHAR_CREATE_SERVER_LIMIT); SendPacket(&data); return; } } bool AllowTwoSideAccounts = !sWorld.IsPvPRealm() || sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || HasPermissions(PERM_GMT); uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS); bool have_same_race = false; if (!AllowTwoSideAccounts || skipCinematics == 1) { QueryResultAutoPtr result2 = RealmDataDatabase.PQuery("SELECT DISTINCT race FROM characters WHERE account = '%u' %s", GetAccountId(),skipCinematics == 1 ? "" : "LIMIT 1"); if (result2) { uint32 team_= Player::TeamForRace(race_); Field* field = result2->Fetch(); uint8 race = field[0].GetUInt32(); // need to check team only for first character // TODO: what to if account already has characters of both races? if (!AllowTwoSideAccounts) { uint32 team=0; if (race > 0) team = Player::TeamForRace(race); if (team != team_) { data << uint8(CHAR_CREATE_PVP_TEAMS_VIOLATION); SendPacket(&data); return; } } if (skipCinematics == 1) { // TODO: check if cinematic already shown? (already logged in?; cinematic field) while (race_ != race && result2->NextRow()) { field = result2->Fetch(); race = field[0].GetUInt32(); } have_same_race = race_ == race; } } } // extract other data required for player creating uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId; recv_data >> gender >> skin >> face; recv_data >> hairStyle >> hairColor >> facialHair >> outfitId; Player * pNewChar = new Player(this); if (!pNewChar->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_PLAYER), name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId)) { // Player not create (race/class problem?) delete pNewChar; data << uint8(CHAR_CREATE_ERROR); SendPacket(&data); return; } if ((have_same_race && skipCinematics == 1) || skipCinematics == 2) pNewChar->setCinematic(true); // not show intro // Player created, save it now pNewChar->SaveToDB(); charcount += 1; // direct to be sure that character count has proper value (also should fix possible multi char create in some cases) static SqlStatementID updateRealmChars; SqlStatement stmt = AccountsDatabase.CreateStatement(updateRealmChars, "UPDATE realm_characters SET characters_count = ? WHERE account_id = ? AND realm_id = ?"); stmt.addUInt8(charcount); stmt.addUInt32(GetAccountId()); stmt.addUInt32(realmID); stmt.Execute(); delete pNewChar; // created only to call SaveToDB() data << uint8(CHAR_CREATE_SUCCESS); SendPacket(&data); std::string IP_str = GetRemoteAddress(); sLog.outDetail("Account: %d (IP: %s) Create Character:[%s]",GetAccountId(),IP_str.c_str(),name.c_str()); sLog.outLog(LOG_CHAR, "Account: %d (IP: %s) Create Character:[%s]",GetAccountId(),IP_str.c_str(),name.c_str()); }
void Item::SaveToDB() { uint32 guid = GetGUIDLow(); switch(m_state) { case ITEM_NEW: { DeleteFromDB(guid); std::ostringstream ss; for (uint16 i = 0; i < m_valuesCount; ++i) ss << GetUInt32Value(i) << " "; static SqlStatementID insItem; SqlStatement stmt = CharacterDatabase.CreateStatement(insItem, "INSERT INTO item_instance (guid, owner_guid, data, text) VALUES (?, ?, ?, ?)"); stmt.PExecute(guid, GetOwnerGuid().GetCounter(), ss.str().c_str(), m_text.c_str()); break; } case ITEM_CHANGED: { std::ostringstream ss; for (uint16 i = 0; i < m_valuesCount; ++i) ss << GetUInt32Value(i) << " "; static SqlStatementID updInstance; SqlStatement stmt = CharacterDatabase.CreateStatement(updInstance, "UPDATE item_instance SET data = ?, owner_guid = ?, text = ? WHERE guid = ?"); stmt.PExecute(ss.str().c_str(), GetOwnerGuid().GetCounter(), m_text.c_str(), guid); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) { static SqlStatementID updGifts; stmt = CharacterDatabase.CreateStatement(updGifts, "UPDATE character_gifts SET guid = ? WHERE item_guid = ?"); stmt.PExecute(GetOwnerGuid().GetCounter(), GetGUIDLow()); } break; } case ITEM_REMOVED: { DeleteFromDB(guid); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) DeleteGiftsFromDB(); if (HasSavedLoot()) DeleteLootFromDB(); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE)) DeleteRefundDataFromDB(); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_BOP_TRADEABLE)) DeleteSoulboundTradeableFromDB(); delete this; return; } case ITEM_UNCHANGED: return; } if (m_lootState == ITEM_LOOT_CHANGED || m_lootState == ITEM_LOOT_REMOVED) DeleteLootFromDB(); if (m_lootState == ITEM_LOOT_NEW || m_lootState == ITEM_LOOT_CHANGED) { if (Player* owner = GetOwner()) { // save money as 0 itemid data if (loot.gold) { static SqlStatementID saveGold; SqlStatement stmt = CharacterDatabase.CreateStatement(saveGold, "INSERT INTO item_loot (guid, owner_guid, itemid, amount, suffix, property) VALUES (?, ?, 0, ?, 0, 0)"); stmt.PExecute(GetGUIDLow(), owner->GetGUIDLow(), loot.gold); } static SqlStatementID saveLoot; SqlStatement stmt = CharacterDatabase.CreateStatement(saveLoot, "INSERT INTO item_loot (guid, owner_guid, itemid, amount, suffix, property) VALUES (?, ?, ?, ?, ?, ?)"); // save items and quest items (at load its all will added as normal, but this not important for item loot case) for (size_t i = 0; i < loot.GetMaxSlotInLootFor(owner); ++i) { QuestItem* qitem = NULL; LootItem* item = loot.LootItemInSlot(i, owner, &qitem); if (!item) continue; // questitems use the blocked field for other purposes if (!qitem && item->is_blocked) continue; stmt.addUInt32(GetGUIDLow()); stmt.addUInt32(owner->GetGUIDLow()); stmt.addUInt32(item->itemid); stmt.addUInt8(item->count); stmt.addUInt32(item->randomSuffix); stmt.addInt32(item->randomPropertyId); stmt.Execute(); } } } if (m_lootState != ITEM_LOOT_NONE && m_lootState != ITEM_LOOT_TEMPORARY) SetLootState(ITEM_LOOT_UNCHANGED); SetState(ITEM_UNCHANGED); }
/// Logon Proof command handler bool AuthSocket::_HandleLogonProof() { DEBUG_LOG("Entering _HandleLogonProof"); ///- Read the packet sAuthLogonProof_C lp; if(!recv((char *)&lp, sizeof(sAuthLogonProof_C))) return false; ///- Check if the client has one of the expected version numbers bool valid_version = FindBuildInfo(_build) != NULL; /// <ul><li> If the client has no valid version if(!valid_version) { if (this->patch_ != ACE_INVALID_HANDLE) return false; ///- Check if we have the apropriate patch on the disk // file looks like: 65535enGB.mpq char tmp[64]; snprintf(tmp, 24, "./patches/%d%s.mpq", _build, _localizationName.c_str()); char filename[PATH_MAX]; if (ACE_OS::realpath(tmp, filename) != NULL) { patch_ = ACE_OS::open(filename, GENERIC_READ | FILE_FLAG_SEQUENTIAL_SCAN); } if (patch_ == ACE_INVALID_HANDLE) { // no patch found ByteBuffer pkt; pkt << (uint8) CMD_AUTH_LOGON_CHALLENGE; pkt << (uint8) 0x00; pkt << (uint8) WOW_FAIL_VERSION_INVALID; DEBUG_LOG("[AuthChallenge] %u is not a valid client version!", _build); DEBUG_LOG("[AuthChallenge] Patch %s not found", tmp); send((char const*)pkt.contents(), pkt.size()); return true; } XFER_INIT xferh; ACE_OFF_T file_size = ACE_OS::filesize(this->patch_); if (file_size == -1) { close_connection(); return false; } if (!PatchCache::instance()->GetHash(tmp, (uint8*)&xferh.md5)) { // calculate patch md5, happens if patch was added while realmd was running PatchCache::instance()->LoadPatchMD5(tmp); PatchCache::instance()->GetHash(tmp, (uint8*)&xferh.md5); } uint8 data[2] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_VERSION_UPDATE}; send((const char*)data, sizeof(data)); memcpy(&xferh, "0\x05Patch", 7); xferh.cmd = CMD_XFER_INITIATE; xferh.file_size = file_size; send((const char*)&xferh, sizeof(xferh)); return true; } /// </ul> ///- Continue the SRP6 calculation based on data received from the client BigNumber A; A.SetBinary(lp.A, 32); // SRP safeguard: abort if A==0 if (A.isZero()) return false; Sha1Hash sha; sha.UpdateBigNumbers(&A, &B, NULL); sha.Finalize(); BigNumber u; u.SetBinary(sha.GetDigest(), 20); BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N); uint8 t[32]; uint8 t1[16]; uint8 vK[40]; memcpy(t, S.AsByteArray(32), 32); for (int i = 0; i < 16; ++i) { t1[i] = t[i * 2]; } sha.Initialize(); sha.UpdateData(t1, 16); sha.Finalize(); for (int i = 0; i < 20; ++i) { vK[i * 2] = sha.GetDigest()[i]; } for (int i = 0; i < 16; ++i) { t1[i] = t[i * 2 + 1]; } sha.Initialize(); sha.UpdateData(t1, 16); sha.Finalize(); for (int i = 0; i < 20; ++i) { vK[i * 2 + 1] = sha.GetDigest()[i]; } K.SetBinary(vK, 40); uint8 hash[20]; sha.Initialize(); sha.UpdateBigNumbers(&N, NULL); sha.Finalize(); memcpy(hash, sha.GetDigest(), 20); sha.Initialize(); sha.UpdateBigNumbers(&g, NULL); sha.Finalize(); for (int i = 0; i < 20; ++i) { hash[i] ^= sha.GetDigest()[i]; } BigNumber t3; t3.SetBinary(hash, 20); sha.Initialize(); sha.UpdateData(_login); sha.Finalize(); uint8 t4[SHA_DIGEST_LENGTH]; memcpy(t4, sha.GetDigest(), SHA_DIGEST_LENGTH); sha.Initialize(); sha.UpdateBigNumbers(&t3, NULL); sha.UpdateData(t4, SHA_DIGEST_LENGTH); sha.UpdateBigNumbers(&s, &A, &B, &K, NULL); sha.Finalize(); BigNumber M; M.SetBinary(sha.GetDigest(), 20); ///- Check if SRP6 results match (password is correct), else send an error if (!memcmp(M.AsByteArray(), lp.M1, 20)) { sLog.outBasic("User '%s' successfully authenticated", _login.c_str()); uint8 OS; if (!strcmp(operatingSystem_.c_str(), "Win")) OS = CLIENT_OS_WIN; else if (!strcmp(operatingSystem_.c_str(), "OSX")) OS = CLIENT_OS_OSX; else if (!strcmp(operatingSystem_.c_str(), "CHA") || !strcmp(operatingSystem_.c_str(), "CHAT")) OS = CLIENT_OS_CHAT; else { OS = CLIENT_OS_UNKNOWN; AccountsDatabase.escape_string(operatingSystem_); sLog.outLog(LOG_WARDEN, "Client %s got unsupported operating system (%s)", _safelogin.c_str(), operatingSystem_.c_str()); } ///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account // No SQL injection (escaped user name) and IP address as received by socket const char* K_hex = K.AsHexStr(); QueryResultAutoPtr result = AccountsDatabase.PQuery("SELECT account_id FROM account WHERE username = '******'", _safelogin.c_str()); if (!result) { if (_build > 6005) // > 1.12.2 { char data[4] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT, 3, 0}; send(data, sizeof(data)); } else { // 1.x not react incorrectly at 4-byte message use 3 as real error char data[2] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT}; send(data, sizeof(data)); } return true; } uint32 accId = result->Fetch()->GetUInt32(); // direct to be sure that values will be set before character choose, this will slow down logging in a bit ;p AccountsDatabase.DirectPExecute("UPDATE account_session SET session_key = '%s' WHERE account_id = '%u'", K_hex, accId); static SqlStatementID updateAccount; SqlStatement stmt = AccountsDatabase.CreateStatement(updateAccount, "UPDATE account SET last_ip = ?, last_local_ip = ?, last_login = NOW(), locale_id = ?, failed_logins = 0, client_os_version_id = ? WHERE account_id = ?"); std::string tmpIp = get_remote_address(); stmt.addString(tmpIp.c_str()); stmt.addString(localIp_.c_str()); stmt.addUInt8(uint8(GetLocaleByName(_localizationName))); stmt.addUInt8(OS); stmt.addUInt32(accId); stmt.DirectExecute(); OPENSSL_free((void*)K_hex); ///- Finish SRP6 and send the final result to the client sha.Initialize(); sha.UpdateBigNumbers(&A, &M, &K, NULL); sha.Finalize(); SendProof(sha); ///- Set _authed to true! _authed = true; } else { if (_build > 6005) // > 1.12.2 { char data[4] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT, 3, 0}; send(data, sizeof(data)); } else { // 1.x not react incorrectly at 4-byte message use 3 as real error char data[2] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT}; send(data, sizeof(data)); } sLog.outBasic("[AuthChallenge] account %s tried to login with wrong password!",_login.c_str ()); uint32 MaxWrongPassCount = sConfig.GetIntDefault("WrongPass.MaxCount", 0); if (MaxWrongPassCount > 0) { static SqlStatementID updateAccountFailedLogins; //Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP SqlStatement stmt = AccountsDatabase.CreateStatement(updateAccountFailedLogins, "UPDATE account SET failed_logins = failed_logins + 1 WHERE username = ?"); stmt.addString(_login); stmt.Execute(); if (QueryResultAutoPtr loginfail = AccountsDatabase.PQuery("SELECT account_id, failed_logins FROM account WHERE username = '******'", _safelogin.c_str())) { Field* fields = loginfail->Fetch(); uint32 failed_logins = fields[1].GetUInt32(); if (failed_logins >= MaxWrongPassCount) { uint32 WrongPassBanTime = sConfig.GetIntDefault("WrongPass.BanTime", 600); bool WrongPassBanType = sConfig.GetBoolDefault("WrongPass.BanType", false); if (WrongPassBanType) { uint32 acc_id = fields[0].GetUInt32(); AccountsDatabase.PExecute("INSERT INTO account_punishment VALUES ('%u', '%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+%u, 'Realm', 'Incorrect password for: %u times. Ban for: %u seconds')", acc_id, PUNISHMENT_BAN, WrongPassBanTime, failed_logins, WrongPassBanTime); sLog.outBasic("[AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times", _login.c_str(), WrongPassBanTime, failed_logins); } else { std::string current_ip = get_remote_address(); AccountsDatabase.escape_string(current_ip); AccountsDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Realm','Incorrect password for: %u times. Ban for: %u seconds')", current_ip.c_str(), WrongPassBanTime, failed_logins, WrongPassBanTime); sLog.outBasic("[AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times", current_ip.c_str(), WrongPassBanTime, _login.c_str(), failed_logins); } } } } } return true; }