summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/modules/m_channames.cpp145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/modules/m_channames.cpp b/src/modules/m_channames.cpp
new file mode 100644
index 000000000..8b75a06a7
--- /dev/null
+++ b/src/modules/m_channames.cpp
@@ -0,0 +1,145 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+
+/* $ModDesc: Implements config tags which allow changing characters allowed in channel names */
+
+static bool allowedmap[256];
+
+class NewIsChannelHandler : public HandlerBase2<bool, const char*, size_t>
+{
+ InspIRCd* Server;
+ public:
+ NewIsChannelHandler(InspIRCd* Srv) : Server(Srv) { }
+ virtual ~NewIsChannelHandler() { }
+ virtual bool Call(const char*, size_t);
+};
+
+bool NewIsChannelHandler::Call(const char* chname, size_t max)
+{
+ const char *c = chname + 1;
+
+ /* check for no name - don't check for !*chname, as if it is empty, it won't be '#'! */
+ if (!chname || *chname != '#')
+ return false;
+
+ while (*c)
+ if (!allowedmap[(unsigned int)(*c++)]) return false;
+
+ size_t len = c - chname;
+ return len <= max;
+}
+
+class ModuleChannelNames : public Module
+{
+ private:
+ InspIRCd* ServerInstance;
+ NewIsChannelHandler* myhandler;
+ caller2<bool, const char*, size_t> * rememberer;
+ bool badchan;
+
+ public:
+ ModuleChannelNames(InspIRCd* Me) : Module(Me)
+ {
+ rememberer = (caller2<bool, const char*, size_t> *) malloc(sizeof(caller2<bool, const char*, size_t>));
+ ServerInstance = Me;
+ *rememberer = ServerInstance->IsChannel;
+ myhandler = new NewIsChannelHandler(ServerInstance);
+ ServerInstance->IsChannel = myhandler;
+ badchan = false;
+ Implementation eventlist[] = { I_OnRehash, I_OnUserKick };
+ ServerInstance->Modules->Attach(eventlist, this, 2);
+ OnRehash(NULL);
+ }
+
+ void ValidateChans()
+ {
+ badchan = true;
+ std::vector<Channel*> chanvec;
+ for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); ++i)
+ {
+ if (!ServerInstance->IsChannel(i->second->name.c_str(), MAXBUF))
+ chanvec.push_back(i->second);
+ }
+ std::vector<Channel*>::reverse_iterator c2 = chanvec.rbegin();
+ while (c2 != chanvec.rend())
+ {
+ Channel* c = *c2++;
+ if (c->IsModeSet('P') && c->GetUserCounter())
+ {
+ std::vector<std::string> modes;
+ modes.push_back(c->name);
+ modes.push_back("-P");
+
+ ServerInstance->SendMode(modes, ServerInstance->FakeClient);
+ ServerInstance->PI->SendMode(c->name, ServerInstance->Modes->GetLastParseParams(), ServerInstance->Modes->GetLastParseTranslate());
+ }
+ const UserMembList* users = c->GetUsers();
+ for(UserMembCIter j = users->begin(); j != users->end(); ++j)
+ if (IS_LOCAL(j->first) && !c->ServerKickUser(j->first, "Channel name no longer valid", NULL))
+ delete c;
+ }
+ badchan = false;
+ }
+
+ virtual void OnRehash(User* user)
+ {
+ ConfigReader Conf(ServerInstance);
+ std::string denyToken = Conf.ReadValue("channames", "denyrange", 0);
+ std::string allowToken = Conf.ReadValue("channames", "allowrange", 0);
+ memset(allowedmap, 1, sizeof(allowedmap));
+
+ irc::portparser denyrange(denyToken, false);
+ int denyno = -1;
+ while (0 != (denyno = denyrange.GetToken()))
+ allowedmap[(unsigned char)(denyno)] = false;
+
+ irc::portparser allowrange(allowToken, false);
+ int allowno = -1;
+ while (0 != (allowno = allowrange.GetToken()))
+ allowedmap[(unsigned char)(allowno)] = true;
+
+ allowedmap[7] = false;
+ allowedmap[' '] = false;
+ allowedmap[','] = false;
+
+ ValidateChans();
+ }
+
+ virtual void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& except_list)
+ {
+ if (badchan)
+ {
+ const UserMembList* users = memb->chan->GetUsers();
+ for(UserMembCIter i = users->begin(); i != users->end(); i++)
+ if (i->first != memb->user)
+ except_list.insert(i->first);
+ }
+ }
+
+ virtual ~ModuleChannelNames()
+ {
+ delete myhandler;
+ ServerInstance->IsChannel = *rememberer;
+ free(rememberer);
+ ValidateChans();
+ }
+
+ virtual Version GetVersion()
+ {
+ return Version("$Id$", VF_VENDOR,API_VERSION);
+ }
+};
+
+MODULE_INIT(ModuleChannelNames)