X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fcoremods%2Fcore_channel%2Fcore_channel.cpp;h=3af809645e8fbb4fa8110d4b4aa218ae18a0c27b;hb=dcd3438011d59aa4de4df64abf06bca1cbf36859;hp=99ad74d3da009a90f87904f38d6c78b129c40fcb;hpb=cd268bb2d5d1740233d150e2f3877f7f136d3512;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/coremods/core_channel/core_channel.cpp b/src/coremods/core_channel/core_channel.cpp index 99ad74d3d..3af809645 100644 --- a/src/coremods/core_channel/core_channel.cpp +++ b/src/coremods/core_channel/core_channel.cpp @@ -1,7 +1,7 @@ /* * InspIRCd -- Internet Relay Chat Daemon * - * Copyright (C) 2014 Attila Molnar + * Copyright (C) 2014-2015 Attila Molnar * * This file is part of InspIRCd. InspIRCd is free software: you can * redistribute it and/or modify it under the terms of the GNU General Public @@ -19,27 +19,102 @@ #include "inspircd.h" #include "core_channel.h" +#include "invite.h" +#include "listmode.h" -class CoreModChannel : public Module +class CoreModChannel : public Module, public CheckExemption::EventListener { + Invite::APIImpl invapi; CommandInvite cmdinvite; CommandJoin cmdjoin; CommandKick cmdkick; CommandNames cmdnames; CommandTopic cmdtopic; + insp::flat_map exemptions; + + ModResult IsInvited(User* user, Channel* chan) + { + LocalUser* localuser = IS_LOCAL(user); + if ((localuser) && (invapi.IsInvited(localuser, chan))) + return MOD_RES_ALLOW; + return MOD_RES_PASSTHRU; + } public: CoreModChannel() - : cmdinvite(this), cmdjoin(this), cmdkick(this), cmdnames(this), cmdtopic(this) + : CheckExemption::EventListener(this) + , invapi(this) + , cmdinvite(this, invapi) + , cmdjoin(this) + , cmdkick(this) + , cmdnames(this) + , cmdtopic(this) { } + void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE + { + ConfigTag* optionstag = ServerInstance->Config->ConfValue("options"); + Implementation events[] = { I_OnCheckKey, I_OnCheckLimit, I_OnCheckChannelBan }; + if (optionstag->getBool("invitebypassmodes", true)) + ServerInstance->Modules.Attach(events, this, sizeof(events)/sizeof(Implementation)); + else + { + for (unsigned int i = 0; i < sizeof(events)/sizeof(Implementation); i++) + ServerInstance->Modules.Detach(events[i], this); + } + + std::string current; + irc::spacesepstream defaultstream(optionstag->getString("exemptchanops")); + insp::flat_map exempts; + while (defaultstream.GetToken(current)) + { + std::string::size_type pos = current.find(':'); + if (pos == std::string::npos || (pos + 2) > current.size()) + throw ModuleException("Invalid exemptchanops value '" + current + "' at " + optionstag->getTagLocation()); + + const std::string restriction = current.substr(0, pos); + const char prefix = current[pos + 1]; + + ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Exempting prefix %c from %s", prefix, restriction.c_str()); + exempts[restriction] = prefix; + } + exemptions.swap(exempts); + } + + void On005Numeric(std::map& tokens) CXX11_OVERRIDE + { + // Build a map of limits to their mode character. + insp::flat_map limits; + const ModeParser::ListModeList& listmodes = ServerInstance->Modes->GetListModes(); + for (ModeParser::ListModeList::const_iterator iter = listmodes.begin(); iter != listmodes.end(); ++iter) + { + const unsigned int limit = (*iter)->GetLowerLimit(); + limits[limit].push_back((*iter)->GetModeChar()); + } + + // Generate the MAXLIST token from the limits map. + std::string& buffer = tokens["MAXLIST"]; + for (insp::flat_map::const_iterator iter = limits.begin(); iter != limits.end(); ++iter) + { + if (!buffer.empty()) + buffer.push_back(','); + + buffer.append(iter->second); + buffer.push_back(':'); + buffer.append(ConvToStr(iter->first)); + } + } + void OnPostJoin(Membership* memb) CXX11_OVERRIDE { Channel* const chan = memb->chan; LocalUser* const localuser = IS_LOCAL(memb->user); if (localuser) { + // Remove existing invite, if any + invapi.Remove(localuser, chan); + if (chan->topicset) Topic::ShowTopic(localuser, chan); @@ -48,6 +123,57 @@ class CoreModChannel : public Module } } + ModResult OnCheckKey(User* user, Channel* chan, const std::string& keygiven) CXX11_OVERRIDE + { + // Hook only runs when being invited bypasses +bkl + return IsInvited(user, chan); + } + + ModResult OnCheckChannelBan(User* user, Channel* chan) CXX11_OVERRIDE + { + // Hook only runs when being invited bypasses +bkl + return IsInvited(user, chan); + } + + ModResult OnCheckLimit(User* user, Channel* chan) CXX11_OVERRIDE + { + // Hook only runs when being invited bypasses +bkl + return IsInvited(user, chan); + } + + ModResult OnCheckInvite(User* user, Channel* chan) CXX11_OVERRIDE + { + // Hook always runs + return IsInvited(user, chan); + } + + void OnUserDisconnect(LocalUser* user) CXX11_OVERRIDE + { + invapi.RemoveAll(user); + } + + void OnChannelDelete(Channel* chan) CXX11_OVERRIDE + { + // Make sure the channel won't appear in invite lists from now on, don't wait for cull to unset the ext + invapi.RemoveAll(chan); + } + + ModResult OnCheckExemption(User* user, Channel* chan, const std::string& restriction) CXX11_OVERRIDE + { + if (!exemptions.count(restriction)) + return MOD_RES_PASSTHRU; + + unsigned int mypfx = chan->GetPrefixValue(user); + char minmode = exemptions[restriction]; + + PrefixMode* mh = ServerInstance->Modes->FindPrefixMode(minmode); + if (mh && mypfx >= mh->GetPrefixRank()) + return MOD_RES_ALLOW; + if (mh || minmode == '*') + return MOD_RES_DENY; + return MOD_RES_PASSTHRU; + } + void Prioritize() CXX11_OVERRIDE { ServerInstance->Modules.SetPriority(this, I_OnPostJoin, PRIORITY_FIRST);