X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmode.cpp;h=3842b01e6ea02301b5d3b86e2221d89948dd1409;hb=84a19a9ab6129deb71cdc24b216b74dd8eb80978;hp=d61725eef27489415ff277a45dedac4507a9aa29;hpb=772d6f16c0c474d2b66121c618c0273c26ca574e;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/mode.cpp b/src/mode.cpp index d61725eef..3842b01e6 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -54,21 +54,7 @@ extern ServerConfig* Config; extern time_t TIME; -ModeOutput::ModeOutput(std::string parameter, ModeAction action) : par(parameter), act(action) -{ -} - -ModeAction ModeOutput::GetAction() -{ - return act; -} - -std::string& ModeOutput::GetParameter() -{ - return par; -} - -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) { } @@ -91,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() @@ -101,9 +87,9 @@ char ModeHandler::GetModeChar() return mode; } -ModeOutput ModeHandler::OnModeChange(userrec* source, userrec* dest, chanrec* channel, const std::string ¶meter, bool adding) +ModeAction ModeHandler::OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string ¶meter, bool adding) { - return ModeOutput("", MODEACTION_DENY); + return MODEACTION_DENY; } void ModeHandler::DisplayList(userrec* user, chanrec* channel) @@ -133,12 +119,12 @@ ModeType ModeWatcher::GetModeType() return m_type; } -bool ModeWatcher::BeforeMode(userrec* source, userrec* dest, chanrec* channel, const std::string ¶meter, bool adding) +bool ModeWatcher::BeforeMode(userrec* source, userrec* dest, chanrec* channel, std::string ¶meter, bool adding, ModeType type) { return true; } -void ModeWatcher::AfterMode(userrec* source, userrec* dest, chanrec* channel, const std::string ¶meter, bool adding) +void ModeWatcher::AfterMode(userrec* source, userrec* dest, chanrec* channel, const std::string ¶meter, bool adding, ModeType type) { } @@ -489,55 +475,143 @@ char* ModeParser::TakeBan(userrec *user,char *dest,chanrec *chan,int status) return NULL; } - -/** 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) +void ModeParser::Process(char **parameters, int pcnt, userrec *user, bool servermode) { - /* - * 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; + std::string target = parameters[0]; + ModeType type = MODETYPE_USER; + chanrec* targetchannel = FindChan(parameters[0]); + userrec* targetuser = Find(parameters[0]); - if(!channelmodes || (channelmodes && (strchr("itnmsp", *i) || (ModeDefined(*i, MT_CHANNEL) && !ModeDefinedOn(*i,MT_CHANNEL) && !ModeDefinedOff(*i,MT_CHANNEL))))) + if (pcnt > 1) + { + if (targetchannel) { - log(DEBUG,"Tidy mode %c", *i); - counts[*i]++; - active[*i] = true; + type = MODETYPE_CHANNEL; } - } - - for(unsigned char j = 65; j < 127; j++) - { - if ((counts[j] > 1) && (active[j] == true)) + else if (targetuser) { - std::string::size_type pos; + type = MODETYPE_USER; + } + else + { + /* No such nick/channel */ + return; + } + std::string mode_sequence = parameters[1]; + std::string parameter = ""; + std::ostringstream parameter_list; + 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; + continue; + break; + case '-': + if ((adding) || (!output_sequence.length())) + state_change = true; + adding = false; + continue; + break; + default: - while((pos = modes.find(j)) != std::string::npos) + /* 65 is the ascii value of 'A' */ + handler_id = *modeletter - 65; + + if (modehandlers[handler_id]) + { + bool abort = false; + for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++) + { + if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type) == MODEACTION_DENY) + abort = true; + } + 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) + { + /* We're about to output a valid mode letter - was there previously a pending state-change? */ + if (state_change) + output_sequence.append(adding ? "+" : "-"); + + /* Add the mode letter */ + output_sequence = output_sequence + *modeletter; + + /* Is there a valid parameter for this mode? If so add it to the parameter list */ + if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter != "")) + { + parameter_list << " " << parameter; + } + + /* Call all the AfterMode events in the mode watchers for this mode */ + for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++) + { + (*watchers)->AfterMode(user, targetuser, targetchannel, parameter, adding, type); + } + + /* Reset the state change flag */ + state_change = false; + } + } + } + break; + } + } + /* Was there at least one valid mode in the sequence? */ + if (output_sequence != "") + { + if (servermode) { - log(DEBUG, "Deleting occurence of mode %c...", j); - modes.erase(pos, 1); - log(DEBUG,"New mode line: %s", modes.c_str()); + if (type == MODETYPE_CHANNEL) + { + WriteChannelWithServ(Config->ServerName,targetchannel,"MODE %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str()); + } + } + else + { + if (type == MODETYPE_CHANNEL) + { + WriteChannel(targetchannel,user,"MODE %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str()); + FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, output_sequence + parameter_list.str())); + } } } } - - return modes; +} + +std::string ModeParser::CompressModes(std::string modes,bool channelmodes) +{ + return ""; } void ModeParser::ProcessModes(char **parameters,userrec* user,chanrec *chan,int status, int pcnt, bool servermode, bool silent, bool local)