void cmd_kill::Handle (const char** parameters, int pcnt, userrec *user) { userrec *u = ServerInstance->FindNick(parameters[0]); char killreason[MAXBUF]; int MOD_RESULT = 0; ServerInstance->Log(DEBUG,"kill: %s %s", parameters[0], parameters[1]); if (u) { ServerInstance->Log(DEBUG, "into kill mechanism"); FOREACH_RESULT(I_OnKill, OnKill(user, u, parameters[1])); if (MOD_RESULT) { ServerInstance->Log(DEBUG, "A module prevented the kill with result %d", MOD_RESULT); return; } if (!IS_LOCAL(u)) { // remote kill ServerInstance->WriteOpers("*** Remote kill by %s: %s!%s@%s (%s)", user->nick, u->nick, u->ident, u->host, parameters[1]); snprintf(killreason, MAXQUIT,"[%s] Killed (%s (%s))", ServerInstance->Config->ServerName, user->nick, parameters[1]); u->WriteCommonExcept("QUIT :%s", killreason); FOREACH_MOD(I_OnRemoteKill, OnRemoteKill(user, u, killreason)); user_hash::iterator iter = ServerInstance->clientlist.find(u->nick); if (iter != ServerInstance->clientlist.end()) { ServerInstance->Log(DEBUG,"deleting user hash value %d", iter->second); ServerInstance->clientlist.erase(iter); } if (u->registered == REG_ALL) { u->PurgeEmptyChannels(); } DELETE(u); } else { // local kill ServerInstance->Log(DEFAULT,"LOCAL KILL: %s :%s!%s!%s (%s)", u->nick, ServerInstance->Config->ServerName, user->dhost, user->nick, parameters[1]); user->WriteTo(u, "KILL %s :%s!%s!%s (%s)", u->nick, ServerInstance->Config->ServerName, user->dhost, user->nick, parameters[1]); ServerInstance->WriteOpers("*** Local Kill by %s: %s!%s@%s (%s)", user->nick, u->nick, u->ident, u->host, parameters[1]); snprintf(killreason,MAXQUIT,"Killed (%s (%s))", user->nick, parameters[1]); userrec::QuitUser(ServerInstance, u, killreason); } } else { user->WriteServ( "401 %s %s :No such nick/channel", user->nick, parameters[0]); } }
/** Handle /KILL */ CmdResult CommandKill::Handle (const std::vector<std::string>& parameters, User *user) { /* Allow comma seperated lists of users for /KILL (thanks w00t) */ if (ServerInstance->Parser->LoopCall(user, this, parameters, 0)) return CMD_SUCCESS; User *u = ServerInstance->FindNick(parameters[0]); if ((u) && (!IS_SERVER(u))) { /* * Here, we need to decide how to munge kill messages. Whether to hide killer, what to show opers, etc. * We only do this when the command is being issued LOCALLY, for remote KILL, we just copy the message we got. * * This conditional is so that we only append the "Killed (" prefix ONCE. If killer is remote, then the kill * just gets processed and passed on, otherwise, if they are local, it gets prefixed. Makes sense :-) -- w00t */ std::string killreason; if (IS_LOCAL(user)) { /* * Moved this event inside the IS_LOCAL check also, we don't want half the network killing a user * and the other half not. This would be a bad thing. ;p -- w00t */ ModResult MOD_RESULT; FIRST_MOD_RESULT(OnKill, MOD_RESULT, (user, u, parameters[1])); if (MOD_RESULT == MOD_RES_DENY) return CMD_FAILURE; killreason = "Killed ("; if (!ServerInstance->Config->HideKillsServer.empty()) { // hidekills is on, use it killreason += ServerInstance->Config->HideKillsServer; } else { // hidekills is off, do nothing killreason += user->nick; } killreason += " (" + parameters[1] + "))"; } else { /* Leave it alone, remote server has already formatted it */ killreason.assign(parameters[1], 0, ServerInstance->Config->Limits.MaxQuit); } /* * Now we need to decide whether or not to send a local or remote snotice. Currently this checking is a little flawed. * No time to fix it right now, so left a note. -- w00t */ if (!IS_LOCAL(u)) { // remote kill ServerInstance->SNO->WriteToSnoMask('K', "Remote kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str()); FOREACH_MOD(I_OnRemoteKill, OnRemoteKill(user, u, killreason, killreason)); } else { // local kill /* * XXX - this isn't entirely correct, servers A - B - C, oper on A, client on C. Oper kills client, A and B will get remote kill * snotices, C will get a local kill snotice. this isn't accurate, and needs fixing at some stage. -- w00t */ if (IS_LOCAL(user)) ServerInstance->SNO->WriteGlobalSno('k',"Local Kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str()); else ServerInstance->SNO->WriteToSnoMask('k',"Local Kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str()); ServerInstance->Logs->Log("KILL", LOG_DEFAULT, "LOCAL KILL: %s :%s!%s!%s (%s)", u->nick.c_str(), ServerInstance->Config->ServerName.c_str(), user->dhost.c_str(), user->nick.c_str(), parameters[1].c_str()); /* Bug #419, make sure this message can only occur once even in the case of multiple KILL messages crossing the network, and change to show * hidekillsserver as source if possible */ if (!u->quitting) { u->Write(":%s KILL %s :%s!%s!%s (%s)", ServerInstance->Config->HideKillsServer.empty() ? user->GetFullHost().c_str() : ServerInstance->Config->HideKillsServer.c_str(), u->nick.c_str(), ServerInstance->Config->ServerName.c_str(), user->dhost.c_str(), ServerInstance->Config->HideKillsServer.empty() ? user->nick.c_str() : ServerInstance->Config->HideKillsServer.c_str(), parameters[1].c_str()); } } // send the quit out ServerInstance->Users->QuitUser(u, killreason); } else { user->WriteServ( "401 %s %s :No such nick/channel", user->nick.c_str(), parameters[0].c_str()); return CMD_FAILURE; } return CMD_SUCCESS; }