summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/modules.h28
-rw-r--r--include/users.h7
-rw-r--r--src/modules.cpp3
-rw-r--r--src/modules/m_auditorium.cpp36
-rw-r--r--src/modules/m_deaf.cpp9
-rw-r--r--src/modules/m_delayjoin.cpp41
-rw-r--r--src/modules/m_invisible.cpp41
-rw-r--r--src/modules/m_silence.cpp4
-rw-r--r--src/users.cpp163
9 files changed, 118 insertions, 214 deletions
diff --git a/include/modules.h b/include/modules.h
index c9927133f..ca345dbc1 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -389,9 +389,9 @@ enum Implementation
I_OnPostTopicChange, I_OnEvent, I_OnRequest, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan,
I_OnDelBan, I_OnChangeLocalUserGECOS, I_OnUserRegister, I_OnChannelPreDelete, I_OnChannelDelete,
I_OnPostOper, I_OnSyncNetwork, I_OnSetAway, I_OnUserList, I_OnPostCommand, I_OnPostJoin,
- I_OnWhoisLine, I_OnBuildExemptList, I_OnGarbageCollect,
+ I_OnWhoisLine, I_OnBuildNeighborList, I_OnGarbageCollect,
I_OnText, I_OnPassCompare, I_OnRunTestSuite, I_OnNamesListItem, I_OnNumeric, I_OnHookIO,
- I_OnHostCycle, I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent,
+ I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent,
I_END
};
@@ -681,16 +681,16 @@ class CoreExport Module : public Extensible
*/
virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text,char status, CUList &exempt_list);
- /** Called whenever the server wants to build the exemption list for a channel, but is not directly doing a PRIVMSG or NOTICE.
- * For example, the spanningtree protocol will call this event when passing a privmsg on (but not processing it directly).
- * @param message_type The message type, either MSG_PRIVMSG or MSG_NOTICE
- * @param chan The channel to build the exempt list of
- * @param sender The original sender of the PRIVMSG or NOTICE
- * @param status The status char to be used for the channel list
- * @param exempt_list The exempt list to be populated
- * @param text The original message text causing the exempt list to be built
+ /** Called when sending a message to all "neighbors" of a given user -
+ * that is, all users that share a common channel. This is used in
+ * commands such as NICK, QUIT, etc.
+ * @param source The source of the message
+ * @param include_c Channels to scan for users to include
+ * @param exceptions Map of user->bool that overrides the inclusion decision
+ *
+ * Set exceptions[user] = true to include, exceptions[user] = false to exclude
*/
- virtual void OnBuildExemptList(MessageType message_type, Channel* chan, User* sender, char status, CUList &exempt_list, const std::string &text);
+ virtual void OnBuildNeighborList(User* source, UserChanList &include_c, std::map<User*,bool> &exceptions);
/** Called before any nickchange, local or remote. This can be used to implement Q-lines etc.
* Please note that although you can see remote nickchanges through this function, you should
@@ -1327,12 +1327,6 @@ class CoreExport Module : public Extensible
virtual ModResult OnNumeric(User* user, unsigned int numeric, const std::string &text);
- /** Called for every time the user's host or ident changes, to indicate wether or not the 'Changing host'
- * message should be sent, if enabled. Certain modules such as auditorium may opt to hide this message
- * even if it is enabled.
- */
- virtual ModResult OnHostCycle(User* user);
-
/** Called whenever a result from /WHO is about to be returned
* @param source The user running the /WHO query
* @param user The user that this line of the query is about
diff --git a/include/users.h b/include/users.h
index 6f656a51b..ac3b2b459 100644
--- a/include/users.h
+++ b/include/users.h
@@ -715,7 +715,7 @@ class CoreExport User : public StreamSocket
/** Write to all users that can see this user (including this user in the list), appending CR/LF
* @param text A std::string to send to the users
*/
- void WriteCommon(const std::string &text);
+ void WriteCommonRaw(const std::string &line, bool include_self = true);
/** Write to all users that can see this user (including this user in the list), appending CR/LF
* @param text The format string for text to send to the users
@@ -729,11 +729,6 @@ class CoreExport User : public StreamSocket
*/
void WriteCommonExcept(const char* text, ...) CUSTOM_PRINTF(2, 3);
- /** Write to all users that can see this user (not including this user in the list), appending CR/LF
- * @param text A std::string to send to the users
- */
- void WriteCommonExcept(const std::string &text);
-
/** Write a quit message to all common users, as in User::WriteCommonExcept but with a specific
* quit message for opers only.
* @param normal_text Normal user quit message
diff --git a/src/modules.cpp b/src/modules.cpp
index 2a835f10d..f7904d07b 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -193,14 +193,13 @@ void Module::OnChannelDelete(Channel*) { }
ModResult Module::OnSetAway(User*, const std::string &) { return MOD_RES_PASSTHRU; }
ModResult Module::OnUserList(User*, Channel*) { return MOD_RES_PASSTHRU; }
ModResult Module::OnWhoisLine(User*, User*, int&, std::string&) { return MOD_RES_PASSTHRU; }
-void Module::OnBuildExemptList(MessageType, Channel*, User*, char, CUList&, const std::string&) { }
+void Module::OnBuildNeighborList(User*, UserChanList&, std::map<User*,bool>&) { }
void Module::OnGarbageCollect() { }
void Module::OnText(User*, void*, int, const std::string&, char, CUList&) { }
void Module::OnRunTestSuite() { }
void Module::OnNamesListItem(User*, Membership*, std::string&, std::string&) { }
ModResult Module::OnNumeric(User*, unsigned int, const std::string&) { return MOD_RES_PASSTHRU; }
void Module::OnHookIO(StreamSocket*, ListenSocketBase*) { }
-ModResult Module::OnHostCycle(User*) { return MOD_RES_PASSTHRU; }
void Module::OnSendWhoLine(User*, User*, Channel*, std::string&) { }
ModuleManager::ModuleManager() : ModCount(0)
diff --git a/src/modules/m_auditorium.cpp b/src/modules/m_auditorium.cpp
index d27ccfaad..ec321bb35 100644
--- a/src/modules/m_auditorium.cpp
+++ b/src/modules/m_auditorium.cpp
@@ -52,8 +52,8 @@ class ModuleAuditorium : public Module
OnRehash(NULL);
- Implementation eventlist[] = { I_OnUserJoin, I_OnUserPart, I_OnUserKick, I_OnUserQuit, I_OnNamesListItem, I_OnRehash, I_OnHostCycle };
- ServerInstance->Modules->Attach(eventlist, this, 7);
+ Implementation eventlist[] = { I_OnUserJoin, I_OnUserPart, I_OnUserKick, I_OnBuildNeighborList, I_OnNamesListItem, I_OnRehash };
+ ServerInstance->Modules->Attach(eventlist, this, 6);
}
@@ -137,34 +137,14 @@ class ModuleAuditorium : public Module
BuildExcept(memb, excepts);
}
- ModResult OnHostCycle(User* user)
+ void OnBuildNeighborList(User* source, UserChanList &include, std::map<User*,bool> &exception)
{
- for (UCListIter f = user->chans.begin(); f != user->chans.end(); f++)
- if ((*f)->IsModeSet('u'))
- return MOD_RES_DENY;
-
- return MOD_RES_PASSTHRU;
- }
-
- void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message)
- {
- Command* parthandler = ServerInstance->Parser->GetHandler("PART");
- std::vector<std::string> to_leave;
- if (parthandler)
+ UCListIter i = include.begin();
+ while (i != include.end())
{
- for (UCListIter f = user->chans.begin(); f != user->chans.end(); f++)
- {
- if ((*f)->IsModeSet('u'))
- to_leave.push_back((*f)->name);
- }
- /* We cant do this neatly in one loop, as we are modifying the map we are iterating */
- for (std::vector<std::string>::iterator n = to_leave.begin(); n != to_leave.end(); n++)
- {
- std::vector<std::string> parameters;
- parameters.push_back(*n);
- /* This triggers our OnUserPart, above, making the PART silent */
- parthandler->Handle(parameters, user);
- }
+ Channel* c = *i++;
+ if (c->IsModeSet('u'))
+ include.erase(c);
}
}
};
diff --git a/src/modules/m_deaf.cpp b/src/modules/m_deaf.cpp
index 78040e81f..2d13be98b 100644
--- a/src/modules/m_deaf.cpp
+++ b/src/modules/m_deaf.cpp
@@ -60,8 +60,8 @@ class ModuleDeaf : public Module
throw ModuleException("Could not add new modes!");
OnRehash(NULL);
- Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice, I_OnRehash, I_OnBuildExemptList };
- ServerInstance->Modules->Attach(eventlist, this, 4);
+ Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice, I_OnRehash };
+ ServerInstance->Modules->Attach(eventlist, this, 3);
}
@@ -98,11 +98,6 @@ class ModuleDeaf : public Module
return MOD_RES_PASSTHRU;
}
- virtual void OnBuildExemptList(MessageType message_type, Channel* chan, User* sender, char status, CUList &exempt_list, const std::string &text)
- {
- BuildDeafList(message_type, chan, sender, status, text, exempt_list);
- }
-
virtual void BuildDeafList(MessageType message_type, Channel* chan, User* sender, char status, const std::string &text, CUList &exempt_list)
{
const UserMembList *ulist = chan->GetUsers();
diff --git a/src/modules/m_delayjoin.cpp b/src/modules/m_delayjoin.cpp
index 1a84ee694..1db0e7c0d 100644
--- a/src/modules/m_delayjoin.cpp
+++ b/src/modules/m_delayjoin.cpp
@@ -36,18 +36,17 @@ class ModuleDelayJoin : public Module
{
if (!ServerInstance->Modes->AddMode(&djm))
throw ModuleException("Could not add new modes!");
- Implementation eventlist[] = { I_OnUserJoin, I_OnUserPart, I_OnUserKick, I_OnUserQuit, I_OnNamesListItem, I_OnText, I_OnHostCycle };
- ServerInstance->Modules->Attach(eventlist, this, 7);
+ Implementation eventlist[] = { I_OnUserJoin, I_OnUserPart, I_OnUserKick, I_OnBuildNeighborList, I_OnNamesListItem, I_OnText };
+ ServerInstance->Modules->Attach(eventlist, this, 6);
}
~ModuleDelayJoin();
Version GetVersion();
void OnNamesListItem(User* issuer, Membership*, std::string &prefixes, std::string &nick);
void OnUserJoin(Membership*, bool, bool, CUList&);
void CleanUser(User* user);
- ModResult OnHostCycle(User* user);
void OnUserPart(Membership*, std::string &partmessage, CUList&);
void OnUserKick(User* source, Membership*, const std::string &reason, CUList&);
- void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message);
+ void OnBuildNeighborList(User* source, UserChanList &include, std::map<User*,bool> &exception);
void OnText(User* user, void* dest, int target_type, const std::string &text, char status, CUList &exempt_list);
};
@@ -125,37 +124,15 @@ void ModuleDelayJoin::OnUserKick(User* source, Membership* memb, const std::stri
populate(except, memb);
}
-ModResult ModuleDelayJoin::OnHostCycle(User* user)
+void ModuleDelayJoin::OnBuildNeighborList(User* source, UserChanList &include, std::map<User*,bool> &exception)
{
- for (UCListIter f = user->chans.begin(); f != user->chans.end(); f++)
+ UCListIter i = include.begin();
+ while (i != include.end())
{
- Channel* chan = *f;
- Membership* memb = chan->GetUser(user);
-
- if (memb && unjoined.get(memb))
- {
- return MOD_RES_DENY;
- }
- }
- return MOD_RES_PASSTHRU;
-}
-
-void ModuleDelayJoin::OnUserQuit(User* user, const std::string &reason, const std::string &oper_message)
-{
- Command* parthandler = ServerInstance->Parser->GetHandler("PART");
- if (!parthandler)
- return;
- for (UCListIter f = user->chans.begin(); f != user->chans.end(); f++)
- {
- Channel* chan = *f;
- Membership* memb = chan->GetUser(user);
+ Channel* c = *i++;
+ Membership* memb = c->GetUser(source);
if (memb && unjoined.get(memb))
- {
- std::vector<std::string> parameters;
- parameters.push_back(chan->name);
- /* Send a fake PART from the channel, which will be silent */
- parthandler->Handle(parameters, user);
- }
+ include.erase(c);
}
}
diff --git a/src/modules/m_invisible.cpp b/src/modules/m_invisible.cpp
index 9c4a58278..1e8be61f5 100644
--- a/src/modules/m_invisible.cpp
+++ b/src/modules/m_invisible.cpp
@@ -115,8 +115,8 @@ class ModuleInvisible : public Module
/* Yeah i know people can take this out. I'm not about to obfuscate code just to be a pain in the ass. */
ServerInstance->Users->ServerNoticeAll("*** m_invisible.so has just been loaded on this network. For more information, please visit http://inspircd.org/wiki/Modules/invisible");
Implementation eventlist[] = {
- I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserJoin, I_OnUserPart, I_OnUserQuit,
- I_OnHostCycle, I_OnSendWhoLine, I_OnNamesListItem
+ I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserJoin,
+ I_OnBuildNeighborList, I_OnSendWhoLine, I_OnNamesListItem
};
ServerInstance->Modules->Attach(eventlist, this, 8);
};
@@ -127,9 +127,7 @@ class ModuleInvisible : public Module
Version GetVersion();
void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts);
- void OnUserPart(Membership* memb, std::string &partmessage, CUList& excepts);
- void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message);
- ModResult OnHostCycle(User* user);
+ void OnBuildNeighborList(User* source, UserChanList &include, std::map<User*,bool> &exceptions);
ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list);
ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list);
void OnSendWhoLine(User* source, User* user, Channel* channel, std::string& line);
@@ -162,41 +160,14 @@ void ModuleInvisible::OnUserJoin(Membership* memb, bool sync, bool created, CULi
}
}
-void ModuleInvisible::OnUserPart(Membership* memb, std::string &partmessage, CUList& excepts)
+void ModuleInvisible::OnBuildNeighborList(User* source, UserChanList &include, std::map<User*,bool> &exceptions)
{
- if (memb->user->IsModeSet('Q'))
- {
- BuildExcept(memb, excepts);
- }
-}
-
-void ModuleInvisible::OnUserQuit(User* user, const std::string &reason, const std::string &oper_message)
-{
- if (user->IsModeSet('Q'))
+ if (source->IsModeSet('Q'))
{
- Command* parthandler = ServerInstance->Parser->GetHandler("PART");
- std::vector<std::string> to_leave;
- if (parthandler)
- {
- for (UCListIter f = user->chans.begin(); f != user->chans.end(); f++)
- to_leave.push_back((*f)->name);
- /* We cant do this neatly in one loop, as we are modifying the map we are iterating */
- for (std::vector<std::string>::iterator n = to_leave.begin(); n != to_leave.end(); n++)
- {
- std::vector<std::string> parameters;
- parameters.push_back(*n);
- /* This triggers our OnUserPart, above, making the PART silent */
- parthandler->Handle(parameters, user);
- }
- }
+ include.clear();
}
}
-ModResult ModuleInvisible::OnHostCycle(User* user)
-{
- return user->IsModeSet('Q') ? MOD_RES_DENY : MOD_RES_PASSTHRU;
-}
-
/* No privmsg response when hiding - submitted by Eric at neowin */
ModResult ModuleInvisible::OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
{
diff --git a/src/modules/m_silence.cpp b/src/modules/m_silence.cpp
index eae6bf35c..dd7a62726 100644
--- a/src/modules/m_silence.cpp
+++ b/src/modules/m_silence.cpp
@@ -277,8 +277,8 @@ class ModuleSilence : public Module
ServerInstance->AddCommand(&cmdsilence);
ServerInstance->AddCommand(&cmdsvssilence);
- Implementation eventlist[] = { I_OnRehash, I_OnBuildExemptList, I_On005Numeric, I_OnUserPreNotice, I_OnUserPreMessage, I_OnUserPreInvite };
- ServerInstance->Modules->Attach(eventlist, this, 6);
+ Implementation eventlist[] = { I_OnRehash, I_On005Numeric, I_OnUserPreNotice, I_OnUserPreMessage, I_OnUserPreInvite };
+ ServerInstance->Modules->Attach(eventlist, this, 5);
}
void OnRehash(User* user)
diff --git a/src/users.cpp b/src/users.cpp
index 10ed754bb..889e5acdc 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -1199,78 +1199,80 @@ void User::WriteTo(User *dest, const std::string &data)
dest->WriteFrom(this, data);
}
-
void User::WriteCommon(const char* text, ...)
{
char textbuffer[MAXBUF];
va_list argsPtr;
- if (this->registered != REG_ALL)
+ if (this->registered != REG_ALL || !IS_LOCAL(this) || quitting)
return;
+ int len = snprintf(textbuffer,MAXBUF,":%s ",this->GetFullHost().c_str());
+
va_start(argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
+ vsnprintf(textbuffer + len, MAXBUF - len, text, argsPtr);
va_end(argsPtr);
- this->WriteCommon(std::string(textbuffer));
+ this->WriteCommonRaw(std::string(textbuffer), true);
}
-void User::WriteCommon(const std::string &text)
+void User::WriteCommonExcept(const char* text, ...)
{
- bool sent_to_at_least_one = false;
- char tb[MAXBUF];
+ char textbuffer[MAXBUF];
+ va_list argsPtr;
- if (this->registered != REG_ALL)
+ if (this->registered != REG_ALL || !IS_LOCAL(this) || quitting)
return;
- uniq_id++;
+ int len = snprintf(textbuffer,MAXBUF,":%s ",this->GetFullHost().c_str());
+
+ va_start(argsPtr, text);
+ vsnprintf(textbuffer + len, MAXBUF - len, text, argsPtr);
+ va_end(argsPtr);
+
+ this->WriteCommonRaw(std::string(textbuffer), false);
+}
+
+void User::WriteCommonRaw(const std::string &line, bool include_self)
+{
+ if (this->registered != REG_ALL || !IS_LOCAL(this) || quitting)
+ return;
if (!already_sent)
InitializeAlreadySent(ServerInstance->SE);
+ uniq_id++;
+
+ UserChanList include_c(chans);
+ std::map<User*,bool> exceptions;
- /* We dont want to be doing this n times, just once */
- snprintf(tb,MAXBUF,":%s %s",this->GetFullHost().c_str(),text.c_str());
- std::string out = tb;
+ exceptions[this] = include_self;
- for (UCListIter v = this->chans.begin(); v != this->chans.end(); v++)
+ FOREACH_MOD(I_OnBuildNeighborList,OnBuildNeighborList(this, include_c, exceptions));
+
+ for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
{
- const UserMembList* ulist = (*v)->GetUsers();
+ User* u = i->first;
+ if (IS_LOCAL(u) && !u->quitting)
+ {
+ already_sent[u->fd] = uniq_id;
+ if (i->second)
+ u->Write(line);
+ }
+ }
+ for (UCListIter v = include_c.begin(); v != include_c.end(); ++v)
+ {
+ Channel* c = *v;
+ const UserMembList* ulist = c->GetUsers();
for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++)
{
- if ((IS_LOCAL(i->first)) && (already_sent[i->first->fd] != uniq_id))
+ User* u = i->first;
+ if (IS_LOCAL(u) && !u->quitting && already_sent[u->fd] != uniq_id)
{
- already_sent[i->first->fd] = uniq_id;
- i->first->Write(out);
- sent_to_at_least_one = true;
+ already_sent[u->fd] = uniq_id;
+ u->Write(line);
}
}
}
-
- /*
- * if the user was not in any channels, no users will receive the text. Make sure the user
- * receives their OWN message for WriteCommon
- */
- if (!sent_to_at_least_one)
- {
- this->Write(std::string(tb));
- }
-}
-
-
-/* write a formatted string to all users who share at least one common
- * channel, NOT including the source user e.g. for use in QUIT
- */
-
-void User::WriteCommonExcept(const char* text, ...)
-{
- char textbuffer[MAXBUF];
- va_list argsPtr;
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
- this->WriteCommonExcept(std::string(textbuffer));
}
void User::WriteCommonQuit(const std::string &normal_text, const std::string &oper_text)
@@ -1291,53 +1293,34 @@ void User::WriteCommonQuit(const std::string &normal_text, const std::string &op
std::string out1 = tb1;
std::string out2 = tb2;
- for (UCListIter v = this->chans.begin(); v != this->chans.end(); v++)
+ UserChanList include_c(chans);
+ std::map<User*,bool> exceptions;
+
+ FOREACH_MOD(I_OnBuildNeighborList,OnBuildNeighborList(this, include_c, exceptions));
+
+ for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
{
- const UserMembList* ulist = (*v)->GetUsers();
- for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++)
+ User* u = i->first;
+ if (IS_LOCAL(u) && !u->quitting)
{
- User* u = i->first;
- if (IS_LOCAL(u) && !u->quitting && (already_sent[u->fd] != uniq_id))
- {
- already_sent[u->fd] = uniq_id;
+ already_sent[u->fd] = uniq_id;
+ if (i->second)
u->Write(IS_OPER(u) ? out2 : out1);
- }
}
}
-}
-
-void User::WriteCommonExcept(const std::string &text)
-{
- char tb1[MAXBUF];
- std::string out1;
-
- if (this->registered != REG_ALL)
- return;
-
- uniq_id++;
-
- if (!already_sent)
- InitializeAlreadySent(ServerInstance->SE);
-
- snprintf(tb1,MAXBUF,":%s %s",this->GetFullHost().c_str(),text.c_str());
- out1 = tb1;
-
- for (UCListIter v = this->chans.begin(); v != this->chans.end(); v++)
+ for (UCListIter v = include_c.begin(); v != include_c.end(); ++v)
{
const UserMembList* ulist = (*v)->GetUsers();
for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++)
{
- if (this != i->first)
+ User* u = i->first;
+ if (IS_LOCAL(u) && !u->quitting && (already_sent[u->fd] != uniq_id))
{
- if ((IS_LOCAL(i->first)) && (already_sent[i->first->fd] != uniq_id))
- {
- already_sent[i->first->fd] = uniq_id;
- i->first->Write(out1);
- }
+ already_sent[u->fd] = uniq_id;
+ u->Write(IS_OPER(u) ? out2 : out1);
}
}
}
-
}
void User::WriteWallOps(const std::string &text)
@@ -1419,12 +1402,7 @@ void User::DoHostCycle(const std::string &quitline)
{
char buffer[MAXBUF];
- ModResult result = MOD_RES_PASSTHRU;
- FIRST_MOD_RESULT(OnHostCycle, result, (this));
-
- if (result == MOD_RES_DENY)
- return;
- if (result == MOD_RES_PASSTHRU && !ServerInstance->Config->CycleHosts)
+ if (!ServerInstance->Config->CycleHosts)
return;
uniq_id++;
@@ -1432,7 +1410,22 @@ void User::DoHostCycle(const std::string &quitline)
if (!already_sent)
InitializeAlreadySent(ServerInstance->SE);
- for (UCListIter v = this->chans.begin(); v != this->chans.end(); v++)
+ UserChanList include_c(chans);
+ std::map<User*,bool> exceptions;
+
+ FOREACH_MOD(I_OnBuildNeighborList,OnBuildNeighborList(this, include_c, exceptions));
+
+ for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
+ {
+ User* u = i->first;
+ if (IS_LOCAL(u) && !u->quitting)
+ {
+ already_sent[u->fd] = uniq_id;
+ if (i->second)
+ u->Write(quitline);
+ }
+ }
+ for (UCListIter v = include_c.begin(); v != include_c.end(); ++v)
{
Channel* c = *v;
snprintf(buffer, MAXBUF, ":%s JOIN %s", GetFullHost().c_str(), c->name.c_str());