X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_auditorium.cpp;h=f708ea9d0b253b452c7646aec3cf10b83e2af0a2;hb=e59cb85871f75b7603c63c6cd274d57536cf6794;hp=6b88a5e166ad5a4b03dea0938461d10005f93aef;hpb=fcacc8e0306382bc3f938073092c3729d77e2b41;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_auditorium.cpp b/src/modules/m_auditorium.cpp index 6b88a5e16..f708ea9d0 100644 --- a/src/modules/m_auditorium.cpp +++ b/src/modules/m_auditorium.cpp @@ -21,56 +21,65 @@ #include "inspircd.h" +#include "modules/exemption.h" +#include "modules/names.h" +#include "modules/who.h" -/* $ModDesc: Allows for auditorium channels (+u) where nobody can see others joining and parting or the nick list */ - -class AuditoriumMode : public ModeHandler +class AuditoriumMode : public SimpleChannelModeHandler { public: - AuditoriumMode(Module* Creator) : ModeHandler(Creator, "auditorium", 'u', PARAM_NONE, MODETYPE_CHANNEL) + AuditoriumMode(Module* Creator) : SimpleChannelModeHandler(Creator, "auditorium", 'u') { - levelrequired = OP_VALUE; + ranktoset = ranktounset = OP_VALUE; } +}; - ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) - { - if (channel->IsModeSet(this) == adding) - return MODEACTION_DENY; - channel->SetMode(this, adding); - return MODEACTION_ALLOW; - } +class ModuleAuditorium; + +namespace +{ + +/** Hook handler for join client protocol events. + * This allows us to block join protocol events completely, including all associated messages (e.g. MODE, away-notify AWAY). + * This is not the same as OnUserJoin() because that runs only when a real join happens but this runs also when a module + * such as delayjoin or hostcycle generates a join. + */ +class JoinHook : public ClientProtocol::EventHook +{ + ModuleAuditorium* const parentmod; + bool active; + + public: + JoinHook(ModuleAuditorium* mod); + void OnEventInit(const ClientProtocol::Event& ev) CXX11_OVERRIDE; + ModResult OnPreEventSend(LocalUser* user, const ClientProtocol::Event& ev, ClientProtocol::MessageList& messagelist) CXX11_OVERRIDE; }; -class ModuleAuditorium : public Module +} + +class ModuleAuditorium + : public Module + , public Names::EventListener + , public Who::EventListener { - private: + CheckExemption::EventProvider exemptionprov; AuditoriumMode aum; bool OpsVisible; bool OpsCanSee; bool OperCanSee; - public: - ModuleAuditorium() : aum(this) - { - } - - void init() - { - ServerInstance->Modules->AddService(aum); - - OnRehash(NULL); + JoinHook joinhook; - Implementation eventlist[] = { - I_OnUserJoin, I_OnUserPart, I_OnUserKick, - I_OnBuildNeighborList, I_OnNamesListItem, I_OnSendWhoLine, - I_OnRehash }; - ServerInstance->Modules->Attach(eventlist, this, 7); - } - - ~ModuleAuditorium() + public: + ModuleAuditorium() + : Names::EventListener(this) + , Who::EventListener(this) + , exemptionprov(this) + , aum(this) + , joinhook(this) { } - void OnRehash(User* user) + void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE { ConfigTag* tag = ServerInstance->Config->ConfValue("auditorium"); OpsVisible = tag->getBool("opvisible"); @@ -78,9 +87,9 @@ class ModuleAuditorium : public Module OperCanSee = tag->getBool("opercansee", true); } - Version GetVersion() + Version GetVersion() CXX11_OVERRIDE { - return Version("Allows for auditorium channels (+u) where nobody can see others joining and parting or the nick list", VF_VENDOR); + return Version("Provides channel mode +u, auditorium channels where nobody can see others joining and parting or the nick list", VF_VENDOR); } /* Can they be seen by everyone? */ @@ -89,7 +98,7 @@ class ModuleAuditorium : public Module if (!memb->chan->IsModeSet(&aum)) return true; - ModResult res = ServerInstance->OnCheckExemption(memb->user, memb->chan, "auditorium-vis"); + ModResult res = CheckExemption::Call(exemptionprov, memb->user, memb->chan, "auditorium-vis"); return res.check(OpsVisible && memb->getRank() >= OP_VALUE); } @@ -105,26 +114,23 @@ class ModuleAuditorium : public Module return true; // Can you see the list by permission? - ModResult res = ServerInstance->OnCheckExemption(issuer,memb->chan,"auditorium-see"); + ModResult res = CheckExemption::Call(exemptionprov, issuer, memb->chan, "auditorium-see"); if (res.check(OpsCanSee && memb->chan->GetPrefixValue(issuer) >= OP_VALUE)) return true; return false; } - void OnNamesListItem(User* issuer, Membership* memb, std::string &prefixes, std::string &nick) + ModResult OnNamesListItem(LocalUser* issuer, Membership* memb, std::string& prefixes, std::string& nick) CXX11_OVERRIDE { - // Some module already hid this from being displayed, don't bother - if (nick.empty()) - return; - if (IsVisible(memb)) - return; + return MOD_RES_PASSTHRU; if (CanSee(issuer, memb)) - return; + return MOD_RES_PASSTHRU; - nick.clear(); + // Don't display this user in the NAMES list + return MOD_RES_DENY; } /** Build CUList for showing this join/part/kick */ @@ -133,43 +139,40 @@ class ModuleAuditorium : public Module if (IsVisible(memb)) return; - const UserMembList* users = memb->chan->GetUsers(); - for(UserMembCIter i = users->begin(); i != users->end(); i++) + const Channel::MemberMap& users = memb->chan->GetUsers(); + for (Channel::MemberMap::const_iterator i = users.begin(); i != users.end(); ++i) { if (IS_LOCAL(i->first) && !CanSee(i->first, memb)) excepts.insert(i->first); } } - void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts) + void OnUserPart(Membership* memb, std::string &partmessage, CUList& excepts) CXX11_OVERRIDE { BuildExcept(memb, excepts); } - void OnUserPart(Membership* memb, std::string &partmessage, CUList& excepts) + void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& excepts) CXX11_OVERRIDE { BuildExcept(memb, excepts); } - void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& excepts) + void OnBuildNeighborList(User* source, IncludeChanList& include, std::map& exception) CXX11_OVERRIDE { - BuildExcept(memb, excepts); - } - - void OnBuildNeighborList(User* source, UserChanList &include, std::map &exception) - { - UCListIter i = include.begin(); - while (i != include.end()) + for (IncludeChanList::iterator i = include.begin(); i != include.end(); ) { - Channel* c = *i++; - Membership* memb = c->GetUser(source); - if (!memb || IsVisible(memb)) + Membership* memb = *i; + if (IsVisible(memb)) + { + ++i; continue; + } + // this channel should not be considered when listing my neighbors - include.erase(c); + i = include.erase(i); // however, that might hide me from ops that can see me... - const UserMembList* users = c->GetUsers(); - for(UserMembCIter j = users->begin(); j != users->end(); j++) + const Channel::MemberMap& users = memb->chan->GetUsers(); + for(Channel::MemberMap::const_iterator j = users.begin(); j != users.end(); ++j) { if (IS_LOCAL(j->first) && CanSee(j->first, memb)) exception[j->first] = true; @@ -177,18 +180,37 @@ class ModuleAuditorium : public Module } } - void OnSendWhoLine(User* source, const std::vector& params, User* user, std::string& line) + ModResult OnWhoLine(const Who::Request& request, LocalUser* source, User* user, Membership* memb, Numeric::Numeric& numeric) CXX11_OVERRIDE { - Channel* channel = ServerInstance->FindChan(params[0]); - if (!channel) - return; - Membership* memb = channel->GetUser(user); + if (!memb) + return MOD_RES_PASSTHRU; if (IsVisible(memb)) - return; + return MOD_RES_PASSTHRU; if (CanSee(source, memb)) - return; - line.clear(); + return MOD_RES_PASSTHRU; + return MOD_RES_DENY; } }; +JoinHook::JoinHook(ModuleAuditorium* mod) + : ClientProtocol::EventHook(mod, "JOIN", 10) + , parentmod(mod) +{ +} + +void JoinHook::OnEventInit(const ClientProtocol::Event& ev) +{ + const ClientProtocol::Events::Join& join = static_cast(ev); + active = !parentmod->IsVisible(join.GetMember()); +} + +ModResult JoinHook::OnPreEventSend(LocalUser* user, const ClientProtocol::Event& ev, ClientProtocol::MessageList& messagelist) +{ + if (!active) + return MOD_RES_PASSTHRU; + + const ClientProtocol::Events::Join& join = static_cast(ev); + return ((parentmod->CanSee(user, join.GetMember())) ? MOD_RES_PASSTHRU : MOD_RES_DENY); +} + MODULE_INIT(ModuleAuditorium)