X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_delayjoin.cpp;h=d157b97bcc90461ebf39d3895aa031919a1d6b7c;hb=de4e4860091fe5a9a530acdb25f9a17e22323acf;hp=f9cd837d7a23bd66dbcf27c11dda9727838d28c3;hpb=124c17e14134a4999afc1a5e981ab7c75b3694b9;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_delayjoin.cpp b/src/modules/m_delayjoin.cpp index f9cd837d7..d157b97bc 100644 --- a/src/modules/m_delayjoin.cpp +++ b/src/modules/m_delayjoin.cpp @@ -33,14 +33,50 @@ class DelayJoinMode : public ModeHandler ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& parameter, bool adding) CXX11_OVERRIDE; }; + +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 hostcycle generates a join. + */ +class JoinHook : public ClientProtocol::EventHook +{ + const LocalIntExt& unjoined; + + public: + JoinHook(Module* mod, const LocalIntExt& unjoinedref) + : ClientProtocol::EventHook(mod, "JOIN", 10) + , unjoined(unjoinedref) + { + } + + ModResult OnPreEventSend(LocalUser* user, const ClientProtocol::Event& ev, ClientProtocol::MessageList& messagelist) CXX11_OVERRIDE + { + const ClientProtocol::Events::Join& join = static_cast(ev); + const User* const u = join.GetMember()->user; + if ((unjoined.get(u)) && (u != user)) + return MOD_RES_DENY; + return MOD_RES_PASSTHRU; + } +}; + +} + class ModuleDelayJoin : public Module { DelayJoinMode djm; + void RevealUser(User* user, Channel* chan); public: LocalIntExt unjoined; + JoinHook joinhook; + ModuleDelayJoin() : djm(this) , unjoined("delayjoin", ExtensionItem::EXT_MEMBERSHIP, this) + , joinhook(this, unjoined) { } @@ -55,6 +91,16 @@ class ModuleDelayJoin : public Module ModResult OnRawMode(User* user, Channel* channel, ModeHandler* mh, const std::string& param, bool adding) CXX11_OVERRIDE; }; +// TODO: make RevealUser accessible from DelayJoinMode and get rid of this. +class DummyMessageDetails : public MessageDetails +{ +public: + DummyMessageDetails() : MessageDetails(MSG_PRIVMSG, "", ClientProtocol::TagMap()) { } + bool IsCTCP(std::string& name, std::string& body) const CXX11_OVERRIDE { return false; } + bool IsCTCP(std::string&) const CXX11_OVERRIDE { return false; } + bool IsCTCP() const CXX11_OVERRIDE { return false; } +}; + ModeAction DelayJoinMode::OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) { /* no change */ @@ -68,7 +114,7 @@ ModeAction DelayJoinMode::OnModeChange(User* source, User* dest, Channel* channe * they remain permanently invisible on this channel! */ MessageTarget msgtarget(channel, 0); - MessageDetails msgdetails(MSG_PRIVMSG, ""); + DummyMessageDetails msgdetails; const Channel::MemberMap& users = channel->GetUsers(); for (Channel::MemberMap::const_iterator n = users.begin(); n != users.end(); ++n) { @@ -111,10 +157,7 @@ static void populate(CUList& except, Membership* memb) void ModuleDelayJoin::OnUserJoin(Membership* memb, bool sync, bool created, CUList& except) { if (memb->chan->IsModeSet(djm)) - { unjoined.set(memb, 1); - populate(except, memb); - } } void ModuleDelayJoin::OnUserPart(Membership* memb, std::string &partmessage, CUList& except) @@ -147,20 +190,20 @@ void ModuleDelayJoin::OnUserMessage(User* user, const MessageTarget& target, con return; Channel* channel = target.Get(); + RevealUser(user, channel); +} - Membership* memb = channel->GetUser(user); +void ModuleDelayJoin::RevealUser(User* user, Channel* chan) +{ + Membership* memb = chan->GetUser(user); if (!memb || !unjoined.set(memb, 0)) return; /* Display the join to everyone else (the user who joined got it earlier) */ - channel->WriteAllExceptSender(user, false, 0, "JOIN %s", channel->name.c_str()); - - std::string ms = memb->modes; - for(unsigned int i=0; i < memb->modes.length(); i++) - ms.append(" ").append(user->nick); - - if (ms.length() > 0) - channel->WriteAllExceptSender(user, false, 0, "MODE %s +%s", channel->name.c_str(), ms.c_str()); + CUList except_list; + except_list.insert(user); + ClientProtocol::Events::Join joinevent(memb); + chan->Write(joinevent, 0, except_list); } /* make the user visible if he receives any mode change */ @@ -182,9 +225,7 @@ ModResult ModuleDelayJoin::OnRawMode(User* user, Channel* channel, ModeHandler* if (!dest) return MOD_RES_PASSTHRU; - Membership* memb = channel->GetUser(dest); - if (memb && unjoined.set(memb, 0)) - channel->WriteAllExceptSender(dest, false, 0, "JOIN %s", channel->name.c_str()); + RevealUser(dest, channel); return MOD_RES_PASSTHRU; }