- if (modehandlers[handler_id]->GetModeType() == type)
- {
- int MOD_RESULT = 0;
-
- if (modehandlers[handler_id]->GetNumParams(adding))
- {
- /* This mode expects a parameter, do we have any parameters left in our list to use? */
- if (parameter_counter < parameters.size())
- {
- parameter = parameters[parameter_counter++];
-
- /* Yerk, invalid! */
- if ((parameter.find(':') == 0) || (parameter.rfind(' ') != std::string::npos))
- parameter.clear();
- }
- else
- {
- /* No parameter, continue to the next mode */
- modehandlers[handler_id]->OnParameterMissing(user, targetuser, targetchannel);
- continue;
- }
-
- FOREACH_RESULT(I_OnRawMode, OnRawMode(user, targetchannel, modechar, parameter, adding, 1, servermode));
- }
- else
- {
- FOREACH_RESULT(I_OnRawMode, OnRawMode(user, targetchannel, modechar, "", adding, 0, servermode));
- }
-
- if (IS_LOCAL(user) && (MOD_RESULT == ACR_DENY))
- continue;
-
- if (!SkipAccessChecks && IS_LOCAL(user) && (MOD_RESULT != ACR_ALLOW))
- {
- /* Check access to this mode character */
- if ((type == MODETYPE_CHANNEL) && (modehandlers[handler_id]->GetNeededPrefix()))
- {
- char needed = modehandlers[handler_id]->GetNeededPrefix();
- ModeHandler* prefixmode = FindPrefix(needed);
-
- /* If the mode defined by the handler is not '\0', but the handler for it
- * cannot be found, they probably dont have the right module loaded to implement
- * the prefix they want to compare the mode against, e.g. '&' for m_chanprotect.
- * Revert to checking against the minimum core prefix, '%'.
- */
- if (needed && !prefixmode)
- prefixmode = FindPrefix('%');
-
- unsigned int neededrank = prefixmode->GetPrefixRank();
- /* Compare our rank on the channel against the rank of the required prefix,
- * allow if >= ours. Because mIRC and xchat throw a tizz if the modes shown
- * in NAMES(X) are not in rank order, we know the most powerful mode is listed
- * first, so we don't need to iterate, we just look up the first instead.
- */
- std::string modestring = targetchannel->GetAllPrefixChars(user);
- char ml = (modestring.empty() ? '\0' : modestring[0]);
- ModeHandler* ourmode = FindPrefix(ml);
- if (!ourmode || ourmode->GetPrefixRank() < neededrank)
- {
- /* Bog off */
- user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must have channel privilege %c or above to %sset channel mode %c",
- user->nick.c_str(), targetchannel->name.c_str(), needed, adding ? "" : "un", modechar);
- continue;
- }
- }
- }
-
- bool had_parameter = !parameter.empty();
-
- for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
- {
- if ((*watchers)->BeforeMode(user, targetuser, targetchannel, parameter, adding, type, servermode) == false)
- {
- abort = true;
- break;
- }
- /* A module whacked the parameter completely, and there was one. abort. */
- if ((had_parameter) && (parameter.empty()))
- {
- abort = true;
- break;
- }
- }
-
- if (abort)
- continue;
-
- /* If it's disabled, they have to be an oper.
- */
- if (IS_LOCAL(user) && !IS_OPER(user) && ((type == MODETYPE_CHANNEL ? ServerInstance->Config->DisabledCModes : ServerInstance->Config->DisabledUModes)[modehandlers[handler_id]->GetModeChar() - 'A']))
- {
- user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - %s mode %c has been locked by the administrator",
- user->nick.c_str(),
- type == MODETYPE_CHANNEL ? "channel" : "user",
- modehandlers[handler_id]->GetModeChar());
- continue;
- }
-
- /* It's an oper only mode, check if theyre an oper. If they arent,
- * eat any parameter that came with the mode, and continue to next
- */
- if (adding && (IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!user->HasModePermission(modehandlers[handler_id]->GetModeChar(), type)))
- {
- if (IS_OPER(user))
- {
- user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Oper type %s does not have access to set %s mode %c",
- user->nick.c_str(),
- user->oper.c_str(),
- type == MODETYPE_CHANNEL ? "channel" : "user",
- modehandlers[handler_id]->GetModeChar());
- }
- else
- {
- user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Only operators may set %s mode %c",
- user->nick.c_str(),
- type == MODETYPE_CHANNEL ? "channel" : "user",
- modehandlers[handler_id]->GetModeChar());
- }
- continue;
- }
-
- /* Call the handler for the mode */
- ModeAction ma = modehandlers[handler_id]->OnModeChange(user, targetuser, targetchannel, parameter, adding, servermode);
-
- if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter.empty()))
- {
- /* The handler nuked the parameter and they are supposed to have one.
- * We CANT continue now, even if they actually returned MODEACTION_ALLOW,
- * so we bail to the next mode character.
- */
- continue;
- }
-
- if (ma == MODEACTION_ALLOW)
- {
- /* We're about to output a valid mode letter - was there previously a pending state-change? */
- if (state_change)
- {
- if (adding != last_successful_state_change)
- output_sequence.append(adding ? "+" : "-");
- last_successful_state_change = adding;
- }
-
- /* Add the mode letter */
- output_sequence.push_back(modechar);
-
- modehandlers[handler_id]->ChangeCount(adding ? 1 : -1);
-
- /* Is there a valid parameter for this mode? If so add it to the parameter list */
- if ((modehandlers[handler_id]->GetNumParams(adding)) && (!parameter.empty()))
- {
- parameter_list << " " << parameter;
- parameter_xlate.push_back(modehandlers[handler_id]->GetTranslateType());
- parameter_count++;
- /* Does this mode have a prefix? */
- if (modehandlers[handler_id]->GetPrefix() && targetchannel)
- {
- User* user_to_prefix = ServerInstance->FindNick(parameter);
- if (user_to_prefix)
- targetchannel->SetPrefix(user_to_prefix, modehandlers[handler_id]->GetPrefix(),
- modehandlers[handler_id]->GetPrefixRank(), adding);
- }
- }
-
- /* 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, servermode);
-
- /* Reset the state change flag */
- state_change = false;
-
- if ((output_sequence.length() + parameter_list.str().length() > 450) || (output_sequence.length() > 100)
- || (parameter_count > ServerInstance->Config->Limits.MaxModes))
- {
- /* We cant have a mode sequence this long */
- letter = mode_sequence.end() - 1;
- continue;
- }
- }
- }
- }
- else
- {
- /* No mode handler? Unknown mode character then. */
- user->WriteServ("%d %s %c :is unknown mode char to me", type == MODETYPE_CHANNEL ? 472 : 501, user->nick.c_str(), modechar);
- }
- break;
- }