diff options
-rw-r--r-- | src/modules/m_channames.cpp | 145 |
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) |