void ModuleSpanningTree::OnMode(User* source, User* u, Channel* c, const Modes::ChangeList& modes, ModeParser::ModeProcessFlag processflags) { if (processflags & ModeParser::MODE_LOCALONLY) return; if (u) { if (u->registered != REG_ALL) return; CmdBuilder params(source, "MODE"); params.push(u->uuid); params.push(ClientProtocol::Messages::Mode::ToModeLetters(modes)); params.push_raw(Translate::ModeChangeListToParams(modes.getlist())); params.Broadcast(); } else { CmdBuilder params(source, "FMODE"); params.push(c->name); params.push_int(c->age); params.push(ClientProtocol::Messages::Mode::ToModeLetters(modes)); params.push_raw(Translate::ModeChangeListToParams(modes.getlist())); params.Broadcast(); } }
unsigned int ModeParser::ProcessSingle(User* user, Channel* targetchannel, User* targetuser, Modes::ChangeList& changelist, ModeProcessFlag flags, unsigned int beginindex) { LastParse.clear(); LastChangeList.clear(); unsigned int modes_processed = 0; 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()+beginindex; i != list.end(); ++i) { modes_processed++; Modes::Change& item = *i; ModeHandler* mh = item.mh; // 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->GetNumParams(item.adding)) { // Skip the mode if the parameter does not pass basic validation if (!IsModeParamValid(user, targetchannel, targetuser, item)) continue; // If this is a merge and we won we don't apply this mode if ((flags & MODE_MERGE) && (!ShouldApplyMergedMode(targetchannel, item))) continue; } ModeAction ma = TryMode(user, targetuser, targetchannel, item, (!(flags & MODE_CHECKACCESS))); if (ma != MODEACTION_ALLOW) continue; char needed_pm = item.adding ? '+' : '-'; if (needed_pm != output_pm) { output_pm = needed_pm; output_mode.append(1, output_pm); } output_mode.push_back(mh->GetModeChar()); if (!item.param.empty()) { output_parameters.push_back(' '); output_parameters.append(item.param); } LastChangeList.push(mh, item.adding, item.param); if ((output_mode.length() + output_parameters.length() > 450) || (output_mode.length() > 100) || (LastChangeList.size() >= ServerInstance->Config->Limits.MaxModes)) { /* mode sequence is getting too long */ break; } } if (!output_mode.empty()) { LastParse = targetchannel ? targetchannel->name : targetuser->nick; LastParse.append(" "); LastParse.append(output_mode); LastParse.append(output_parameters); if (targetchannel) targetchannel->WriteChannel(user, "MODE " + LastParse); else targetuser->WriteFrom(user, "MODE " + LastParse); FOREACH_MOD(OnMode, (user, targetuser, targetchannel, LastChangeList, flags, output_mode)); } return modes_processed; }