+ if (display)
+ mh->DisplayList(user, targetchannel);
+ }
+ else
+ nonlistmodes_found++;
+
+ mode++;
+ }
+
+ /* We didnt have any modes that were non-list, we can return here */
+ if (!nonlistmodes_found)
+ return;
+ }
+
+ if (pcnt == 1)
+ {
+ this->DisplayCurrentModes(user, targetuser, targetchannel, parameters[0]);
+ }
+ else if (pcnt > 1)
+ {
+ bool SkipAccessChecks = false;
+
+ if (targetchannel)
+ {
+ type = MODETYPE_CHANNEL;
+ mask = MASK_CHANNEL;
+
+ /* Extra security checks on channel modes
+ * (e.g. are they a (half)op?
+ */
+
+ if ((IS_LOCAL(user)) && (!ServerInstance->ULine(user->server)) && (!servermode))
+ {
+ /* We don't have halfop */
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user, NULL, targetchannel, AC_GENERAL_MODE));
+ if (MOD_RESULT == ACR_DENY)
+ return;
+ SkipAccessChecks = (MOD_RESULT == ACR_ALLOW);
+ }
+ }
+ else if (targetuser)
+ {
+ type = MODETYPE_USER;
+ mask = MASK_USER;
+ if ((user != targetuser) && (!ServerInstance->ULine(user->server)))
+ {
+ user->WriteNumeric(502, "%s :Can't change mode for other users", user->nick);
+ return;
+ }
+ }
+ else
+ {
+ /* No such nick/channel */
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick, parameters[0]);
+ return;
+ }
+
+ std::string mode_sequence = parameters[1];
+ std::string parameter;
+ std::ostringstream parameter_list;
+ std::string output_sequence;
+ bool adding = true, state_change = false;
+ unsigned char handler_id = 0;
+ int parameter_counter = 2; /* Index of first parameter */
+ int parameter_count = 0;
+ bool last_successful_state_change = false;
+
+ /* A mode sequence that doesnt start with + or -. Assume +. - Thanks for the suggestion spike (bug#132) */
+ if ((*mode_sequence.begin() != '+') && (*mode_sequence.begin() != '-'))
+ mode_sequence.insert(0, "+");
+
+ for (std::string::const_iterator letter = mode_sequence.begin(); letter != mode_sequence.end(); letter++)
+ {
+ unsigned char modechar = *letter;
+
+ switch (modechar)
+ {
+ /* 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;
+ if (!output_sequence.length())
+ last_successful_state_change = false;
+ continue;