+
+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<const ClientProtocol::Events::Join&>(ev);
+ const Membership* const memb = join.GetMember();
+ const User* const u = memb->user;
+ if ((unjoined.get(memb)) && (u != user))
+ return MOD_RES_DENY;
+ return MOD_RES_PASSTHRU;
+ }
+};
+
+}
+
+class ModuleDelayJoin
+ : public Module
+ , public CTCTags::EventListener
+ , public Names::EventListener