diff options
Diffstat (limited to 'src/modules/m_namedmodes.cpp')
-rw-r--r-- | src/modules/m_namedmodes.cpp | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/modules/m_namedmodes.cpp b/src/modules/m_namedmodes.cpp new file mode 100644 index 000000000..4bf8960e1 --- /dev/null +++ b/src/modules/m_namedmodes.cpp @@ -0,0 +1,136 @@ +/* +------------------------------------+ + * | 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" + +class ModuleNamedModes : public Module +{ + public: + ModuleNamedModes() + { + Implementation eventlist[] = { I_OnPreMode, I_On005Numeric }; + ServerInstance->Modules->Attach(eventlist, this, 2); + } + + Version GetVersion() + { + return Version("Provides the ability to manipulate modes via long names.",VF_VENDOR); + } + + void On005Numeric(std::string& line) + { + std::string::size_type pos = line.find(" CHANMODES="); + if (pos != std::string::npos) + { + pos += 11; + while (line[pos] > 'A' && line[pos] < 'Z') + pos++; + line.insert(pos, 1, 'Z'); + } + } + + void DisplayList(User* user, Channel* channel) + { + for(char letter = 'A'; letter <= 'z'; letter++) + { + ModeHandler* mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL); + if (!mh || mh->IsListMode()) + continue; + if (!channel->IsModeSet(letter)) + continue; + std::string item = mh->name; + if (mh->GetNumParams(true)) + item += "=" + channel->GetModeParameter(letter); + user->WriteNumeric(961, "%s %s %s", user->nick.c_str(), channel->name.c_str(), item.c_str()); + } + user->WriteNumeric(960, "%s %s :End of mode list", user->nick.c_str(), channel->name.c_str()); + } + + ModResult OnPreMode(User* source, User* dest, Channel* channel, const std::vector<std::string>& parameters) + { + if (!channel) + return MOD_RES_PASSTHRU; + if (parameters[1].find('Z') == std::string::npos) + return MOD_RES_PASSTHRU; + if (parameters.size() <= 2) + { + DisplayList(source, channel); + return MOD_RES_DENY; + } + + std::vector<std::string> newparms; + newparms.push_back(parameters[0]); + newparms.push_back(parameters[1]); + + std::string modelist = newparms[1]; + bool adding = true; + unsigned int param_at = 2; + for(unsigned int i = 0; i < modelist.length(); i++) + { + unsigned char modechar = modelist[i]; + if (modechar == '+' || modechar == '-') + { + adding = (modechar == '+'); + continue; + } + ModeHandler *mh = ServerInstance->Modes->FindMode(modechar, MODETYPE_CHANNEL); + if (modechar == 'Z') + { + modechar = 0; + std::string name, value; + if (param_at < parameters.size()) + name = parameters[param_at++]; + std::string::size_type eq = name.find('='); + if (eq != std::string::npos) + { + value = name.substr(eq + 1); + name = name.substr(0, eq); + } + for(char letter = 'A'; modechar == 0 && letter <= 'z'; letter++) + { + mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL); + if (mh && mh->name == name) + { + if (mh->GetNumParams(adding)) + { + if (!value.empty()) + { + newparms.push_back(value); + modechar = letter; + break; + } + } + else + { + modechar = letter; + break; + } + } + } + if (modechar) + modelist[i] = modechar; + else + modelist.erase(i, 1); + } + else if (mh && mh->GetNumParams(adding) && param_at < parameters.size()) + { + newparms.push_back(parameters[param_at++]); + } + } + newparms[1] = modelist; + ServerInstance->Modes->Process(newparms, source, false); + return MOD_RES_DENY; + } +}; + +MODULE_INIT(ModuleNamedModes) |