X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmode.cpp;h=9d17f5be8b8eda5cae8a329fd550ef2d3d6d6b08;hb=8f5952d1e56c9dbefebbacfc7e40546a9df901e8;hp=22173c189aa63ee5dcc63870f2cecbfb0d5464a9;hpb=c6a508a3da977041909f18f77d6e8fea942512cf;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/mode.cpp b/src/mode.cpp index 22173c189..9d17f5be8 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -24,12 +24,18 @@ #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) { } @@ -83,6 +89,11 @@ void ModeHandler::DisplayEmptyList(User*, Channel*) 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*) @@ -155,11 +166,20 @@ void ModeWatcher::AfterMode(User*, User*, Channel*, const std::string&, bool) 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; @@ -182,6 +202,14 @@ ModeAction PrefixMode::OnModeChange(User* source, User*, Channel* chan, std::str 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) @@ -237,7 +265,7 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode 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 @@ -286,8 +314,8 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Mode 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)); @@ -426,6 +454,12 @@ unsigned int ModeParser::ProcessSingle(User* user, Channel* targetchannel, User* 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)) @@ -570,11 +604,7 @@ ModeHandler::Id ModeParser::AllocateModeId(ModeType mt) 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. @@ -624,7 +654,7 @@ void ModeParser::AddMode(ModeHandler* mh) bool ModeParser::DelMode(ModeHandler* mh) { - if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z')) + if (!ModeParser::IsModeChar(mh->GetModeChar())) return false; ModeHandlerMap& mhmap = modehandlersbyname[mh->GetModeType()]; @@ -694,7 +724,7 @@ ModeHandler* ModeParser::FindMode(const std::string& modename, ModeType mt) 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]; @@ -724,7 +754,9 @@ std::string ModeParser::CreateModeList(ModeType mt, bool needparam) 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) @@ -872,51 +904,9 @@ void PrefixMode::RemoveMode(Channel* chan, Modes::ChangeList& changelist) } } -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()