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;
    }
}