X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmode.cpp;h=e562a8551a39013f0becb0169b1a92bc68e53222;hb=1ff26bac16487869af7a5e4ebfa1219096c9327b;hp=db9641edbb77662b42c2479729d7926577152c9c;hpb=743c10e4ca5acd45e670b335a07b5bf3ab754ab6;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/mode.cpp b/src/mode.cpp index db9641edb..e562a8551 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -577,14 +577,23 @@ void ModeParser::Process(const char* const* parameters, int pcnt, User *user, bo /* 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->HasModePermission(modehandlers[handler_id]->GetModeChar(), type))) + if (adding && (IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!user->HasModePermission(modehandlers[handler_id]->GetModeChar(), type))) { - user->WriteNumeric(481, "%s :Permission Denied - Oper type %s does not have access to %sset %s mode %c", - user->nick, - user->oper, - adding ? "" : "un", - type == MODETYPE_CHANNEL ? "channel" : "user", - modehandlers[handler_id]->GetModeChar()); + if (IS_OPER(user)) + { + user->WriteNumeric(481, "%s :Permission Denied - Oper type %s does not have access to set %s mode %c", + user->nick, + user->oper, + type == MODETYPE_CHANNEL ? "channel" : "user", + modehandlers[handler_id]->GetModeChar()); + } + else + { + user->WriteNumeric(481, "%s :Permission Denied - Only operators may set %s mode %c", + user->nick, + type == MODETYPE_CHANNEL ? "channel" : "user", + modehandlers[handler_id]->GetModeChar()); + } continue; } @@ -705,12 +714,12 @@ void ModeParser::CleanMask(std::string &mask) std::string::size_type pos_of_pling = mask.find_first_of('!'); std::string::size_type pos_of_at = mask.find_first_of('@'); std::string::size_type pos_of_dot = mask.find_first_of('.'); - std::string::size_type pos_of_colon = mask.find_first_of(':'); /* Because ipv6 addresses are colon delimited */ + std::string::size_type pos_of_colons = mask.find("::"); /* Because ipv6 addresses are colon delimited -- double so it treats extban as nick */ if ((pos_of_pling == std::string::npos) && (pos_of_at == std::string::npos)) { - /* Just a nick, or just a host */ - if ((pos_of_dot == std::string::npos) && (pos_of_colon == std::string::npos)) + /* Just a nick, or just a host - or clearly ipv6 (starting with :) */ + if ((pos_of_dot == std::string::npos) && (pos_of_colons == std::string::npos) && mask[0] != ':') { /* It has no '.' in it, it must be a nick. */ mask.append("!*@*"); @@ -776,6 +785,9 @@ bool ModeParser::DelMode(ModeHandler* mh) if (!modehandlers[pos]) return false; + /* Note: We can't stack here, as we have modes potentially being removed across many different channels. + * To stack here we have to make the algorithm slower. Discuss. + */ switch (mh->GetModeType()) { case MODETYPE_USER: @@ -879,7 +891,7 @@ ModeHandler* ModeParser::FindPrefix(unsigned const char pfxletter) return NULL; } -std::string ModeParser::ModeString(User* user, Channel* channel) +std::string ModeParser::ModeString(User* user, Channel* channel, bool nick_suffix) { std::string types; std::string pars; @@ -897,14 +909,20 @@ std::string ModeParser::ModeString(User* user, Channel* channel) ret = mh->ModeSet(NULL, user, channel, user->nick); if ((ret.first) && (ret.second == user->nick)) { - pars.append(" "); - pars.append(user->nick); + if (nick_suffix) + { + pars.append(" "); + pars.append(user->nick); + } types.push_back(mh->GetModeChar()); } } } - return types+pars; + if (nick_suffix) + return types+pars; + else + return types; } std::string ModeParser::ChanModes() @@ -1042,30 +1060,44 @@ bool ModeParser::DelModeWatcher(ModeWatcher* mw) /** This default implementation can remove simple user modes */ -void ModeHandler::RemoveMode(User* user) +void ModeHandler::RemoveMode(User* user, irc::modestacker* stack) { char moderemove[MAXBUF]; const char* parameters[] = { user->nick, moderemove }; if (user->IsModeSet(this->GetModeChar())) { - sprintf(moderemove,"-%c",this->GetModeChar()); - ServerInstance->Parser->CallHandler("MODE", parameters, 2, user); + if (stack) + { + stack->Push(this->GetModeChar()); + } + else + { + sprintf(moderemove,"-%c",this->GetModeChar()); + ServerInstance->Parser->CallHandler("MODE", parameters, 2, user); + } } } /** This default implementation can remove simple channel modes * (no parameters) */ -void ModeHandler::RemoveMode(Channel* channel) +void ModeHandler::RemoveMode(Channel* channel, irc::modestacker* stack) { char moderemove[MAXBUF]; const char* parameters[] = { channel->name, moderemove }; if (channel->IsModeSet(this->GetModeChar())) { - sprintf(moderemove,"-%c",this->GetModeChar()); - ServerInstance->SendMode(parameters, 2, ServerInstance->FakeClient); + if (stack) + { + stack->Push(this->GetModeChar()); + } + else + { + sprintf(moderemove,"-%c",this->GetModeChar()); + ServerInstance->SendMode(parameters, 2, ServerInstance->FakeClient); + } } }