X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=include%2Fmodules%2Fcap.h;h=0bbd745c0ca40a5eb1d3e2c0a2865512d4dccd8b;hb=b0f16081ccaef527ed4b5434a7264508cf455f39;hp=9dd44a4aa35e4dd8a1bd0003e125524bacb6d6e8;hpb=259b1113944a01aeb450265f03fb97a283e8ef15;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/include/modules/cap.h b/include/modules/cap.h index 9dd44a4aa..0bbd745c0 100644 --- a/include/modules/cap.h +++ b/include/modules/cap.h @@ -1,7 +1,8 @@ /* * InspIRCd -- Internet Relay Chat Daemon * - * Copyright (C) 2015 Attila Molnar + * Copyright (C) 2018-2021 Sadie Powell + * Copyright (C) 2015-2016, 2018 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 @@ -23,11 +24,53 @@ namespace Cap { - static const unsigned int MAX_CAPS = sizeof(intptr_t) * 8; + static const unsigned int MAX_CAPS = (sizeof(intptr_t) * 8) - 1; + static const intptr_t CAP_302_BIT = (intptr_t)1 << MAX_CAPS; + static const unsigned int MAX_VALUE_LENGTH = 100; + typedef intptr_t Ext; - typedef LocalIntExt ExtItem; + class ExtItem : public LocalIntExt + { + public: + ExtItem(Module* mod); + void FromInternal(Extensible* container, const std::string& value) CXX11_OVERRIDE; + std::string ToHuman(const Extensible* container, void* item) const CXX11_OVERRIDE; + std::string ToInternal(const Extensible* container, void* item) const CXX11_OVERRIDE; + }; + class Capability; + enum Protocol + { + /** Supports capability negotiation protocol v3.1, or none + */ + CAP_LEGACY, + + /** Supports capability negotiation v3.2 + */ + CAP_302 + }; + + class EventListener : public Events::ModuleEventListener + { + public: + EventListener(Module* mod) + : ModuleEventListener(mod, "event/cap") + { + } + + /** Called whenever a new client capability becomes available or unavailable + * @param cap Capability being added or removed + * @param add If true, the capability is being added, otherwise its being removed + */ + virtual void OnCapAddDel(Capability* cap, bool add) = 0; + + /** Called whenever the value of a cap changes. + * @param cap Capability whose value changed + */ + virtual void OnCapValueChange(Capability* cap) { } + }; + class Manager : public DataProvider { public: @@ -53,6 +96,11 @@ namespace Cap * @return Capability object pointer if found, NULL otherwise */ virtual Capability* Find(const std::string& name) const = 0; + + /** Notify manager when a value of a cap changed + * @param cap Cap whose value changed + */ + virtual void NotifyValueChange(Capability* cap) = 0; }; /** Represents a client capability. @@ -65,6 +113,8 @@ namespace Cap * * The cap module must be loaded for the capability to work. The IsRegistered() method can be used to query whether the cap is actually online or not. * The capability can be deactivated and reactivated with the SetActive() method. Deactivated caps behave as if they don't exist. + * + * It is possible to implement special behavior by inheriting from this class and overriding some of its methods. */ class Capability : public ServiceProvider, private dynamic_reference_base::CaptureHook { @@ -104,6 +154,16 @@ namespace Cap friend class ManagerImpl; + protected: + /** Notify the manager that the value of the capability changed. + * Must be called if the value of the cap changes for any reason. + */ + void NotifyValueChange() + { + if (IsRegistered()) + manager->NotifyValueChange(this); + } + public: /** Constructor, initializes the capability. * Caps are active by default. @@ -139,7 +199,7 @@ namespace Cap if (!IsRegistered()) return false; Ext caps = extitem->get(user); - return (caps & GetMask()); + return ((caps & GetMask()) != 0); } /** Turn the capability on/off for a user. If the cap is not registered this method has no effect. @@ -187,5 +247,97 @@ namespace Cap * @return True if the cap is registered in the manager, false otherwise */ bool IsRegistered() const { return (extitem != NULL); } + + /** Get the CAP negotiation protocol version of a user. + * The cap must be registered for this to return anything other than CAP_LEGACY. + * @param user User whose negotiation protocol version to query + * @return One of the Capability::Protocol enum indicating the highest supported capability negotiation protocol version + */ + Protocol GetProtocol(LocalUser* user) const + { + return ((IsRegistered() && (extitem->get(user) & CAP_302_BIT)) ? CAP_302 : CAP_LEGACY); + } + + /** Called when a user requests to turn this capability on or off. + * @param user User requesting to change the state of the cap + * @param add True if requesting to turn the cap on, false if requesting to turn it off + * @return True to allow the request, false to reject it + */ + virtual bool OnRequest(LocalUser* user, bool add) + { + return true; + } + + /** Called when a user requests a list of all capabilities and this capability is about to be included in the list. + * The default behavior always includes the cap in the list. + * @param user User querying a list capabilities + * @return True to add this cap to the list sent to the user, false to not list it + */ + virtual bool OnList(LocalUser* user) + { + return true; + } + + /** Query the value of this capability for a user + * @param user User who will get the value of the capability + * @return Value to show to the user. If NULL, the capability has no value (default). + */ + virtual const std::string* GetValue(LocalUser* user) const + { + return NULL; + } + }; + + /** Reference to a cap. The cap may be provided by another module. + */ + class Reference + { + dynamic_reference_nocheck ref; + + public: + /** Constructor, initializes the capability reference + * @param mod Module creating this object + * @param Name Raw name of the cap as used in the protocol (CAP LS, etc.) + */ + Reference(Module* mod, const std::string& Name) + : ref(mod, "cap/" + Name) + { + } + + /** Retrieves the underlying cap. */ + operator const Cap::Capability*() const + { + return ref ? *ref : NULL; + } + + /** Check whether a user has the referenced capability turned on. + * @param user User to check + * @return True if the user is using the referenced capability, false otherwise + */ + bool get(LocalUser* user) + { + if (ref) + return ref->get(user); + return false; + } + }; + + class MessageBase : public ClientProtocol::Message + { + public: + MessageBase(const std::string& subcmd) + : ClientProtocol::Message("CAP", ServerInstance->Config->GetServerName()) + { + PushParamPlaceholder(); + PushParam(subcmd); + } + + void SetUser(LocalUser* user) + { + if (user->registered & REG_NICK) + ReplaceParamRef(0, user->nick); + else + ReplaceParam(0, "*"); + } }; }