bool ClientSession::checkMsgForCommand(std::string msg, WorldPacket & recv_data) { if (msg.c_str()[0] == '!' || msg.c_str()[0] == '.') { if (strContains(msg, ".mute", false) || strContains(msg, ".unmute", false)) { if (ChatHandler(this).ParseDotCommands(msg.c_str()) > 0) SendPacketToNode(&recv_data); } else if (strContains(msg, ".ticket", false)) ChatHandler(this).ParseDotCommands(msg.c_str()); else SendPacketToNode(&recv_data); return true; } return false; }
bool WorldSession::UpdateClientIO(uint32 diff, PacketFilter& updater) { ///- Retrieve packets from the receive queue and call the appropriate handlers /// not process packets if socket already closed WorldPacket* packet = NULL; while (m_Socket && !m_Socket->IsClosed() && _recvQueue.next(packet, updater)) { const OpcodeHandler* opHandle = opcodeTable[packet->GetOpcode()]; // !=NULL checked in WorldSocket try { switch (opHandle->routing_node) { case ROUTE_NODE: SendPacketToNode(packet); break; case ROUTE_BOTH: SendPacketToNode(packet); case ROUTE_LOGON: { switch (opHandle->status) { case STATUS_LOGGEDIN: if (!_player) { // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets if (!m_playerRecentlyLogout) LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN", "the player has not logged in yet"); } else if (_player->IsInWorld()) { sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); (this->*opHandle->handler)(*packet); if (sLog->IsOutDebug() && packet->rpos() < packet->wpos()) LogUnprocessedTail(packet); } // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer break; case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT: if (!_player && !m_playerRecentlyLogout) LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT", "the player has not logged in yet and not recently logout"); else { // not expected _player or must checked in packet hanlder sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); (this->*opHandle->handler)(*packet); if (sLog->IsOutDebug() && packet->rpos() < packet->wpos()) LogUnprocessedTail(packet); } break; case STATUS_TRANSFER: if (!_player) LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player has not logged in yet"); else if (_player->IsInWorld()) LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player is still in world"); else { sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); (this->*opHandle->handler)(*packet); if (sLog->IsOutDebug() && packet->rpos() < packet->wpos()) LogUnprocessedTail(packet); } break; case STATUS_AUTHED: // prevent cheating with skip queue wait if (m_inQueue) { LogUnexpectedOpcode(packet, "STATUS_AUTHED", "the player not pass queue yet"); break; } // single from authed time opcodes send in to after logout time // and before other STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes. if (packet->GetOpcode() != CMSG_SET_ACTIVE_VOICE_CHANNEL) m_playerRecentlyLogout = false; sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); (this->*opHandle->handler)(*packet); if (sLog->IsOutDebug() && packet->rpos() < packet->wpos()) LogUnprocessedTail(packet); break; case STATUS_NEVER: sLog->outError("SESSION (account: %u, guidlow: %u, char: %s): received not allowed opcode %s (0x%.4X)", GetAccountId(), m_GUIDLow, _player ? _player->GetName() : "<none>", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode()); break; case STATUS_UNHANDLED: sLog->outDebug(LOG_FILTER_NETWORKIO, "SESSION (account: %u, guidlow: %u, char: %s): received not handled opcode %s (0x%.4X)", GetAccountId(), m_GUIDLow, _player ? _player->GetName() : "<none>", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode()); break; } } } } catch(ByteBufferException &) { sLog->outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.", packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId()); if (sLog->IsOutDebug()) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Dumping error causing packet:"); packet->hexlike(); } } delete packet; } return true; }
void ClientSession::HandleMessagechatOpcode(WorldPacket & recv_data) { uint32 type; uint32 lang; recv_data >> type; recv_data >> lang; if (type >= MAX_CHAT_MSG_TYPE) { sLog->outError("CHAT: Wrong message type received: %u", type); recv_data.rfinish(); return; } Player* sender = GetPlayer(); // prevent talking at unknown language (cheating) LanguageDesc const* langDesc = GetLanguageDescByID(lang); if (!langDesc) { SendNotification(LANG_UNKNOWN_LANGUAGE); recv_data.rfinish(); return; } bool ignoreChecks = false; if (lang == LANG_ADDON) { // LANG_ADDON is only valid for the following message types switch (type) { case CHAT_MSG_PARTY: case CHAT_MSG_RAID: case CHAT_MSG_GUILD: case CHAT_MSG_BATTLEGROUND: case CHAT_MSG_WHISPER: ignoreChecks = true; break; default: sLog->outError("Player %s (GUID: %u) sent a chatmessage with an invalid language/message type combination", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); recv_data.rfinish(); return; } } std::string to, channel, msg, temp; switch (type) { case CHAT_MSG_SAY: case CHAT_MSG_EMOTE: case CHAT_MSG_YELL: case CHAT_MSG_PARTY: case CHAT_MSG_PARTY_LEADER: case CHAT_MSG_GUILD: case CHAT_MSG_OFFICER: case CHAT_MSG_RAID: case CHAT_MSG_RAID_LEADER: case CHAT_MSG_RAID_WARNING: case CHAT_MSG_BATTLEGROUND: case CHAT_MSG_BATTLEGROUND_LEADER: recv_data >> msg; break; case CHAT_MSG_WHISPER: recv_data >> to; recv_data >> msg; break; case CHAT_MSG_CHANNEL: recv_data >> channel; recv_data >> msg; break; case CHAT_MSG_AFK: case CHAT_MSG_DND: recv_data >> msg; if (checkMsgForCommand(msg, recv_data) || checkMsgForMute(sender, recv_data)) return; ignoreChecks = true; break; } if (!ignoreChecks) { if (msg.empty()) return; if (checkMsgForCommand(msg, recv_data) || checkMsgForMute(sender, recv_data)) { if (!AccountMgr::IsVIPorPlayer(GetSecurity())) { /*if (Player* pPlayer = sender->GetSelectedPlayer()) sGMQualityManager->OnGMChat(CHAT_MSG_SYSTEM, sender, msg, pPlayer->GetName()); else*/ sGMQualityManager->OnGMChat(CHAT_MSG_SYSTEM, sender, msg); } return; } StripLineInvisibleChars(msg); } switch (type) { case CHAT_MSG_SAY: case CHAT_MSG_EMOTE: case CHAT_MSG_YELL: if (lang != LANG_ADDON) { if (!AccountMgr::IsVIPorPlayer(GetSecurity())) sGMQualityManager->OnGMChat(ChatMsg(type), sender, msg); else sGMQualityManager->OnPlayerChat(ChatMsg(type), sender, msg); } case CHAT_MSG_PARTY: case CHAT_MSG_PARTY_LEADER: case CHAT_MSG_GUILD: case CHAT_MSG_OFFICER: case CHAT_MSG_RAID: case CHAT_MSG_RAID_LEADER: case CHAT_MSG_RAID_WARNING: case CHAT_MSG_BATTLEGROUND: case CHAT_MSG_BATTLEGROUND_LEADER: { if (GetAntiSpamCounter() > LOGON_DOS_STRIKE_LIMIT || sLogon->CheckForSpam(msg)) { IncAntiSpamCounter(); SendFakeChatNotification(type, msg, lang); return; } SendPacketToNode(&recv_data); break; } case CHAT_MSG_WHISPER: { if (GetAntiSpamCounter() > LOGON_DOS_STRIKE_LIMIT || sLogon->CheckForSpam(msg)) { IncAntiSpamCounter(); SendFakeChatNotification(type, msg, lang); return; } if (sender->getLevel() < sLogon->getIntConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ)) { SendNotification(GetTrinityString(LANG_WHISPER_REQ), sLogon->getIntConfig(CONFIG_CHAT_WHISPER_LEVEL_REQ)); return; } if (!normalizePlayerName(to)) { SendPlayerNotFoundNotice(to); return; } Player* receiver = sObjectMgr->FindPlayerByName(to.c_str()); bool senderIsPlayer = AccountMgr::IsPlayerAccount(GetSecurity()); bool receiverIsPlayer = AccountMgr::IsPlayerAccount(receiver ? receiver->GetSession()->GetSecurity() : SEC_PLAYER); if (!receiver || (senderIsPlayer && !receiverIsPlayer && !receiver->isAcceptWhispers() && !receiver->IsInWhisperWhiteList(sender->GetGUID()))) { SendPlayerNotFoundNotice(to); return; } if (!sLogon->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT) && senderIsPlayer && receiverIsPlayer) if (GetPlayer()->GetTeam() != receiver->GetTeam()) { SendWrongFactionNotice(); return; } if (!GetPlayer()->CanSpeak() && !receiver->isGameMaster()) { SendNotification(GetTrinityString(LANG_GM_SILENCE), GetPlayer()->GetName()); return; } // If player is a Gamemaster and doesn't accept whisper, we auto-whitelist every player that the Gamemaster is talking to if (!senderIsPlayer && !sender->isAcceptWhispers() && !sender->IsInWhisperWhiteList(receiver->GetGUID())) sender->AddWhisperWhiteList(receiver->GetGUID()); GetPlayer()->Whisper(msg, lang, receiver->GetGUID()); if (sLogon->getBoolConfig(CONFIG_CHATLOG_WHISPER)) sLog->outChat("[WHISPER] Player %s tells %s: %s", GetPlayer()->GetName(), receiver ? receiver->GetName() : "<unknown>", msg.c_str()); if (lang != LANG_ADDON) { if (!AccountMgr::IsVIPorPlayer(GetSecurity())) sGMQualityManager->OnGMChat(ChatMsg(type), sender, msg, to); else sGMQualityManager->OnPlayerChat(ChatMsg(type), sender, msg, to); } break; } case CHAT_MSG_CHANNEL: { if ((channel.compare("GLaDOS") == 0) || (channel.compare("GM") == 0)) { if (AccountMgr::IsVIPorPlayer(GetSecurity())) return; if (ChatHandler(this).ParseCommands(msg.c_str()) > 0) return; } else { if (GetPlayer() && GetPlayer()->getLevel() < 10) return; if (GetAntiSpamCounter() > LOGON_DOS_STRIKE_LIMIT || sLogon->CheckForSpam(msg)) { IncAntiSpamCounter(); SendFakeChannelNotification(channel, msg, lang); return; } if (sLogon->getBoolConfig(CONFIG_CHATLOG_CHANNEL)) sLog->outChat("[CHANNEL] Player %s tells Channel [%s]: %s", GetPlayer()->GetName(), channel.c_str(), msg.c_str()); if (strContains(channel, " - ", false) || strContains(channel, "SucheNachGruppe", false)) { SendPacketToNode(&recv_data); //Send if the Channel is not on our LogonServer return; } if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) { if (Channel* chn = cMgr->GetChannel(channel, _player)) chn->Say(_player->GetGUID(), msg.c_str(), lang); } } break; } case CHAT_MSG_AFK: { if ((msg.empty() || !_player->isAFK())) //&& !_player->isInCombat()) { if (!_player->isAFK()) { if (msg.empty()) msg = GetTrinityString(LANG_PLAYER_AFK_DEFAULT); _player->afkMsg = msg; } _player->ToggleAFK(); if (_player->isAFK() && _player->isDND()) _player->ToggleDND(); } break; } case CHAT_MSG_DND: { if (msg.empty() || !_player->isDND()) { if (!_player->isDND()) { if (msg.empty()) msg = GetTrinityString(LANG_PLAYER_DND_DEFAULT); _player->dndMsg = msg; } _player->ToggleDND(); if (_player->isDND() && _player->isAFK()) _player->ToggleAFK(); } break; } default: sLog->outError("CHAT: unknown message type %u, lang: %u", type, lang); break; } }