diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Accounts/RBAC.h | 1 | ||||
-rw-r--r-- | src/server/game/Handlers/MailHandler.cpp | 131 |
2 files changed, 68 insertions, 64 deletions
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 60dea9cc11a..e8ea9a33134 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -61,6 +61,7 @@ enum RBACPermissions RBAC_PERM_LOG_GM_TRADE = 11,
RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES = 13,
RBAC_PERM_SKIP_CHECK_OVERSPEED_PING = 23,
+ RBAC_PERM_TWO_SIDE_INTERACTION_MAIL = 27,
RBAC_PERM_COMMANDS_SAVE_WITHOUT_DELAY = 30,
RBAC_PERM_COMMANDS_USE_UNSTUCK_WITH_ARGS = 31,
RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET = 32,
diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp index 787cd93576c..3cdd3d854a1 100644 --- a/src/server/game/Handlers/MailHandler.cpp +++ b/src/server/game/Handlers/MailHandler.cpp @@ -32,23 +32,16 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) { uint64 mailbox, unk3; - std::string receiver, subject, body; + std::string receiverName, subject, body; uint32 unk1, unk2, money, COD; uint8 unk4; - recvData >> mailbox; - recvData >> receiver; - - recvData >> subject; - - recvData >> body; - - recvData >> unk1; // stationery? - recvData >> unk2; // 0x00000000 - uint8 items_count; - recvData >> items_count; // attached items count + recvData >> mailbox >> receiverName >> subject >> body + >> unk1 // stationery? + >> unk2 // 0x00000000 + >> items_count; // attached items count - if (items_count > MAX_MAIL_ITEMS) // client limit + if (items_count > MAX_MAIL_ITEMS) // client limit { GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_TOO_MANY_ATTACHMENTS); recvData.rfinish(); // set to end to avoid warnings spam @@ -72,7 +65,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; - if (receiver.empty()) + if (receiverName.empty()) return; Player* player = _player; @@ -83,21 +76,26 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) return; } - uint64 rc = 0; - if (normalizePlayerName(receiver)) - rc = sObjectMgr->GetPlayerGUIDByName(receiver); + uint64 receiverGuid = 0; + if (normalizePlayerName(receiverName)) + receiverGuid = sObjectMgr->GetPlayerGUIDByName(receiverName); - if (!rc) + if (!receiverGuid) { - sLog->outInfo(LOG_FILTER_NETWORKIO, "Player %u is sending mail to %s (GUID: not existed!) with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", - player->GetGUIDLow(), receiver.c_str(), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); + sLog->outInfo(LOG_FILTER_NETWORKIO, "Player %u is sending mail to %s (GUID: not existed!) with subject %s " + "and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", + player->GetGUIDLow(), receiverName.c_str(), subject.c_str(), body.c_str(), + items_count, money, COD, unk1, unk2); player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND); return; } - sLog->outInfo(LOG_FILTER_NETWORKIO, "Player %u is sending mail to %s (GUID: %u) with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", player->GetGUIDLow(), receiver.c_str(), GUID_LOPART(rc), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); + sLog->outInfo(LOG_FILTER_NETWORKIO, "Player %u is sending mail to %s (GUID: %u) with subject %s and body %s " + "includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", + player->GetGUIDLow(), receiverName.c_str(), GUID_LOPART(receiverGuid), subject.c_str(), + body.c_str(), items_count, money, COD, unk1, unk2); - if (player->GetGUID() == rc) + if (player->GetGUID() == receiverGuid) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANNOT_SEND_TO_SELF); return; @@ -113,58 +111,62 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) return; } - Player* receive = ObjectAccessor::FindPlayer(rc); + Player* receiver = ObjectAccessor::FindPlayer(receiverGuid); - uint32 rc_team = 0; - uint8 mails_count = 0; //do not allow to send to one player more than 100 mails - uint8 receiveLevel = 0; + uint32 receiverTeam = 0; + uint8 mailsCount = 0; //do not allow to send to one player more than 100 mails + uint8 receiverLevel = 0; + uint32 receiverAccountId = 0; + bool canReceiveMailFromOtherFaction = false; - if (receive) + if (receiver) { - rc_team = receive->GetTeam(); - mails_count = receive->GetMailSize(); - receiveLevel = receive->getLevel(); + receiverTeam = receiver->GetTeam(); + mailsCount = receiver->GetMailSize(); + receiverLevel = receiver->getLevel(); + receiverAccountId = receiver->GetSession()->GetAccountId(); + canReceiveMailFromOtherFaction = receiver->GetSession()->HasPermission(RBAC_PERM_TWO_SIDE_INTERACTION_MAIL); } else { - rc_team = sObjectMgr->GetPlayerTeamByGUID(rc); + receiverTeam = sObjectMgr->GetPlayerTeamByGUID(receiverGuid); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_COUNT); - - stmt->setUInt32(0, GUID_LOPART(rc)); + stmt->setUInt32(0, GUID_LOPART(receiverGuid)); PreparedQueryResult result = CharacterDatabase.Query(stmt); - if (result) { Field* fields = result->Fetch(); - mails_count = fields[0].GetUInt64(); + mailsCount = fields[0].GetUInt64(); } stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_LEVEL); - - stmt->setUInt32(0, GUID_LOPART(rc)); + stmt->setUInt32(0, GUID_LOPART(receiverGuid)); result = CharacterDatabase.Query(stmt); - if (result) { Field* fields = result->Fetch(); - receiveLevel = fields[0].GetUInt8(); + receiverLevel = fields[0].GetUInt8(); } + + receiverAccountId = sObjectMgr->GetPlayerAccountIdByGUID(receiverGuid); + canReceiveMailFromOtherFaction = AccountMgr::HasPermission(receiverAccountId, RBAC_PERM_TWO_SIDE_INTERACTION_MAIL, realmID); } - //do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255.. - if (mails_count > 100) + + // do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255.. + if (mailsCount > 100) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_CAP_REACHED); return; } + // test the receiver's Faction... or all items are account bound bool accountBound = items_count ? true : false; for (uint8 i = 0; i < items_count; ++i) { - Item* item = player->GetItemByGuid(itemGUIDs[i]); - if (item) + if (Item* item = player->GetItemByGuid(itemGUIDs[i])) { ItemTemplate const* itemProto = item->GetTemplate(); if (!itemProto || !(itemProto->Flags & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT)) @@ -175,22 +177,21 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) } } - if (!accountBound && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) && player->GetTeam() != rc_team && AccountMgr::IsPlayerAccount(GetSecurity())) + if (!accountBound && player->GetTeam() != receiverTeam && // Sender and reciver are from different faction + (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) || // Config not enabled + !HasPermission(RBAC_PERM_TWO_SIDE_INTERACTION_MAIL) || // Sender cant mail interact with the other faction + !canReceiveMailFromOtherFaction)) // Receiver cant mail interact with the other faction { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM); return; } - if (receiveLevel < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) + if (receiverLevel < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) { SendNotification(GetTrinityString(LANG_MAIL_RECEIVER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)); return; } - uint32 rc_account = receive - ? receive->GetSession()->GetAccountId() - : sObjectMgr->GetPlayerAccountIdByGUID(rc); - Item* items[MAX_MAIL_ITEMS]; for (uint8 i = 0; i < items_count; ++i) @@ -216,7 +217,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) return; } - if (item->IsBoundAccountWide() && item->IsSoulBound() && player->GetSession()->GetAccountId() != rc_account) + if (item->IsBoundAccountWide() && item->IsSoulBound() && player->GetSession()->GetAccountId() != receiverAccountId) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS); return; @@ -264,28 +265,30 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) Item* item = items[i]; if (log) { - sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail item: %s (Entry: %u Count: %u) to player: %s (Account: %u)", - GetPlayerName().c_str(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount(), receiver.c_str(), rc_account); + sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail item: %s (Entry: %u Count: %u) " + "to player: %s (Account: %u)", GetPlayerName().c_str(), GetAccountId(), + item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount(), + receiverName.c_str(), receiverAccountId); } item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable player->MoveItemFromInventory(items[i]->GetBagSlot(), item->GetSlot(), true); item->DeleteFromInventoryDB(trans); // deletes item from character's inventory - item->SetOwnerGUID(rc); + item->SetOwnerGUID(receiverGuid); item->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone draft.AddItem(item); } // if item send to character at another account, then apply item delivery delay - needItemDelay = player->GetSession()->GetAccountId() != rc_account; + needItemDelay = player->GetSession()->GetAccountId() != receiverAccountId; } if (log && money > 0) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail money: %u to player: %s (Account: %u)", - GetPlayerName().c_str(), GetAccountId(), money, receiver.c_str(), rc_account); + GetPlayerName().c_str(), GetAccountId(), money, receiverName.c_str(), receiverAccountId); } } @@ -296,7 +299,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) draft .AddMoney(money) .AddCOD(COD) - .SendMailTo(trans, MailReceiver(receive, GUID_LOPART(rc)), MailSender(player), body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); + .SendMailTo(trans, MailReceiver(receiver, GUID_LOPART(receiverGuid)), MailSender(player), body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); @@ -459,17 +462,17 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData) if (m->COD > 0) //if there is COD, take COD money from player and send them to sender by mail { uint64 sender_guid = MAKE_NEW_GUID(m->sender, 0, HIGHGUID_PLAYER); - Player* receive = ObjectAccessor::FindPlayer(sender_guid); + Player* receiver = ObjectAccessor::FindPlayer(sender_guid); uint32 sender_accId = 0; if (HasPermission(RBAC_PERM_LOG_GM_TRADE) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) { std::string sender_name; - if (receive) + if (receiver) { - sender_accId = receive->GetSession()->GetAccountId(); - sender_name = receive->GetName(); + sender_accId = receiver->GetSession()->GetAccountId(); + sender_name = receiver->GetName(); } else { @@ -479,18 +482,18 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData) if (!sObjectMgr->GetPlayerNameByGUID(sender_guid, sender_name)) sender_name = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN); } - sLog->outCommand(GetAccountId(), "GM %s (Account: %u) receive mail item: %s (Entry: %u Count: %u) and send COD money: %u to player: %s (Account: %u)", + sLog->outCommand(GetAccountId(), "GM %s (Account: %u) receiver mail item: %s (Entry: %u Count: %u) and send COD money: %u to player: %s (Account: %u)", GetPlayerName().c_str(), GetAccountId(), it->GetTemplate()->Name1.c_str(), it->GetEntry(), it->GetCount(), m->COD, sender_name.c_str(), sender_accId); } - else if (!receive) + else if (!receiver) sender_accId = sObjectMgr->GetPlayerAccountIdByGUID(sender_guid); // check player existence - if (receive || sender_accId) + if (receiver || sender_accId) { MailDraft(m->subject, "") .AddMoney(m->COD) - .SendMailTo(trans, MailReceiver(receive, m->sender), MailSender(MAIL_NORMAL, m->receiver), MAIL_CHECK_MASK_COD_PAYMENT); + .SendMailTo(trans, MailReceiver(receiver, m->sender), MailSender(MAIL_NORMAL, m->receiver), MAIL_CHECK_MASK_COD_PAYMENT); } player->ModifyMoney(-int32(m->COD)); |