- if (modehandlers[handler_id]->GetModeType() == type)
- {
- 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 < pcnt)
- {
- ServerInstance->Log(DEBUG,"parameter_counter = %d, pcnt = %d", parameter_counter, pcnt);
- parameter = parameters[parameter_counter++];
-
- /* Yerk, invalid! */
- if ((parameter.find(':') == 0) || (parameter.rfind(' ') != std::string::npos))
- parameter = "";
- }
- else
- {
- /* No parameter, continue to the next mode */
- 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) == MODEACTION_DENY)
- {
- 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;
- }
-
- /* 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 ((IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!*user->oper))
- {
- user->WriteServ("481 %s :Permission Denied- Only IRC operators may %sset %s mode %c", user->nick,
- adding ? "" : "un", 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);
-
- if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter == ""))
- {
- /* 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);
-
- /* 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;
- parameter_count++;
- /* Does this mode have a prefix? */
- if (modehandlers[handler_id]->GetPrefix() && targetchannel)
- {
- userrec* 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);
-
- /* Reset the state change flag */
- state_change = false;
-
- if ((output_sequence.length() + parameter_list.str().length() > 450) || (output_sequence.length() > 100)
- || (parameter_count > 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("472 %s %c :is unknown mode char to me",user->nick, modechar);
- }
- break;
- }
+ for (std::string::const_iterator letter = mode_sequence.begin(); letter != mode_sequence.end(); letter++)
+ {
+ unsigned char mletter = *letter;
+ if (mletter == '+')
+ continue;
+
+ /* Ensure the user doesnt request the same mode twice,
+ * so they cant flood themselves off out of idiocy.
+ */
+ if (sent[mletter] == seq)
+ continue;
+
+ sent[mletter] = seq;
+
+ ModeHandler *mh = this->FindMode(mletter, MODETYPE_CHANNEL);
+
+ if (!mh || !mh->IsListMode())
+ return;
+
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnRawMode, OnRawMode(user, chan, mletter, "", true, 0));
+ if (MOD_RESULT == ACR_DENY)
+ continue;
+
+ bool display = true;
+ if (!user->HasPrivPermission("channels/auspex") && ServerInstance->Config->HideModeLists[mletter] && (chan->GetStatus(user) < STATUS_HOP))
+ {
+ user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :Only half-operators and above may view the +%c list",
+ user->nick.c_str(), chan->name.c_str(), mletter);
+ display = false;