summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAttila Molnar <attilamolnar@hush.com>2014-09-03 14:47:13 +0200
committerAttila Molnar <attilamolnar@hush.com>2014-09-03 14:47:13 +0200
commit3d958279c6c4d352132ea50836a2b7b1d3be5434 (patch)
treeb4d941a4c69f2e18dc0f8642f23bd6a77044a6a9
parentfb82075a2e69514f23bad84643f903384c6d11e8 (diff)
Split out ModeParser::ProcessSingle() from Process()
This applies up to one MODE line's worth of mode changes from a Modes::ChangeList
-rw-r--r--include/mode.h14
-rw-r--r--src/mode.cpp61
2 files changed, 55 insertions, 20 deletions
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<ModeParser>
/**
* 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 &param, 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<ModeParser>
*/
void Process(const std::vector<std::string>& 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 &parameter, 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<std::string>& 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<std::string>& 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<std::string>& 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<std::string>& 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)