bool IRCdMessage::OnQuit(const Anope::string &source, const std::vector<Anope::string> ¶ms) { const Anope::string &reason = !params.empty() ? params[0] : ""; User *user = finduser(source); if (!user) { Log() << "user: QUIT from nonexistent user " << source << " (" << reason << ")"; return true; } Log(user, "quit") << "quit (Reason: " << (!reason.empty() ? reason : "no reason") << ")"; NickAlias *na = findnick(user->nick); if (na && !na->nc->HasFlag(NI_SUSPENDED) && (user->IsRecognized() || user->IsIdentified(true))) { na->last_seen = Anope::CurTime; na->last_quit = reason; } FOREACH_MOD(I_OnUserQuit, OnUserQuit(user, reason)); delete user; return true; }
void UserManager::QuitUser(User *user, const std::string &quitreason, const char* operreason) { if (user->quitting) { ServerInstance->Logs->Log("CULLLIST",DEBUG, "*** Warning *** - You tried to quit a user (%s) twice. Did your module call QuitUser twice?", user->nick.c_str()); return; } if (IS_SERVER(user)) { ServerInstance->Logs->Log("CULLLIST",DEBUG, "*** Warning *** - You tried to quit a fake user (%s)", user->nick.c_str()); return; } user->quitting = true; ServerInstance->Logs->Log("USERS", DEBUG, "QuitUser: %s=%s '%s'", user->uuid.c_str(), user->nick.c_str(), quitreason.c_str()); user->Write("ERROR :Closing link: (%s@%s) [%s]", user->ident.c_str(), user->host.c_str(), *operreason ? operreason : quitreason.c_str()); std::string reason; std::string oper_reason; reason.assign(quitreason, 0, ServerInstance->Config->Limits.MaxQuit); if (operreason && *operreason) oper_reason.assign(operreason, 0, ServerInstance->Config->Limits.MaxQuit); else oper_reason = quitreason; ServerInstance->GlobalCulls.AddItem(user); if (user->registered == REG_ALL) { FOREACH_MOD(I_OnUserQuit,OnUserQuit(user, reason, oper_reason)); user->WriteCommonQuit(reason, oper_reason); } if (user->registered != REG_ALL) if (ServerInstance->Users->unregistered_count) ServerInstance->Users->unregistered_count--; if (IS_LOCAL(user)) { LocalUser* lu = IS_LOCAL(user); FOREACH_MOD(I_OnUserDisconnect,OnUserDisconnect(lu)); lu->eh.Close(); } /* * this must come before the ServerInstance->SNO->WriteToSnoMaskso that it doesnt try to fill their buffer with anything * if they were an oper with +s +qQ. */ if (user->registered == REG_ALL) { if (IS_LOCAL(user)) { if (!user->quietquit) { ServerInstance->SNO->WriteToSnoMask('q',"Client exiting: %s (%s) [%s]", user->GetFullRealHost().c_str(), user->GetIPString().c_str(), oper_reason.c_str()); } } else { if ((!ServerInstance->SilentULine(user->server)) && (!user->quietquit)) { ServerInstance->SNO->WriteToSnoMask('Q',"Client exiting on server %s: %s (%s) [%s]", user->server.c_str(), user->GetFullRealHost().c_str(), user->GetIPString().c_str(), oper_reason.c_str()); } } } user_hash::iterator iter = this->clientlist->find(user->nick); if (iter != this->clientlist->end()) this->clientlist->erase(iter); else ServerInstance->Logs->Log("USERS", DEBUG, "iter == clientlist->end, can't remove them from hash... problematic.."); ServerInstance->Users->uuidlist->erase(user->uuid); }