summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mode.h7
-rw-r--r--src/mode.cpp87
2 files changed, 39 insertions, 55 deletions
diff --git a/include/mode.h b/include/mode.h
index 70c02a503..381145319 100644
--- a/include/mode.h
+++ b/include/mode.h
@@ -48,19 +48,20 @@ enum ModeAction {
class ModeHandler
{
char mode;
- int n_params;
+ int n_params_on;
+ int n_params_off;
bool list;
ModeType m_type;
bool oper;
public:
- ModeHandler(char modeletter, int parameters, bool listmode, ModeType type, bool operonly);
+ ModeHandler(char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly);
virtual ~ModeHandler();
bool IsListMode();
ModeType GetModeType();
bool NeedsOper();
- int GetNumParams();
+ int GetNumParams(bool adding);
char GetModeChar();
virtual ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string &parameter, bool adding); /* Can change the mode parameter as its a ref */
diff --git a/src/mode.cpp b/src/mode.cpp
index 7d6423d02..8690180e9 100644
--- a/src/mode.cpp
+++ b/src/mode.cpp
@@ -54,7 +54,7 @@ extern ServerConfig* Config;
extern time_t TIME;
-ModeHandler::ModeHandler(char modeletter, int parameters, bool listmode, ModeType type, bool operonly) : mode(modeletter), n_params(parameters), list(listmode), m_type(type), oper(operonly)
+ModeHandler::ModeHandler(char modeletter, int parameters_on, int parameters_off, bool listmode, ModeType type, bool operonly) : mode(modeletter), n_params_on(parameters_on), n_params_off(parameters_off), list(listmode), m_type(type), oper(operonly)
{
}
@@ -77,9 +77,9 @@ bool ModeHandler::NeedsOper()
return oper;
}
-int ModeHandler::GetNumParams()
+int ModeHandler::GetNumParams(bool adding)
{
- return n_params;
+ return adding ? n_params_on : n_params_off;
}
char ModeHandler::GetModeChar()
@@ -503,19 +503,32 @@ void ModeParser::Process(char **parameters, int pcnt, userrec *user)
std::string output_sequence = "";
bool adding = true, state_change = false;
int handler_id = 0;
+ int parameter_counter = 2; /* Index of first parameter */
for (std::string::const_iterator modeletter = mode_sequence.begin(); modeletter != mode_sequence.end(); modeletter++)
{
switch (*modeletter)
{
+ /* NB:
+ * For + and - mode characters, we don't just stick the character into the output sequence.
+ * This is because the user may do something dumb, like: +-+ooo or +oo-+. To prevent this
+ * appearing in the output sequence, we store a flag which says there was a state change,
+ * which is set on any + or -, however, the + or - that we finish on is only appended to
+ * the output stream in the event it is followed by a non "+ or -" character, such as o or v.
+ */
case '+':
+ /* The following expression prevents: +o+o nick nick, compressing it to +oo nick nick,
+ * however, will allow the + if it is the first item in the sequence, regardless.
+ */
+ if ((!adding) || (!output_sequence.length()))
+ state_change = true;
adding = true;
- state_change = true;
continue;
break;
case '-':
+ if ((adding) || (!output_sequence.length()))
+ state_change = true;
adding = false;
- state_change = true;
continue;
break;
default:
@@ -535,11 +548,27 @@ void ModeParser::Process(char **parameters, int pcnt, userrec *user)
}
if ((modehandlers[handler_id]->GetModeType() == type) && (!abort))
{
+ if (modehandlers[handler_id]->GetNumParams(adding))
+ {
+ if (pcnt < parameter_counter)
+ {
+ parameter = parameters[parameter_counter++];
+ }
+ else
+ {
+ parameter = "";
+ }
+ }
ModeAction ma = modehandlers[handler_id]->OnModeChange(user, targetuser, targetchannel, parameter, adding);
if (ma == MODEACTION_ALLOW)
{
output_sequence = output_sequence + *modeletter;
+ if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter != ""))
+ {
+ parameter_list >> " " >> parameter;
+ }
+
for (std::vector<ModeWatcher*>::iterator watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
{
(*watchers)->AfterMode(user, targetuser, targetchannel, parameter, adding, type);
@@ -553,55 +582,9 @@ void ModeParser::Process(char **parameters, int pcnt, userrec *user)
}
}
-
-/** ModeParser::CompressModes()
- * Tidies up redundant modes,
- * e.g. +nt-nt+i becomes +-+i
- * A section further down the chain tidies up the +-+- crap.
- */
std::string ModeParser::CompressModes(std::string modes,bool channelmodes)
{
- /*
- * OK, iterate over the mode string and count how many times a certain mode appears in it.
- * Then, erase all instances of any character that appears more than once.
- * This only operates on modes with no parameters, you can still +v-v+v-v+v-v to your heart's content.
- */
-
- /* Do we really need an int here? Can you fit enough modes in a line to overflow a short? */
- short counts[127];
- bool active[127];
- memset(counts, 0, sizeof(counts));
- memset(active, 0, sizeof(active));
-
- for(unsigned char* i = (unsigned char*)modes.c_str(); *i; i++)
- {
- if((*i == '+') || (*i == '-'))
- continue;
-
- if(!channelmodes || (channelmodes && (strchr("itnmsp", *i) || (ModeDefined(*i, MT_CHANNEL) && !ModeDefinedOn(*i,MT_CHANNEL) && !ModeDefinedOff(*i,MT_CHANNEL)))))
- {
- log(DEBUG,"Tidy mode %c", *i);
- counts[*i]++;
- active[*i] = true;
- }
- }
-
- for(unsigned char j = 65; j < 127; j++)
- {
- if ((counts[j] > 1) && (active[j] == true))
- {
- std::string::size_type pos;
-
- while((pos = modes.find(j)) != std::string::npos)
- {
- log(DEBUG, "Deleting occurence of mode %c...", j);
- modes.erase(pos, 1);
- log(DEBUG,"New mode line: %s", modes.c_str());
- }
- }
- }
-
- return modes;
+ return "";
}
void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int status, int pcnt, bool servermode, bool silent, bool local)