#include "inspircd.h"
-#include "builtinmodes.h"
ModeHandler::ModeHandler(Module* Creator, const std::string& Name, char modeletter, ParamSpec Params, ModeType type, Class mclass)
- : ServiceProvider(Creator, Name, SERVICE_MODE), modeid(ModeParser::MODEID_MAX),
- parameters_taken(Params), mode(modeletter), oper(false),
- list(false), m_type(type), type_id(mclass), levelrequired(HALFOP_VALUE)
+ : ServiceProvider(Creator, Name, SERVICE_MODE)
+ , modeid(ModeParser::MODEID_MAX)
+ , parameters_taken(Params)
+ , mode(modeletter)
+ , oper(false)
+ , list(false)
+ , m_type(type)
+ , type_id(mclass)
+ , ranktoset(HALFOP_VALUE)
+ , ranktounset(HALFOP_VALUE)
{
}
return false;
}
-std::string ModeHandler::GetUserParameter(User* user)
+std::string ModeHandler::GetUserParameter(const User* user) const
{
return "";
}
void ModeHandler::OnParameterMissing(User* user, User* dest, Channel* channel)
{
+ const std::string message = InspIRCd::Format("You must specify a parameter for the %s mode", name.c_str());
+ if (channel)
+ user->WriteNumeric(Numerics::InvalidModeParameter(channel, this, "*", message));
+ else
+ user->WriteNumeric(Numerics::InvalidModeParameter(dest, this, "*", message));
}
bool ModeHandler::ResolveModeConflict(std::string& theirs, const std::string& ours, Channel*)
PrefixMode::PrefixMode(Module* Creator, const std::string& Name, char ModeLetter, unsigned int Rank, char PrefixChar)
: ModeHandler(Creator, Name, ModeLetter, PARAM_ALWAYS, MODETYPE_CHANNEL, MC_PREFIX)
- , prefix(PrefixChar), prefixrank(Rank)
+ , prefix(PrefixChar)
+ , prefixrank(Rank)
+ , selfremove(true)
{
list = true;
}
+ModResult PrefixMode::AccessCheck(User* src, Channel*, std::string& value, bool adding)
+{
+ if (!adding && src->nick == value && selfremove)
+ return MOD_RES_ALLOW;
+ return MOD_RES_PASSTHRU;
+}
+
ModeAction PrefixMode::OnModeChange(User* source, User*, Channel* chan, std::string& parameter, bool adding)
{
User* target;
return (memb->SetPrefix(this, adding) ? MODEACTION_ALLOW : MODEACTION_DENY);
}
+void PrefixMode::Update(unsigned int rank, unsigned int setrank, unsigned int unsetrank, bool selfrm)
+{
+ prefixrank = rank;
+ ranktoset = setrank;
+ ranktounset = unsetrank;
+ selfremove = selfrm;
+}
+
ModeAction ParamModeBase::OnModeChange(User* source, User*, Channel* chan, std::string& parameter, bool adding)
{
if (adding)
return MODEACTION_DENY;
if (MOD_RESULT == MOD_RES_PASSTHRU)
{
- unsigned int neededrank = mh->GetLevelRequired();
+ unsigned int neededrank = mh->GetLevelRequired(adding);
/* Compare our rank on the channel against the rank of the required prefix,
* allow if >= ours. Because mIRC and xchat throw a tizz if the modes shown
* in NAMES(X) are not in rank order, we know the most powerful mode is listed
if (IS_LOCAL(user) && !user->IsOper())
{
- char* disabled = (type == MODETYPE_CHANNEL) ? ServerInstance->Config->DisabledCModes : ServerInstance->Config->DisabledUModes;
- if (disabled[modechar - 'A'])
+ const std::bitset<64>& disabled = (type == MODETYPE_CHANNEL) ? ServerInstance->Config->DisabledCModes : ServerInstance->Config->DisabledUModes;
+ if (disabled.test(modechar - 'A'))
{
user->WriteNumeric(ERR_NOPRIVILEGES, InspIRCd::Format("Permission Denied - %s mode %c has been locked by the administrator",
type == MODETYPE_CHANNEL ? "channel" : "user", modechar));
Modes::Change& item = *i;
ModeHandler* mh = item.mh;
+ // If a mode change has been given for a mode that does not exist then reject
+ // it. This can happen when core_reloadmodule attempts to restore a mode that
+ // no longer exists.
+ if (!mh)
+ continue;
+
// If the mode is supposed to have a parameter then we first take a look at item.param
// and, if we were asked to, also handle mode merges now
if (mh->NeedsParam(item.adding))
void ModeParser::AddMode(ModeHandler* mh)
{
- /* Yes, i know, this might let people declare modes like '_' or '^'.
- * If they do that, thats their problem, and if i ever EVER see an
- * official InspIRCd developer do that, i'll beat them with a paddle!
- */
- if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z'))
+ if (!ModeParser::IsModeChar(mh->GetModeChar()))
throw ModuleException("Invalid letter for mode " + mh->name);
/* A mode prefix of ',' is not acceptable, it would fuck up server to server.
bool ModeParser::DelMode(ModeHandler* mh)
{
- if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z'))
+ if (!ModeParser::IsModeChar(mh->GetModeChar()))
return false;
ModeHandlerMap& mhmap = modehandlersbyname[mh->GetModeType()];
ModeHandler* ModeParser::FindMode(unsigned const char modeletter, ModeType mt)
{
- if ((modeletter < 'A') || (modeletter > 'z'))
+ if (!ModeParser::IsModeChar(modeletter))
return NULL;
return modehandlers[mt][modeletter-65];
void ModeParser::RecreateModeListFor004Numeric()
{
- Cached004ModeList = CreateModeList(MODETYPE_USER) + " " + CreateModeList(MODETYPE_CHANNEL) + " " + CreateModeList(MODETYPE_CHANNEL, true);
+ Cached004ModeList[0] = CreateModeList(MODETYPE_USER);
+ Cached004ModeList[1] = CreateModeList(MODETYPE_CHANNEL);
+ Cached004ModeList[2] = CreateModeList(MODETYPE_CHANNEL, true);
}
PrefixMode* ModeParser::FindPrefix(unsigned const char pfxletter)
const Channel::MemberMap& userlist = chan->GetUsers();
for (Channel::MemberMap::const_iterator i = userlist.begin(); i != userlist.end(); ++i)
{
- if (i->second->hasMode(this->GetModeChar()))
+ if (i->second->HasMode(this))
changelist.push_remove(this, i->first->nick);
}
}
-struct builtin_modes
-{
- SimpleChannelModeHandler s;
- SimpleChannelModeHandler p;
- SimpleChannelModeHandler m;
- SimpleChannelModeHandler t;
-
- SimpleChannelModeHandler n;
- SimpleChannelModeHandler i;
- ModeChannelKey k;
- ModeChannelLimit l;
-
- ModeChannelBan b;
- ModeChannelOp o;
- ModeChannelVoice v;
-
- SimpleUserModeHandler ui;
- ModeUserOperator uo;
- ModeUserServerNoticeMask us;
-
- builtin_modes()
- : s(NULL, "secret", 's')
- , p(NULL, "private", 'p')
- , m(NULL, "moderated", 'm')
- , t(NULL, "topiclock", 't')
- , n(NULL, "noextmsg", 'n')
- , i(NULL, "inviteonly", 'i')
- , ui(NULL, "invisible", 'i')
- {
- }
-
- void init()
- {
- ServiceProvider* modes[] = { &s, &p, &m, &t, &n, &i, &k, &l, &b, &o, &v,
- &ui, &uo, &us };
- ServerInstance->Modules->AddServices(modes, sizeof(modes)/sizeof(ServiceProvider*));
- }
-};
-
-static builtin_modes static_modes;
-
-void ModeParser::InitBuiltinModes()
+bool ModeParser::IsModeChar(char chr)
{
- static_modes.init();
- static_modes.b.DoRehash();
+ return ((chr >= 'A' && chr <= 'Z') || (chr >= 'a' && chr <= 'z'));
}
ModeParser::ModeParser()