From f19f0a19f284aae6d170b04aa6b4aea2aaa06609 Mon Sep 17 00:00:00 2001 From: Machiavelli Date: Tue, 28 Jun 2011 21:35:18 +0200 Subject: Core/Players: Fix possible (exploitable) data desynchronisation that would lead to repeating the same quest while already having received the rewards. --- src/server/game/Entities/Player/Player.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 09b56e79257..56dd4d01b03 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -14960,17 +14960,24 @@ void Player::RewardQuest(Quest const *pQuest, uint32 reward, Object* questGiver, GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST, quest_id); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY, quest_id); } - } else if (pQuest->IsWeekly()) + } + else if (pQuest->IsWeekly()) SetWeeklyQuestStatus(quest_id); RemoveActiveQuest(quest_id); m_RewardedQuests.insert(quest_id); m_RewardedQuestsSave[quest_id] = true; + // StoreNewItem, mail reward, etc. save data directly to the database + // to prevent exploitable data desynchronisation we save the quest status to the database too + // (to prevent rewarding this quest another time while rewards were already given out) + SQLTransaction trans = SQLTransaction(NULL); + _SaveQuestStatus(trans); + if (announce) SendQuestReward(pQuest, XP, questGiver); - // cast spells after mark quest complete (some spells have quest completed state reqyurements in spell_area data) + // cast spells after mark quest complete (some spells have quest completed state requirements in spell_area data) if (pQuest->GetRewSpellCast() > 0) CastSpell(this, pQuest->GetRewSpellCast(), true); else if (pQuest->GetRewSpell() > 0) @@ -18629,6 +18636,10 @@ void Player::_SaveMail(SQLTransaction& trans) void Player::_SaveQuestStatus(SQLTransaction& trans) { + bool isTransaction = !trans.null(); + if (!isTransaction) + trans = CharacterDatabase.BeginTransaction(); + QuestStatusSaveMap::iterator saveItr; QuestStatusMap::iterator statusItr; @@ -18661,6 +18672,9 @@ void Player::_SaveQuestStatus(SQLTransaction& trans) } m_RewardedQuestsSave.clear(); + + if (!isTransaction) + CharacterDatabase.CommitTransaction(trans); } void Player::_SaveDailyQuestStatus(SQLTransaction& trans) -- cgit v1.2.3