+ delete capmoddata;
+ }
+
+ public:
+ ManagerImpl(Module* mod, Events::ModuleEventProvider& evprovref)
+ : Cap::Manager(mod)
+ , ReloadModule::EventListener(mod)
+ , capext(mod)
+ , evprov(evprovref)
+ {
+ managerimpl = this;
+ }
+
+ ~ManagerImpl()
+ {
+ for (CapMap::iterator i = caps.begin(); i != caps.end(); ++i)
+ {
+ Capability* cap = i->second;
+ cap->Unregister();
+ }
+ }
+
+ void AddCap(Cap::Capability* cap) CXX11_OVERRIDE
+ {
+ // No-op if the cap is already registered.
+ // This allows modules to call SetActive() on a cap without checking if it's active first.
+ if (cap->IsRegistered())
+ return;
+
+ ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Registering cap %s", cap->GetName().c_str());
+ cap->bit = AllocateBit();
+ cap->extitem = &capext;
+ caps.insert(std::make_pair(cap->GetName(), cap));
+ ServerInstance->Modules.AddReferent("cap/" + cap->GetName(), cap);
+
+ FOREACH_MOD_CUSTOM(evprov, Cap::EventListener, OnCapAddDel, (cap, true));
+ }
+
+ void DelCap(Cap::Capability* cap) CXX11_OVERRIDE
+ {
+ // No-op if the cap is not registered, see AddCap() above
+ if (!cap->IsRegistered())
+ return;
+
+ ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Unregistering cap %s", cap->GetName().c_str());
+
+ // Fire the event first so modules can still see who is using the cap which is being unregistered
+ FOREACH_MOD_CUSTOM(evprov, Cap::EventListener, OnCapAddDel, (cap, false));
+
+ // Turn off the cap for all users
+ const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
+ for (UserManager::LocalList::const_iterator i = list.begin(); i != list.end(); ++i)
+ {
+ LocalUser* user = *i;
+ cap->set(user, false);
+ }
+
+ ServerInstance->Modules.DelReferent(cap);
+ cap->Unregister();
+ caps.erase(cap->GetName());
+ }
+
+ Capability* Find(const std::string& capname) const CXX11_OVERRIDE
+ {
+ CapMap::const_iterator it = caps.find(capname);
+ if (it != caps.end())
+ return it->second;
+ return NULL;
+ }
+
+ void NotifyValueChange(Capability* cap) CXX11_OVERRIDE
+ {
+ ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Cap %s changed value", cap->GetName().c_str());
+ FOREACH_MOD_CUSTOM(evprov, Cap::EventListener, OnCapValueChange, (cap));
+ }
+
+ Protocol GetProtocol(LocalUser* user) const
+ {
+ return ((capext.get(user) & CAP_302_BIT) ? CAP_302 : CAP_LEGACY);
+ }
+
+ void Set302Protocol(LocalUser* user)
+ {
+ capext.set(user, capext.get(user) | CAP_302_BIT);
+ }
+
+ bool HandleReq(LocalUser* user, const std::string& reqlist)
+ {
+ Ext usercaps = capext.get(user);
+ irc::spacesepstream ss(reqlist);
+ for (std::string capname; ss.GetToken(capname); )
+ {
+ bool remove = (capname[0] == '-');
+ if (remove)
+ capname.erase(capname.begin());
+
+ Capability* cap = ManagerImpl::Find(capname);
+ if ((!cap) || (!CanRequest(user, usercaps, cap, !remove)))
+ return false;
+
+ if (remove)
+ usercaps = cap->DelFromMask(usercaps);
+ else
+ usercaps = cap->AddToMask(usercaps);
+ }
+
+ capext.set(user, usercaps);
+ return true;
+ }
+
+ void HandleList(std::vector<std::string>& out, LocalUser* user, bool show_all, bool show_values, bool minus_prefix = false) const
+ {
+ Ext show_caps = (show_all ? ~0 : capext.get(user));
+
+ for (CapMap::const_iterator i = caps.begin(); i != caps.end(); ++i)