void CChat::CreateJoinChannel(CChatChanMember * pByMember, LPCTSTR pszName, LPCTSTR pszPassword) { ADDTOCALLSTACK("CChat::CreateJoinChannel"); if ( ! IsValidName( pszName, false )) { pByMember->GetClient()->addChatSystemMessage( CHATMSG_InvalidConferenceName ); } else if (IsDuplicateChannelName(pszName)) { pByMember->GetClient()->addChatSystemMessage( CHATMSG_AlreadyAConference ); } else { if ( CreateChannel(pszName, ((pszPassword != NULL) ? pszPassword : ""), pByMember)) JoinChannel(pByMember, pszName, ((pszPassword != NULL) ? pszPassword : "")); } }
void CChat::EventMsg( CClient * pClient, const NCHAR * pszText, int len, CLanguageID lang ) // Text from a client { ADDTOCALLSTACK("CChat::EventMsg"); // ARGS: // len = length of the pszText string in NCHAR's. // CChatChanMember * pMe = pClient; ASSERT(pMe); // newer clients do not send the 'chat button' packet, leading to all kinds of problems // with the client not being initialised properly for chat (e.g. blank name and exceptions // when leaving a chat room) - if chat is not active then we must simulate the chat button // event before processing the chat message if (pMe->IsChatActive() == false) { // simulate the chat button being clicked pClient->Event_ChatButton(NULL); // if chat isn't active now then cancel processing the event if (pMe->IsChatActive() == false) return; } CChatChannel * pChannel = pMe->GetChannel(); TCHAR szText[MAX_TALK_BUFFER * 2]; CvtNUNICODEToSystem( szText, sizeof(szText), pszText, len ); // The 1st character is a command byte, join channel, private message someone, etc etc TCHAR * szMsg = szText+1; switch ( szText[0] ) { case 'a': // a = client typed a plain message in the text entry area { // Check for a chat command here if (szMsg[0] == '/') { DoCommand(pMe, szMsg + 1); break; } if (!pChannel) { not_in_a_channel: pMe->SendChatMsg(CHATMSG_MustBeInAConference); return; } // Not a chat command, must be speech pChannel->MemberTalk(pMe, szMsg, lang); break; }; case 'A': // A = change the channel password { if (!pChannel) goto not_in_a_channel; pChannel->ChangePassword(pMe, szMsg); break; }; case 'b': // b = client joining an existing channel { // Look for second double quote to separate channel from password size_t i = 1; for (; szMsg[i] != '\0'; i++) if (szMsg[i] == '"') break; szMsg[i] = '\0'; TCHAR * pszPassword = szMsg + i + 1; if (pszPassword[0] == ' ') // skip leading space if any pszPassword++; JoinChannel( pMe, szMsg + 1, pszPassword); break; }; case 'c': // c = client creating (and joining) new channel { TCHAR * pszPassword = NULL; size_t iMsgLength = strlen(szMsg); for (size_t i = 0; i < iMsgLength; i++) { if (szMsg[i] == '{') // OK, there's a password here { szMsg[i] = 0; pszPassword = szMsg + i + 1; size_t iPasswordLength = strlen(pszPassword); for (i = 0; i < iPasswordLength; i++) { if (pszPassword[i] == '}') { pszPassword[i] = '\0'; break; } } break; } } CreateJoinChannel(pMe, szMsg, pszPassword); break; }; case 'd': // d = (/rename x) rename conference { if (!pChannel) goto not_in_a_channel; pMe->RenameChannel(szMsg); break; }; case 'e': // e = Send a private message to .... { if (!pChannel) goto not_in_a_channel; TCHAR buffer[2048]; strcpy(buffer, szMsg); // Separate the recipient from the message (look for a space) size_t i = 0; size_t bufferLength = strlen(buffer); for (; i < bufferLength; i++) { if (buffer[i] == ' ') { buffer[i] = '\0'; break; } } pChannel->SendPrivateMessage(pMe, buffer, buffer+i+1); break; }; case 'f': // f = (+ignore) ignore this person { pMe->Ignore(szMsg); break; }; case 'g': // g = (-ignore) don't ignore this person { pMe->DontIgnore(szMsg); break; }; case 'h': // h = toggle ignoring this person { pMe->ToggleIgnore(szMsg); break; }; case 'i': // i = grant speaking privs to this person { if (!pChannel) goto not_in_a_channel; pChannel->GrantVoice(pMe, szMsg); break; }; case 'j': // j = remove speaking privs from this person { if (!pChannel) goto not_in_a_channel; pChannel->RevokeVoice(pMe, szMsg); break; }; case 'k': // k = (/voice) toggle voice status { if (!pChannel) goto not_in_a_channel; pChannel->ToggleVoice(pMe, szMsg); break; }; case 'l': // l = grant moderator status to this person { if (!pChannel) goto not_in_a_channel; pChannel->GrantModerator(pMe, szMsg); break; }; case 'm': // m = remove moderator status from this person { if (!pChannel) goto not_in_a_channel; pChannel->RevokeModerator(pMe, szMsg); break; }; case 'n': // m = toggle the moderator status for this person { if (!pChannel) goto not_in_a_channel; pChannel->ToggleModerator(pMe, szMsg); break; } case 'o': // o = turn on receiving private messages { pMe->SetReceiving(true); break; } case 'p': // p = turn off receiving private messages { pMe->SetReceiving(false); break; } case 'q': // q = toggle receiving messages { pMe->ToggleReceiving(); break; }; case 'r': // r = (+showname) turn on showing character name { pMe->PermitWhoIs(); break; }; case 's': // s = (-showname) turn off showing character name { pMe->ForbidWhoIs(); break; }; case 't': // t = toggle showing character name { pMe->ToggleWhoIs(); break; }; case 'u': // u = who is this player { if (!pChannel) goto not_in_a_channel; pChannel->WhoIs(pMe->GetChatName(), szMsg); break; }; case 'v': // v = kick this person out of the conference { if (!pChannel) goto not_in_a_channel; CChatChanMember * pMember = pChannel->FindMember(szMsg); if (!pMember) { pMe->SendChatMsg(CHATMSG_NoPlayer, szMsg); break; } pChannel->KickMember(pMe, pMember); // If noone is left, tell the chat system to // delete it from memory (you can kick yourself) if (pChannel->m_Members.GetCount() <= 0) // Kicked self { DeleteChannel(pChannel); } break; }; case 'X': // X = client quit chat QuitChat(pClient); break; case 'w': // w = (+defaultvoice) make moderators be the only ones with a voice by default if (!pChannel) goto not_in_a_channel; pChannel->DisableVoiceDefault(pMe->GetChatName()); break; case 'x': // x = (-defaultvoice) give everyone a voice by default if (!pChannel) goto not_in_a_channel; pChannel->EnableVoiceDefault(pMe->GetChatName()); break; case 'y': // y = (/defaultvoice) toggle if (!pChannel) goto not_in_a_channel; pChannel->ToggleVoiceDefault(pMe->GetChatName()); break; case 'z': // z = emote if (!pChannel) goto not_in_a_channel; pChannel->Emote(pMe->GetChatName(), szMsg, lang ); break; }; }
void CChat::Action(CClient *pClient, const NCHAR *pszText, int len, CLanguageID lang) { ADDTOCALLSTACK("CChat::Action"); // ARGS: // len = length of the pszText string in NCHAR's. if ( !(g_Cfg.m_iFeatureT2A & FEATURE_T2A_CHAT) ) return; CChatMember *pMe = static_cast<CChatMember *>(pClient); CChatChannel *pChannel = pMe->GetChannel(); TCHAR szFullText[MAX_TALK_BUFFER]; CvtNUNICODEToSystem(szFullText, sizeof(szFullText), pszText, len); TCHAR *pszMsg = szFullText + 1; switch ( szFullText[0] ) // the 1st character is a command byte (join channel, leave channel, etc) { case CHATACT_ChangeChannelPassword: // client shortcut: /pw { if ( !pChannel ) goto NoConference; pChannel->ChangePassword(pMe, pszMsg); break; } case CHATACT_LeaveChannel: { if ( !pChannel ) goto NoConference; pChannel->RemoveMember(pMe); break; } case CHATACT_LeaveChat: { if ( pChannel ) pChannel->RemoveMember(pMe); break; } case CHATACT_ChannelMessage: { if ( pChannel ) { pChannel->MemberTalk(pMe, pClient->m_UseNewChatSystem ? szFullText : pszMsg, lang); break; } NoConference: pMe->SendChatMsg(CHATMSG_MustBeInAConference); return; } case CHATACT_JoinChannel: // client shortcut: /conf { // Look for second double quote to separate channel from password size_t i = 1; for ( ; pszMsg[i] != '\0'; i++ ) { if ( pszMsg[i] == '"' ) break; } pszMsg[i] = '\0'; TCHAR *pszPassword = pszMsg + i + 1; if ( pszPassword[0] == ' ' ) // skip whitespaces pszPassword++; JoinChannel(pszMsg + 1, pszPassword, pMe); break; } case CHATACT_CreateChannel: // client shortcut: /newconf { TCHAR *pszPassword = NULL; size_t iMsgLength = strlen(pszMsg); for ( size_t i = 0; i < iMsgLength; i++ ) { if ( pszMsg[i] == '{' ) // there's a password here { pszMsg[i] = 0; pszPassword = pszMsg + i + 1; size_t iPasswordLength = strlen(pszPassword); for ( i = 0; i < iPasswordLength; i++ ) { if ( pszPassword[i] == '}' ) { pszPassword[i] = '\0'; break; } } break; } } if ( CreateChannel(pszMsg, pszPassword, pMe) ) JoinChannel(pszMsg, pszPassword, pMe); break; } case CHATACT_RenameChannel: // client shortcut: /rename { if ( !pChannel ) goto NoConference; pMe->RenameChannel(pszMsg); break; } case CHATACT_PrivateMessage: // client shortcut: /msg { if ( !pChannel ) goto NoConference; // Split the recipient from the message (look for a space) TCHAR buffer[2048]; strcpy(buffer, pszMsg); size_t bufferLength = strlen(buffer); size_t i = 0; for ( ; i < bufferLength; i++ ) { if ( buffer[i] == ' ' ) { buffer[i] = '\0'; break; } } pChannel->PrivateMessage(pMe, buffer, buffer + i + 1, lang); break; } case CHATACT_AddIgnore: // client shortcut: +ignore { pMe->AddIgnore(pszMsg); break; } case CHATACT_RemoveIgnore: // client shortcut: -ignore { pMe->RemoveIgnore(pszMsg); break; } case CHATACT_ToggleIgnore: // client shortcut: /ignore { pMe->ToggleIgnore(pszMsg); break; } case CHATACT_AddVoice: // client shortcut: +voice { if ( !pChannel ) goto NoConference; pChannel->AddVoice(pMe, pszMsg); break; } case CHATACT_RemoveVoice: // client shortcut: -voice { if ( !pChannel ) goto NoConference; pChannel->RemoveVoice(pMe, pszMsg); break; } case CHATACT_ToggleVoice: // client shortcut: /voice { if ( !pChannel ) goto NoConference; pChannel->ToggleVoice(pMe, pszMsg); break; } case CHATACT_AddModerator: // client shortcut: +ops { if ( !pChannel ) goto NoConference; pChannel->AddModerator(pMe, pszMsg); break; } case CHATACT_RemoveModerator: // client shortcut: -ops { if ( !pChannel ) goto NoConference; pChannel->RemoveModerator(pMe, pszMsg); break; } case CHATACT_ToggleModerator: // client shortcut: /ops { if ( !pChannel ) goto NoConference; pChannel->ToggleModerator(pMe, pszMsg); break; } case CHATACT_EnablePrivateMessages: // client shortcut: +receive { pMe->SetReceiving(true); break; } case CHATACT_DisablePrivateMessages: // client shortcut: -receive { pMe->SetReceiving(false); break; } case CHATACT_TogglePrivateMessages: // client shortcut: /receive { pMe->ToggleReceiving(); break; } case CHATACT_ShowCharacterName: // client shortcut: +showname { pMe->ShowCharacterName(); break; } case CHATACT_HideCharacterName: // client shortcut: -showname { pMe->HideCharacterName(); break; } case CHATACT_ToggleCharacterName: // client shortcut: /showname { pMe->ToggleCharacterName(); break; } case CHATACT_WhoIs: // client shortcut: /whois { if ( !pChannel ) goto NoConference; pChannel->WhoIs(pMe->GetChatName(), pszMsg); break; } case CHATACT_Kick: // client shortcut: /kick { if ( !pChannel ) goto NoConference; CChatMember *pMember = pChannel->FindMember(pszMsg); if ( pMember ) pChannel->KickMember(pMe, pMember); else pMe->SendChatMsg(CHATMSG_NoPlayer, pszMsg); break; } case CHATACT_EnableDefaultVoice: // client shortcut: +defaultvoice { if ( !pChannel ) goto NoConference; pChannel->EnableDefaultVoice(pMe->GetChatName()); break; } case CHATACT_DisableDefaultVoice: // client shortcut: -defaultvoice { if ( !pChannel ) goto NoConference; pChannel->DisableDefaultVoice(pMe->GetChatName()); break; } case CHATACT_ToggleDefaultVoice: // client shortcut: /defaultvoice { if ( !pChannel ) goto NoConference; pChannel->ToggleDefaultVoice(pMe->GetChatName()); break; } case CHATACT_EmoteMessage: // client shortcut: /emote or /em { if ( !pChannel ) goto NoConference; pChannel->Emote(pMe->GetChatName(), pszMsg, lang); break; } } }
Server::Server(const struct ServerState &init_state, Window *w) : LockingReciever<Window, Monitor> (w) , last_channel(nullptr) , widget(new Fl_Group(0, 0, 800, 600)) , channel_list(nullptr) , task_died(false) , network_task(new ServerTask(this, init_state.socket, &task_died)){ CopyState(state, init_state); state.socket = init_state.socket; Channel *channel = new Channel(this, "server"); channel_list.reset(Parent->GenerateChannelBrowser()); channel->Handlers.push_back(std::unique_ptr<MessageHandler>(new ChannelMessage::YourHost_Handler(channel))); channel->Handlers.push_back(std::unique_ptr<MessageHandler>(new ChannelMessage::Notice_Handler(channel))); channel->Handlers.push_back(std::unique_ptr<MessageHandler>(new ChannelMessage::TopicExtra_Handler(channel))); AddChannel(channel); w->SetChannel(channel); Thread::AddShortRunningTask(network_task); Thread::AddSocketToTaskGroup(state.socket, Thread::GetShortThreadPool()); Handlers.push_back(std::unique_ptr<MessageHandler>(new Ping_Handler(this))); // This should all be put in the call before construction IRC_Message *msg_name = IRC_CreateUser(state.name.c_str(), "falcon", "millenium", state.real.c_str()); IRC_Message *msg_nick = IRC_CreateNick(state.nick.c_str()); Handlers.push_back(std::unique_ptr<MessageHandler>(new Debug_Handler())); Handlers.push_back(std::unique_ptr<MessageHandler>(new SendMessage_Handler(this, msg_name))); Handlers.push_back(std::unique_ptr<MessageHandler>(new SendMessage_Handler(this, msg_nick))); Handlers.push_back(std::unique_ptr<MessageHandler>(new Join_Handler(this))); Handlers.push_back(std::unique_ptr<MessageHandler>(new Part_Handler(this))); Handlers.push_back(std::unique_ptr<MessageHandler>(new Topic_Handler(this))); Handlers.push_back(std::unique_ptr<MessageHandler>(new PrivateMessage_Handler(this))); Handlers.push_back(std::unique_ptr<MessageHandler>(new NumericTopic_Handler(this))); Handlers.push_back(std::unique_ptr<MessageHandler>(new NumericNoTopic_Handler(this))); Handlers.push_back(std::unique_ptr<MessageHandler>(new Namelist_Handler(this))); Handlers.push_back(std::unique_ptr<MessageHandler>(new Quit_Handler(this))); Handlers.push_back(std::unique_ptr<MessageHandler>(new Nick_Handler(this))); Handlers.push_back(std::unique_ptr<MessageHandler>(new Notice_Handler(this))); for(std::list<std::string>::const_iterator iter = state.channels.cbegin(); iter!=state.channels.cend(); iter++){ printf("Joining %s.\n", iter->c_str()); IRC_Message *msg = IRC_CreateJoin(1, iter->c_str()); SendMessage(msg); JoinChannel(iter->c_str()); Handlers.push_back(std::unique_ptr<MessageHandler>(new SendMessageOn_Handler<OnMsgType<IRC_welcome_num> >(this, msg))); } printf("Creating Server.\n"); }