void ModeParser::DisplayListModes(User* user, Channel* chan, std::string &mode_sequence) { seq++; 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; ModResult MOD_RESULT; FIRST_MOD_RESULT(OnRawMode, MOD_RESULT, (user, chan, mletter, "", true, 0)); if (MOD_RESULT == MOD_RES_DENY) continue; bool display = true; if (!user->HasPrivPermission("channels/auspex") && ServerInstance->Config->HideModeLists[mletter] && (chan->GetPrefixValue(user) < HALFOP_VALUE)) { user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You do not have access to view the +%c list", user->nick.c_str(), chan->name.c_str(), mletter); display = false; } // Ask mode watchers whether it's OK to show the list std::pair<ModeWatchIter, ModeWatchIter> itpair = modewatchermap.equal_range(mh->name); for (ModeWatchIter i = itpair.first; i != itpair.second; ++i) { ModeWatcher* mw = i->second; if (mw->GetModeType() == MODETYPE_CHANNEL) { std::string dummyparam; if (!mw->BeforeMode(user, NULL, chan, dummyparam, true)) { // A mode watcher doesn't want us to show the list display = false; break; } } } if (display) mh->DisplayList(user, chan); else mh->DisplayEmptyList(user, chan); } }
void ModeParser::ShowListModeList(User* user, Channel* chan, ModeHandler* mh) { { ModResult MOD_RESULT; FIRST_MOD_RESULT(OnRawMode, MOD_RESULT, (user, chan, mh, "", true)); if (MOD_RESULT == MOD_RES_DENY) return; bool display = true; // Ask mode watchers whether it's OK to show the list std::pair<ModeWatcherMap::iterator, ModeWatcherMap::iterator> itpair = modewatchermap.equal_range(mh->name); for (ModeWatcherMap::iterator i = itpair.first; i != itpair.second; ++i) { ModeWatcher* mw = i->second; if (mw->GetModeType() == MODETYPE_CHANNEL) { std::string dummyparam; if (!mw->BeforeMode(user, NULL, chan, dummyparam, true)) { // A mode watcher doesn't want us to show the list display = false; break; } } } if (display) mh->DisplayList(user, chan); else mh->DisplayEmptyList(user, chan); } }
ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, bool adding, const unsigned char modechar, std::string ¶meter, bool SkipACL) { ModeType type = chan ? MODETYPE_CHANNEL : MODETYPE_USER; ModeHandler *mh = FindMode(modechar, type); int pcnt = mh->GetNumParams(adding); // crop mode parameter size to 250 characters if (parameter.length() > 250 && adding) parameter = parameter.substr(0, 250); ModResult MOD_RESULT; FIRST_MOD_RESULT(OnRawMode, MOD_RESULT, (user, chan, modechar, parameter, adding, pcnt)); if (IS_LOCAL(user) && (MOD_RESULT == MOD_RES_DENY)) return MODEACTION_DENY; if (chan && !SkipACL && (MOD_RESULT != MOD_RES_ALLOW)) { MOD_RESULT = mh->AccessCheck(user, chan, parameter, adding); if (MOD_RESULT == MOD_RES_DENY) return MODEACTION_DENY; if (MOD_RESULT == MOD_RES_PASSTHRU) { unsigned int neededrank = mh->GetLevelRequired(); /* 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. */ unsigned int ourrank = chan->GetPrefixValue(user); if (ourrank < neededrank) { PrefixMode* neededmh = NULL; for(char c='A'; c <= 'z'; c++) { PrefixMode* privmh = FindPrefixMode(c); if (privmh && privmh->GetPrefixRank() >= neededrank) { // this mode is sufficient to allow this action if (!neededmh || privmh->GetPrefixRank() < neededmh->GetPrefixRank()) neededmh = privmh; } } if (neededmh) user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must have channel %s access or above to %sset channel mode %c", user->nick.c_str(), chan->name.c_str(), neededmh->name.c_str(), adding ? "" : "un", modechar); else user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You cannot %sset channel mode %c", user->nick.c_str(), chan->name.c_str(), adding ? "" : "un", modechar); return MODEACTION_DENY; } } } // Ask mode watchers whether this mode change is OK std::pair<ModeWatchIter, ModeWatchIter> itpair = modewatchermap.equal_range(mh->name); for (ModeWatchIter i = itpair.first; i != itpair.second; ++i) { ModeWatcher* mw = i->second; if (mw->GetModeType() == type) { if (!mw->BeforeMode(user, targetuser, chan, parameter, adding)) return MODEACTION_DENY; // A module whacked the parameter completely, and there was one. Abort. if (pcnt && parameter.empty()) return MODEACTION_DENY; } } if (IS_LOCAL(user) && !user->IsOper()) { char* disabled = (type == MODETYPE_CHANNEL) ? ServerInstance->Config->DisabledCModes : ServerInstance->Config->DisabledUModes; if (disabled[modechar - '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", modechar); return MODEACTION_DENY; } } if (adding && IS_LOCAL(user) && mh->NeedsOper() && !user->HasModePermission(modechar, type)) { /* It's an oper only mode, and they don't have access to it. */ if (user->IsOper()) { 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->name.c_str(), type == MODETYPE_CHANNEL ? "channel" : "user", modechar); } else { user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Only operators may set %s mode %c", user->nick.c_str(), type == MODETYPE_CHANNEL ? "channel" : "user", modechar); } return MODEACTION_DENY; } /* Call the handler for the mode */ ModeAction ma = mh->OnModeChange(user, targetuser, chan, parameter, adding); if (pcnt && parameter.empty()) return MODEACTION_DENY; if (ma != MODEACTION_ALLOW) return ma; if ((!mh->IsListMode()) && (mh->GetNumParams(true)) && (chan)) chan->SetModeParam(mh, (adding ? parameter : "")); itpair = modewatchermap.equal_range(mh->name); for (ModeWatchIter i = itpair.first; i != itpair.second; ++i) { ModeWatcher* mw = i->second; if (mw->GetModeType() == type) mw->AfterMode(user, targetuser, chan, parameter, adding); } return MODEACTION_ALLOW; }