diff options
-rw-r--r-- | docs/inspircd.conf.example | 5 | ||||
-rw-r--r-- | include/modules.h | 9 | ||||
-rw-r--r-- | src/channels.cpp | 11 | ||||
-rw-r--r-- | src/cmd_modules.cpp | 2 | ||||
-rw-r--r-- | src/modules.cpp | 1 | ||||
-rw-r--r-- | src/modules/m_alias.cpp | 3 | ||||
-rw-r--r-- | src/modules/m_namesx.cpp | 152 | ||||
-rw-r--r-- | src/modules/m_spanningtree.cpp | 46 |
8 files changed, 203 insertions, 26 deletions
diff --git a/docs/inspircd.conf.example b/docs/inspircd.conf.example index b7dcec7ad..2838ce8e4 100644 --- a/docs/inspircd.conf.example +++ b/docs/inspircd.conf.example @@ -993,6 +993,11 @@ #<database name="mydb" username="myuser" password="mypass" hostname="localhost" id="my_database2"> #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# +# NAMESX module: Provides support for the NAMESX extension which allows +# clients to see all the prefixes set on a user without getting confused. +#<module name="m_namesx.so"> + +#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# # Nicklock module: Let opers change a user's nick and then stop that # user from changing their nick again. /NICKLOCK and /NICKUNLOCK #<module name="m_nicklock.so"> diff --git a/include/modules.h b/include/modules.h index c3b9b0448..f80960f6f 100644 --- a/include/modules.h +++ b/include/modules.h @@ -343,7 +343,7 @@ enum Implementation { I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUse I_OnCheckKey, I_OnCheckLimit, I_OnCheckBan, I_OnStats, I_OnChangeLocalUserHost, I_OnChangeLocalUserGecos, I_OnLocalTopicChange, I_OnPostLocalTopicChange, I_OnEvent, I_OnRequest, I_OnOperCompre, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan, I_OnDelBan, I_OnRawSocketAccept, I_OnRawSocketClose, I_OnRawSocketWrite, I_OnRawSocketRead, I_OnChangeLocalUserGECOS, I_OnUserRegister, - I_OnOperCompare, I_OnChannelDelete, I_OnPostOper, I_OnSyncOtherMetaData, I_OnSetAway, I_OnCancelAway }; + I_OnOperCompare, I_OnChannelDelete, I_OnPostOper, I_OnSyncOtherMetaData, I_OnSetAway, I_OnCancelAway, I_OnUserList }; /** Base class for all InspIRCd modules * This class is the base class for InspIRCd modules. All modules must inherit from this class, @@ -1239,6 +1239,13 @@ class Module : public Extensible /** Called when a user cancels their away state. */ virtual void OnCancelAway(userrec* user); + + /** Called whenever a NAMES list is requested. + * You can produce the nameslist yourself, overriding the current list, + * and if you do you must return 1. If you do not handle the names list, + * return 0. + */ + virtual int OnUserList(userrec* user, chanrec* Ptr); }; diff --git a/src/channels.cpp b/src/channels.cpp index e7564c3ea..345ec79dd 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -450,7 +450,6 @@ chanrec* chanrec::ForceChan(InspIRCd* Instance, chanrec* Ptr,ucrec *a,userrec* u user->WriteServ("333 %s %s %s %lu", user->nick, Ptr->name, Ptr->setby, (unsigned long)Ptr->topicset); } Ptr->UserList(user); - user->WriteServ("366 %s %s :End of /NAMES list.", user->nick, Ptr->name); } FOREACH_MOD_I(Instance,I_OnUserJoin,OnUserJoin(user,Ptr)); return Ptr; @@ -811,6 +810,14 @@ void chanrec::UserList(userrec *user) { char list[MAXBUF]; size_t dlen, curlen; + int MOD_RESULT = 0; + + FOREACH_RESULT(I_OnUserList,OnUserList(user, this)); + ServerInstance->Log(DEBUG,"MOD_RESULT for UserList = %d",MOD_RESULT); + if (MOD_RESULT == 1) + return; + + ServerInstance->Log(DEBUG,"Using builtin NAMES list generation"); dlen = curlen = snprintf(list,MAXBUF,"353 %s = %s :", user->nick, this->name); @@ -861,6 +868,8 @@ void chanrec::UserList(userrec *user) { user->WriteServ(list); } + + user->WriteServ("366 %s %s :End of /NAMES list.", user->nick, this->name); } long chanrec::GetMaxBans() diff --git a/src/cmd_modules.cpp b/src/cmd_modules.cpp index 995384f05..442983873 100644 --- a/src/cmd_modules.cpp +++ b/src/cmd_modules.cpp @@ -45,7 +45,7 @@ char* itab[] = { "OnCheckKey", "OnCheckLimit", "OnCheckBan", "OnStats", "OnChangeLocalUserHost", "OnChangeLocalUserGecos", "OnLocalTopicChange", "OnPostLocalTopicChange", "OnEvent", "OnRequest", "OnOperCompre", "OnGlobalOper", "OnPostConnect", "OnAddBan", "OnDelBan", "OnRawSocketAccept", "OnRawSocketClose", "OnRawSocketWrite", "OnRawSocketRead", "OnChangeLocalUserGECOS", "OnUserRegister", - "OnOperCompare", "OnChannelDelete", "OnPostOper", "OnSyncOtherMetaData", "OnSetAway", "OnCancelAway", NULL + "OnOperCompare", "OnChannelDelete", "OnPostOper", "OnSyncOtherMetaData", "OnSetAway", "OnCancelAway", "OnNamesList", NULL }; void cmd_modules::Handle (const char** parameters, int pcnt, userrec *user) diff --git a/src/modules.cpp b/src/modules.cpp index c6bacaa54..bb6092570 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -209,6 +209,7 @@ void Module::OnChannelDelete(chanrec* chan) { }; Priority Module::Prioritize() { return PRIORITY_DONTCARE; } void Module::OnSetAway(userrec* user) { }; void Module::OnCancelAway(userrec* user) { }; +int Module::OnUserList(userrec* user, chanrec* Ptr) { return 0; }; /* server is a wrapper class that provides methods to all of the C-style * exports in the core diff --git a/src/modules/m_alias.cpp b/src/modules/m_alias.cpp index 09cf15947..855b5b46c 100644 --- a/src/modules/m_alias.cpp +++ b/src/modules/m_alias.cpp @@ -19,15 +19,12 @@ using namespace std; #include "users.h" #include "channels.h" #include "modules.h" - #include "commands.h" #include "inspircd.h" #include <vector> /* $ModDesc: Provides aliases of commands. */ - - class Alias : public classbase { public: diff --git a/src/modules/m_namesx.cpp b/src/modules/m_namesx.cpp new file mode 100644 index 000000000..90c55e648 --- /dev/null +++ b/src/modules/m_namesx.cpp @@ -0,0 +1,152 @@ +/* +------------------------------------+ + * | Inspire Internet Relay Chat Daemon | + * +------------------------------------+ + * + * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev. + * E-mail: + * <brain@chatspike.net> + * <Craig@chatspike.net> + * + * Written by Craig Edwards, Craig McLure, and others. + * This program is free but copyrighted software; see + *the file COPYING for details. + * + * --------------------------------------------------- + */ + +using namespace std; + +#include "users.h" +#include "channels.h" +#include "modules.h" +#include "commands.h" +#include "inspircd.h" +#include <vector> + +static const char* dummy = "ON"; + +/* $ModDesc: Provides aliases of commands. */ + +class ModuleNamesX : public Module +{ + public: + + ModuleNamesX(InspIRCd* Me) + : Module::Module(Me) + { + } + + void Implements(char* List) + { + List[I_OnPreCommand] = List[I_OnUserList] = List[I_On005Numeric] = 1; + } + + virtual ~ModuleNamesX() + { + } + + virtual Version GetVersion() + { + return Version(1,0,0,1,VF_VENDOR); + } + + virtual void On005Numeric(std::string &output) + { + output.append(" NAMESX"); + } + + virtual int OnPreCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, bool validated) + { + irc::string c = command.c_str(); + /* We don't actually create a proper command handler class for PROTOCTL, + * because other modules might want to have PROTOCTL hooks too. + * Therefore, we just hook its as an unvalidated command therefore we + * can capture it even if it doesnt exist! :-) + */ + if (c == "PROTOCTL") + { + if ((pcnt) && (!strcasecmp(parameters[0],"NAMESX"))) + { + ServerInstance->Log(DEBUG,"Setting this user as NAMESX capable"); + user->Extend("NAMESX",dummy); + return 1; + } + } + return 0; + } + + virtual int OnUserList(userrec* user, chanrec* Ptr) + { + ServerInstance->Log(DEBUG,"NAMESX called for %s %s",user->nick,Ptr->name); + if (user->GetExt("NAMESX")) + { + ServerInstance->Log(DEBUG,"Using NAMESX user list code"); + char list[MAXBUF]; + size_t dlen, curlen; + dlen = curlen = snprintf(list,MAXBUF,"353 %s = %s :", user->nick, Ptr->name); + int numusers = 0; + char* ptr = list + dlen; + CUList *ulist= Ptr->GetUsers(); + bool has_user = Ptr->HasUser(user); + for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++) + { + if ((!has_user) && (i->second->modes[UM_INVISIBLE])) + { + continue; + } + size_t ptrlen = snprintf(ptr, MAXBUF, "%s%s ", Ptr->GetAllPrefixChars(i->second), i->second->nick); + curlen += ptrlen; + ptr += ptrlen; + numusers++; + if (curlen > (480-NICKMAX)) + { + /* list overflowed into multiple numerics */ + ServerInstance->Log(DEBUG,"Send list 1"); + user->WriteServ(list); + /* reset our lengths */ + dlen = curlen = snprintf(list,MAXBUF,"353 %s = %s :", user->nick, Ptr->name); + ptr = list + dlen; + ptrlen = 0; + numusers = 0; + } + } + /* if whats left in the list isnt empty, send it */ + if (numusers) + { + ServerInstance->Log(DEBUG,"Send list 2"); + user->WriteServ(list); + } + user->WriteServ("366 %s %s :End of /NAMES list.", user->nick, Ptr->name); + ServerInstance->Log(DEBUG,"Returning 1"); + return 1; + } + + ServerInstance->Log(DEBUG,"Returning 0"); + return 0; + } +}; + + +class ModuleNamesXFactory : public ModuleFactory +{ + public: + ModuleNamesXFactory() + { + } + + ~ModuleNamesXFactory() + { + } + + virtual Module * CreateModule(InspIRCd* Me) + { + return new ModuleNamesX(Me); + } +}; + + +extern "C" void * init_module( void ) +{ + return new ModuleNamesXFactory; +} + diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp index 95a6a97f2..cceaeb70d 100644 --- a/src/modules/m_spanningtree.cpp +++ b/src/modules/m_spanningtree.cpp @@ -4018,17 +4018,20 @@ class ModuleSpanningTree : public Module if (IS_LOCAL(user)) { chanrec *c = (chanrec*)dest; - std::string cname = c->name; - if (status) - cname = status + cname; - std::deque<TreeServer*> list; - GetListOfServersForChannel(c,list); - unsigned int ucount = list.size(); - for (unsigned int i = 0; i < ucount; i++) + if (c) { - TreeSocket* Sock = list[i]->GetSocket(); - if (Sock) - Sock->WriteLine(":"+std::string(user->nick)+" NOTICE "+cname+" :"+text); + std::string cname = c->name; + if (status) + cname = status + cname; + std::deque<TreeServer*> list; + GetListOfServersForChannel(c,list); + unsigned int ucount = list.size(); + for (unsigned int i = 0; i < ucount; i++) + { + TreeSocket* Sock = list[i]->GetSocket(); + if (Sock) + Sock->WriteLine(":"+std::string(user->nick)+" NOTICE "+cname+" :"+text); + } } } } @@ -4066,17 +4069,20 @@ class ModuleSpanningTree : public Module if (IS_LOCAL(user)) { chanrec *c = (chanrec*)dest; - std::string cname = c->name; - if (status) - cname = status + cname; - std::deque<TreeServer*> list; - GetListOfServersForChannel(c,list); - unsigned int ucount = list.size(); - for (unsigned int i = 0; i < ucount; i++) + if (c) { - TreeSocket* Sock = list[i]->GetSocket(); - if (Sock) - Sock->WriteLine(":"+std::string(user->nick)+" PRIVMSG "+cname+" :"+text); + std::string cname = c->name; + if (status) + cname = status + cname; + std::deque<TreeServer*> list; + GetListOfServersForChannel(c,list); + unsigned int ucount = list.size(); + for (unsigned int i = 0; i < ucount; i++) + { + TreeSocket* Sock = list[i]->GetSocket(); + if (Sock) + Sock->WriteLine(":"+std::string(user->nick)+" PRIVMSG "+cname+" :"+text); + } } } } |