]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_ircv3_capnotify.cpp
Sync helpop chmodes s and p with docs
[user/henk/code/inspircd.git] / src / modules / m_ircv3_capnotify.cpp
index 93c30df123ce018e28cc4f3aa73ebf104e65ea41..816412dab6fa575f43905688a5cac33266ab128c 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * InspIRCd -- Internet Relay Chat Daemon
  *
- *   Copyright (C) 2015 Attila Molnar <attilamolnar@hush.com>
+ *   Copyright (C) 2018-2020 Sadie Powell <sadie@witchery.services>
+ *   Copyright (C) 2015, 2018 Attila Molnar <attilamolnar@hush.com>
  *
  * 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
@@ -46,19 +47,53 @@ class CapNotify : public Cap::Capability
        }
 };
 
+class CapNotifyMessage : public Cap::MessageBase
+{
+ public:
+       CapNotifyMessage(bool add, const std::string& capname)
+               : Cap::MessageBase((add ? "NEW" : "DEL"))
+       {
+               PushParamRef(capname);
+       }
+};
+
+class CapNotifyValueMessage : public Cap::MessageBase
+{
+       std::string s;
+       const std::string::size_type pos;
+
+ public:
+       CapNotifyValueMessage(const std::string& capname)
+               : Cap::MessageBase("NEW")
+               , s(capname)
+               , pos(s.size()+1)
+       {
+               s.push_back('=');
+               PushParamRef(s);
+       }
+
+       void SetCapValue(const std::string& capvalue)
+       {
+               s.erase(pos);
+               s.append(capvalue);
+               InvalidateCache();
+       }
+};
+
 class ModuleIRCv3CapNotify : public Module, public Cap::EventListener, public ReloadModule::EventListener
 {
        CapNotify capnotify;
        std::string reloadedmod;
        std::vector<std::string> reloadedcaps;
+       ClientProtocol::EventProvider protoev;
 
        void Send(const std::string& capname, Cap::Capability* cap, bool add)
        {
-               std::string msg = (add ? "NEW :" : "DEL :");
-               msg.append(capname);
-               std::string msgwithval = msg;
-               msgwithval.push_back('=');
-               std::string::size_type msgpos = msgwithval.size();
+               CapNotifyMessage msg(add, capname);
+               CapNotifyValueMessage msgwithval(capname);
+
+               ClientProtocol::Event event(protoev, msg);
+               ClientProtocol::Event eventwithval(protoev, msgwithval);
 
                const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
                for (UserManager::LocalList::const_iterator i = list.begin(); i != list.end(); ++i)
@@ -67,19 +102,24 @@ class ModuleIRCv3CapNotify : public Module, public Cap::EventListener, public Re
                        if (!capnotify.get(user))
                                continue;
 
+                       // Check that this user can actually see the cap.
+                       if (add && (!cap || !cap->OnList(user)))
+                               continue;
+
                        // If the cap is being added and the client supports cap values then show the value, if any
                        if ((add) && (capnotify.GetProtocol(user) != Cap::CAP_LEGACY))
                        {
                                const std::string* capvalue = cap->GetValue(user);
                                if ((capvalue) && (!capvalue->empty()))
                                {
-                                       msgwithval.append(*capvalue);
-                                       user->WriteCommand("CAP", msgwithval);
-                                       msgwithval.erase(msgpos);
+                                       msgwithval.SetUser(user);
+                                       msgwithval.SetCapValue(*capvalue);
+                                       user->Send(eventwithval);
                                        continue;
                                }
                        }
-                       user->WriteCommand("CAP", msg);
+                       msg.SetUser(user);
+                       user->Send(event);
                }
        }
 
@@ -88,6 +128,7 @@ class ModuleIRCv3CapNotify : public Module, public Cap::EventListener, public Re
                : Cap::EventListener(this)
                , ReloadModule::EventListener(this)
                , capnotify(this)
+               , protoev(this, "CAP_NOTIFY")
        {
        }
 
@@ -123,7 +164,7 @@ class ModuleIRCv3CapNotify : public Module, public Cap::EventListener, public Re
 
        void OnReloadModuleRestore(Module* mod, void* data) CXX11_OVERRIDE
        {
-               // Reloading can change the set of caps provided by a module so assuming that if the reload succeded all
+               // Reloading can change the set of caps provided by a module so assuming that if the reload succeeded all
                // caps that the module previously provided are available or all were lost if the reload failed is wrong.
                // Instead, we verify the availability of each cap individually.
                dynamic_reference_nocheck<Cap::Manager> capmanager(this, "capmanager");
@@ -142,7 +183,7 @@ class ModuleIRCv3CapNotify : public Module, public Cap::EventListener, public Re
 
        Version GetVersion() CXX11_OVERRIDE
        {
-               return Version("Provides the cap-notify IRCv3.2 extension", VF_VENDOR);
+               return Version("Provides the IRCv3 cap-notify client capability.", VF_VENDOR);
        }
 };