From: Attila Molnar Date: Wed, 3 Sep 2014 12:47:13 +0000 (+0200) Subject: Split out ModeParser::ProcessSingle() from Process() X-Git-Url: https://git.netwichtig.de/gitweb/?a=commitdiff_plain;h=3d958279c6c4d352132ea50836a2b7b1d3be5434;p=user%2Fhenk%2Fcode%2Finspircd.git Split out ModeParser::ProcessSingle() from Process() This applies up to one MODE line's worth of mode changes from a Modes::ChangeList --- diff --git a/include/mode.h b/include/mode.h index 3d8f0c940..2833d75a2 100644 --- a/include/mode.h +++ b/include/mode.h @@ -542,7 +542,7 @@ class CoreExport ModeParser : public fakederef /** * Attempts to apply a mode change to a user or channel */ - ModeAction TryMode(User* user, User* targu, Channel* targc, bool adding, unsigned char mode, std::string ¶m, bool SkipACL); + ModeAction TryMode(User* user, User* targu, Channel* targc, Modes::Change& mcitem, bool SkipACL); /** Returns a list of user or channel mode characters. * Used for constructing the parts of the mode list in the 004 numeric. @@ -680,6 +680,18 @@ class CoreExport ModeParser : public fakederef */ void Process(const std::vector& parameters, User* user, ModeProcessFlag flags = MODE_NONE); + /** Process a single MODE line's worth of mode changes, taking max modes and line length limits + * into consideration. + * @param user The source of the mode change, can be a server user. + * @param targetchannel Channel to apply the mode change on. NULL if changing modes on a channel. + * @param targetuser User to apply the mode change on. NULL if changing modes on a user. + * @param changelist Modes to change in form of a Modes::ChangeList. May not process + * the entire list due to MODE line length and max modes limitations. + * @param flags Optional flags controlling how the mode change is processed, + * defaults to MODE_NONE. + */ + void ProcessSingle(User* user, Channel* targetchannel, User* targetuser, Modes::ChangeList& changelist, ModeProcessFlag flags = MODE_NONE); + /** Find the mode handler for a given mode name and type. * @param modename The mode name to search for. * @param mt Type of mode to search for, user or channel. diff --git a/src/mode.cpp b/src/mode.cpp index 4fac34f78..3facc7522 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -237,14 +237,15 @@ ModeAction ParamModeBase::OnModeChange(User* source, User*, Channel* chan, std:: return MODEACTION_ALLOW; } -ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, bool adding, const unsigned char modechar, - std::string ¶meter, bool SkipACL) +ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, Modes::Change& mcitem, bool SkipACL) { ModeType type = chan ? MODETYPE_CHANNEL : MODETYPE_USER; - ModeHandler *mh = FindMode(modechar, type); + ModeHandler* mh = mcitem.mh; + bool adding = mcitem.adding; int pcnt = mh->GetNumParams(adding); + std::string& parameter = mcitem.param; // crop mode parameter size to 250 characters if (parameter.length() > 250 && adding) parameter = parameter.substr(0, 250); @@ -255,6 +256,8 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, bool if (IS_LOCAL(user) && (MOD_RESULT == MOD_RES_DENY)) return MODEACTION_DENY; + const char modechar = mh->GetModeChar(); + if (chan && !SkipACL && (MOD_RESULT != MOD_RES_ALLOW)) { MOD_RESULT = mh->AccessCheck(user, chan, parameter, adding); @@ -385,6 +388,9 @@ void ModeParser::Process(const std::vector& parameters, User* user, return; } + // Populate a temporary Modes::ChangeList with the parameters + Modes::ChangeList changelist; + ModResult MOD_RESULT; FIRST_MOD_RESULT(OnPreMode, MOD_RESULT, (user, targetuser, targetchannel, parameters)); @@ -409,11 +415,7 @@ void ModeParser::Process(const std::vector& parameters, User* user, const std::string& mode_sequence = parameters[1]; - std::string output_mode; - std::string output_parameters; - bool adding = true; - char output_pm = '\0'; // current output state, '+' or '-' unsigned int param_at = 2; for (std::string::const_iterator letter = mode_sequence.begin(); letter != mode_sequence.end(); letter++) @@ -456,25 +458,53 @@ void ModeParser::Process(const std::vector& parameters, User* user, } } + changelist.push(mh, adding, parameter); + } + + ProcessSingle(user, targetchannel, targetuser, changelist, flags); + + if ((LastParse.empty()) && (targetchannel) && (parameters.size() == 2)) + { + /* Special case for displaying the list for listmodes, + * e.g. MODE #chan b, or MODE #chan +b without a parameter + */ + this->DisplayListModes(user, targetchannel, mode_sequence); + } +} + +void ModeParser::ProcessSingle(User* user, Channel* targetchannel, User* targetuser, Modes::ChangeList& changelist, ModeProcessFlag flags) +{ + LastParse.clear(); + LastChangeList.clear(); + + std::string output_mode; + std::string output_parameters; + + char output_pm = '\0'; // current output state, '+' or '-' + Modes::ChangeList::List& list = changelist.getlist(); + for (Modes::ChangeList::List::iterator i = list.begin(); i != list.end(); ++i) + { + Modes::Change& item = *i; + ModeHandler* mh = item.mh; ModeAction ma = TryMode(user, targetuser, targetchannel, adding, modechar, parameter, (!(flags & MODE_CHECKACCESS))); if (ma != MODEACTION_ALLOW) continue; - char needed_pm = adding ? '+' : '-'; + char needed_pm = item.adding ? '+' : '-'; if (needed_pm != output_pm) { output_pm = needed_pm; output_mode.append(1, output_pm); } - output_mode.append(1, modechar); + output_mode.push_back(mh->GetModeChar()); - if (pcnt) + if (!item.param.empty()) { output_parameters.push_back(' '); - output_parameters.append(parameter); + output_parameters.append(item.param); } - LastChangeList.push(mh, adding, parameter); + LastChangeList.push(mh, item.adding, item.param); if ((output_mode.length() + output_parameters.length() > 450) || (output_mode.length() > 100) @@ -499,13 +529,6 @@ void ModeParser::Process(const std::vector& parameters, User* user, FOREACH_MOD(OnMode, (user, targetuser, targetchannel, LastChangeList, flags, output_mode)); } - else if (targetchannel && parameters.size() == 2) - { - /* Special case for displaying the list for listmodes, - * e.g. MODE #chan b, or MODE #chan +b without a parameter - */ - this->DisplayListModes(user, targetchannel, mode_sequence); - } } void ModeParser::DisplayListModes(User* user, Channel* chan, const std::string& mode_sequence)