summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/modules.h12
-rw-r--r--src/modules.cpp1
-rw-r--r--src/usermanager.cpp39
3 files changed, 39 insertions, 13 deletions
diff --git a/include/modules.h b/include/modules.h
index 581eb7f04..81664d364 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -214,7 +214,7 @@ enum Priority { PRIORITY_FIRST, PRIORITY_LAST, PRIORITY_BEFORE, PRIORITY_AFTER }
*/
enum Implementation
{
- I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart,
+ I_OnUserConnect, I_OnUserPreQuit, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart,
I_OnSendSnotice, I_OnUserPreJoin, I_OnUserPreKick, I_OnUserKick, I_OnOper,
I_OnUserPreInvite, I_OnUserInvite, I_OnUserPreMessage, I_OnUserPreNick,
I_OnUserPostMessage, I_OnUserMessageBlocked, I_OnMode,
@@ -307,6 +307,16 @@ class CoreExport Module : public classbase, public usecountbase
*/
virtual void OnUserConnect(LocalUser* user);
+ /** Called when before a user quits.
+ * The details of the exiting user are available to you in the parameter User *user
+ * This event is only called when the user is fully registered when they quit. To catch
+ * raw disconnections, use the OnUserDisconnect method.
+ * @param user The user who is quitting
+ * @param message The user's quit message (as seen by non-opers)
+ * @param oper_message The user's quit message (as seen by opers)
+ */
+ virtual ModResult OnUserPreQuit(LocalUser* user, std::string& message, std::string& oper_message);
+
/** Called when a user quits.
* The details of the exiting user are available to you in the parameter User *user
* This event is only called when the user is fully registered when they quit. To catch
diff --git a/src/modules.cpp b/src/modules.cpp
index 444e90645..3e268dae6 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -73,6 +73,7 @@ void Module::DetachEvent(Implementation i)
void Module::ReadConfig(ConfigStatus& status) { }
ModResult Module::OnSendSnotice(char &snomask, std::string &type, const std::string &message) { DetachEvent(I_OnSendSnotice); return MOD_RES_PASSTHRU; }
void Module::OnUserConnect(LocalUser*) { DetachEvent(I_OnUserConnect); }
+ModResult Module::OnUserPreQuit(LocalUser*, std::string&, std::string&) { DetachEvent(I_OnUserPreQuit); return MOD_RES_PASSTHRU; }
void Module::OnUserQuit(User*, const std::string&, const std::string&) { DetachEvent(I_OnUserQuit); }
void Module::OnUserDisconnect(LocalUser*) { DetachEvent(I_OnUserDisconnect); }
void Module::OnUserJoin(Membership*, bool, bool, CUList&) { DetachEvent(I_OnUserJoin); }
diff --git a/src/usermanager.cpp b/src/usermanager.cpp
index fafeffb42..6acd25ac5 100644
--- a/src/usermanager.cpp
+++ b/src/usermanager.cpp
@@ -214,7 +214,7 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs
FOREACH_MOD(OnUserPostInit, (New));
}
-void UserManager::QuitUser(User* user, const std::string& quitreason, const std::string* operreason)
+void UserManager::QuitUser(User* user, const std::string& quitmessage, const std::string* operquitmessage)
{
if (user->quitting)
{
@@ -228,27 +228,42 @@ void UserManager::QuitUser(User* user, const std::string& quitreason, const std:
return;
}
- user->quitting = true;
+ std::string quitmsg(quitmessage);
+ std::string operquitmsg;
+ if (operquitmessage)
+ operquitmsg.assign(*operquitmessage);
- ServerInstance->Logs->Log("USERS", LOG_DEBUG, "QuitUser: %s=%s '%s'", user->uuid.c_str(), user->nick.c_str(), quitreason.c_str());
LocalUser* const localuser = IS_LOCAL(user);
if (localuser)
{
- ClientProtocol::Messages::Error errormsg(InspIRCd::Format("Closing link: (%s@%s) [%s]", user->ident.c_str(), user->GetRealHost().c_str(), operreason ? operreason->c_str() : quitreason.c_str()));
- localuser->Send(ServerInstance->GetRFCEvents().error, errormsg);
+ ModResult MOD_RESULT;
+ FIRST_MOD_RESULT(OnUserPreQuit, MOD_RESULT, (localuser, quitmsg, operquitmsg));
+ if (MOD_RESULT == MOD_RES_DENY)
+ return;
}
- std::string reason;
- reason.assign(quitreason, 0, ServerInstance->Config->Limits.MaxQuit);
- if (!operreason)
- operreason = &reason;
+ if (quitmsg.length() > ServerInstance->Config->Limits.MaxQuit)
+ quitmsg.erase(ServerInstance->Config->Limits.MaxQuit + 1);
+
+ if (operquitmsg.empty())
+ operquitmsg.assign(quitmsg);
+ else if (operquitmsg.length() > ServerInstance->Config->Limits.MaxQuit)
+ operquitmsg.erase(ServerInstance->Config->Limits.MaxQuit + 1);
+
+ user->quitting = true;
+ ServerInstance->Logs->Log("USERS", LOG_DEBUG, "QuitUser: %s=%s '%s'", user->uuid.c_str(), user->nick.c_str(), quitmessage.c_str());
+ if (localuser)
+ {
+ ClientProtocol::Messages::Error errormsg(InspIRCd::Format("Closing link: (%s@%s) [%s]", user->ident.c_str(), user->GetRealHost().c_str(), operquitmsg.c_str()));
+ localuser->Send(ServerInstance->GetRFCEvents().error, errormsg);
+ }
ServerInstance->GlobalCulls.AddItem(user);
if (user->registered == REG_ALL)
{
- FOREACH_MOD(OnUserQuit, (user, reason, *operreason));
- WriteCommonQuit(user, reason, *operreason);
+ FOREACH_MOD(OnUserQuit, (user, quitmsg, operquitmsg));
+ WriteCommonQuit(user, quitmsg, operquitmsg);
}
else
unregistered_count--;
@@ -260,7 +275,7 @@ void UserManager::QuitUser(User* user, const std::string& quitreason, const std:
lu->eh.Close();
if (lu->registered == REG_ALL)
- ServerInstance->SNO->WriteToSnoMask('q',"Client exiting: %s (%s) [%s]", user->GetFullRealHost().c_str(), user->GetIPString().c_str(), operreason->c_str());
+ ServerInstance->SNO->WriteToSnoMask('q',"Client exiting: %s (%s) [%s]", user->GetFullRealHost().c_str(), user->GetIPString().c_str(), operquitmsg.c_str());
local_users.erase(lu);
}