2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2015 Attila Molnar <attilamolnar@hush.com>
6 * This file is part of InspIRCd. InspIRCd is free software: you can
7 * redistribute it and/or modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation, version 2.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 static const unsigned int MAX_CAPS = sizeof(intptr_t) * 8;
28 typedef LocalIntExt ExtItem;
31 class Manager : public DataProvider
35 : DataProvider(mod, "capmanager")
39 /** Register a client capability.
40 * Modules should call Capability::SetActive(true) instead of this method.
41 * @param cap Capability to register
43 virtual void AddCap(Capability* cap) = 0;
45 /** Unregister a client capability.
46 * Modules should call Capability::SetActive(false) instead of this method.
47 * @param cap Capability to unregister
49 virtual void DelCap(Capability* cap) = 0;
51 /** Find a capability by name
52 * @param name Capability to find
53 * @return Capability object pointer if found, NULL otherwise
55 virtual Capability* Find(const std::string& name) const = 0;
58 /** Represents a client capability.
60 * Capabilities offer extensions to the client to server protocol. They must be negotiated with clients before they have any effect on the protocol.
61 * Each cap must have a unique name that is used during capability negotiation.
63 * After construction the cap is ready to be used by clients without any further setup, like other InspIRCd services.
64 * The get() method accepts a user as parameter and can be used to check whether that user has negotiated usage of the cap. This is only known for local users.
66 * 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.
67 * The capability can be deactivated and reactivated with the SetActive() method. Deactivated caps behave as if they don't exist.
69 * It is possible to implement special behavior by inheriting from this class and overriding some of its methods.
71 class Capability : public ServiceProvider, private dynamic_reference_base::CaptureHook
75 /** Bit allocated to this cap, undefined if the cap is unregistered
79 /** Extension containing all caps set by a user. NULL if the cap is unregistered.
83 /** True if the cap is active. Only active caps are registered in the manager.
87 /** Reference to the cap manager object
89 dynamic_reference<Manager> manager;
91 void OnCapture() CXX11_OVERRIDE
103 Ext AddToMask(Ext mask) const { return (mask | GetMask()); }
104 Ext DelFromMask(Ext mask) const { return (mask & (~GetMask())); }
105 Bit GetMask() const { return bit; }
107 friend class ManagerImpl;
110 /** Constructor, initializes the capability.
111 * Caps are active by default.
112 * @param mod Module providing the cap
113 * @param Name Raw name of the cap as used in the protocol (CAP LS, etc.)
115 Capability(Module* mod, const std::string& Name)
116 : ServiceProvider(mod, Name, SERVICE_CUSTOM)
118 , manager(mod, "capmanager")
128 void RegisterService() CXX11_OVERRIDE
130 manager.SetCaptureHook(this);
134 /** Check whether a user has the capability turned on.
135 * This method is safe to call if the cap is unregistered and will return false.
136 * @param user User to check
137 * @return True if the user is using this capability, false otherwise
139 bool get(User* user) const
143 Ext caps = extitem->get(user);
144 return (caps & GetMask());
147 /** Turn the capability on/off for a user. If the cap is not registered this method has no effect.
148 * @param user User to turn the cap on/off for
149 * @param val True to turn the cap on, false to turn it off
151 void set(User* user, bool val)
155 Ext curr = extitem->get(user);
156 extitem->set(user, (val ? AddToMask(curr) : DelFromMask(curr)));
159 /** Activate or deactivate the capability.
160 * If activating, the cap is marked as active and if the manager is available the cap is registered in the manager.
161 * If deactivating, the cap is marked as inactive and if it is registered, it will be unregistered.
162 * Users who had the cap turned on will have it turned off automatically.
163 * @param activate True to activate the cap, false to deactivate it
165 void SetActive(bool activate)
171 manager->AddCap(this);
173 manager->DelCap(this);
177 /** Get the name of the capability that's used in the protocol
178 * @return Name of the capability as used in the protocol
180 const std::string& GetName() const { return name; }
182 /** Check whether the capability is active. The cap must be active and registered to be used by users.
183 * @return True if the cap is active, false if it has been deactivated
185 bool IsActive() const { return active; }
187 /** Check whether the capability is registered
188 * The cap must be active and the manager must be available for a cap to be registered.
189 * @return True if the cap is registered in the manager, false otherwise
191 bool IsRegistered() const { return (extitem != NULL); }
193 /** Called when a user requests to turn this capability on or off.
194 * @param user User requesting to change the state of the cap
195 * @param add True if requesting to turn the cap on, false if requesting to turn it off
196 * @return True to allow the request, false to reject it
198 virtual bool OnRequest(LocalUser* user, bool add)