]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/modules/cap.h
m_cap Add Capability::OnRequest() hook
[user/henk/code/inspircd.git] / include / modules / cap.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2015 Attila Molnar <attilamolnar@hush.com>
5  *
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.
9  *
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
13  * details.
14  *
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/>.
17  */
18
19
20 #pragma once
21
22 #include "event.h"
23
24 namespace Cap
25 {
26         static const unsigned int MAX_CAPS = sizeof(intptr_t) * 8;
27         typedef intptr_t Ext;
28         typedef LocalIntExt ExtItem;
29         class Capability;
30
31         class Manager : public DataProvider
32         {
33          public:
34                 Manager(Module* mod)
35                         : DataProvider(mod, "capmanager")
36                 {
37                 }
38
39                 /** Register a client capability.
40                  * Modules should call Capability::SetActive(true) instead of this method.
41                  * @param cap Capability to register
42                  */
43                 virtual void AddCap(Capability* cap) = 0;
44
45                 /** Unregister a client capability.
46                  * Modules should call Capability::SetActive(false) instead of this method.
47                  * @param cap Capability to unregister
48                  */
49                 virtual void DelCap(Capability* cap) = 0;
50
51                 /** Find a capability by name
52                  * @param name Capability to find
53                  * @return Capability object pointer if found, NULL otherwise
54                  */
55                 virtual Capability* Find(const std::string& name) const = 0;
56         };
57
58         /** Represents a client capability.
59          *
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.
62          *
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.
65          *
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.
68          *
69          * It is possible to implement special behavior by inheriting from this class and overriding some of its methods.
70          */
71         class Capability : public ServiceProvider, private dynamic_reference_base::CaptureHook
72         {
73                 typedef size_t Bit;
74
75                 /** Bit allocated to this cap, undefined if the cap is unregistered
76                  */
77                 Bit bit;
78
79                 /** Extension containing all caps set by a user. NULL if the cap is unregistered.
80                  */
81                 ExtItem* extitem;
82
83                 /** True if the cap is active. Only active caps are registered in the manager.
84                  */
85                 bool active;
86
87                 /** Reference to the cap manager object
88                  */
89                 dynamic_reference<Manager> manager;
90
91                 void OnCapture() CXX11_OVERRIDE
92                 {
93                         if (active)
94                                 SetActive(true);
95                 }
96
97                 void Unregister()
98                 {
99                         bit = 0;
100                         extitem = NULL;
101                 }
102
103                 Ext AddToMask(Ext mask) const { return (mask | GetMask()); }
104                 Ext DelFromMask(Ext mask) const { return (mask & (~GetMask())); }
105                 Bit GetMask() const { return bit; }
106
107                 friend class ManagerImpl;
108
109          public:
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.)
114                  */
115                 Capability(Module* mod, const std::string& Name)
116                         : ServiceProvider(mod, Name, SERVICE_CUSTOM)
117                         , active(true)
118                         , manager(mod, "capmanager")
119                 {
120                         Unregister();
121                 }
122
123                 ~Capability()
124                 {
125                         SetActive(false);
126                 }
127
128                 void RegisterService() CXX11_OVERRIDE
129                 {
130                         manager.SetCaptureHook(this);
131                         SetActive(true);
132                 }
133
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
138                  */
139                 bool get(User* user) const
140                 {
141                         if (!IsRegistered())
142                                 return false;
143                         Ext caps = extitem->get(user);
144                         return (caps & GetMask());
145                 }
146
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
150                  */
151                 void set(User* user, bool val)
152                 {
153                         if (!IsRegistered())
154                                 return;
155                         Ext curr = extitem->get(user);
156                         extitem->set(user, (val ? AddToMask(curr) : DelFromMask(curr)));
157                 }
158
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
164                  */
165                 void SetActive(bool activate)
166                 {
167                         active = activate;
168                         if (manager)
169                         {
170                                 if (activate)
171                                         manager->AddCap(this);
172                                 else
173                                         manager->DelCap(this);
174                         }
175                 }
176
177                 /** Get the name of the capability that's used in the protocol
178                  * @return Name of the capability as used in the protocol
179                  */
180                 const std::string& GetName() const { return name; }
181
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
184                  */
185                 bool IsActive() const { return active; }
186
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
190                  */
191                 bool IsRegistered() const { return (extitem != NULL); }
192
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
197                  */
198                 virtual bool OnRequest(LocalUser* user, bool add)
199                 {
200                         return true;
201                 }
202         };
203 }