summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/inspircd.conf.example5
-rw-r--r--include/modules.h9
-rw-r--r--src/channels.cpp11
-rw-r--r--src/cmd_modules.cpp2
-rw-r--r--src/modules.cpp1
-rw-r--r--src/modules/m_alias.cpp3
-rw-r--r--src/modules/m_namesx.cpp152
-rw-r--r--src/modules/m_spanningtree.cpp46
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);
+ }
}
}
}