From 8659d7224a6ff9d77209c706b4392a814d2e767b Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 19 Oct 2011 10:32:04 +0000 Subject: [PATCH] Make UpdateModule reload the module for every module type UpdateModule has been moved to CZNC because it doesn't really fit into CUser. The new UpdateModule will reload the module for global modules, user modules and network modules. Fixes #69 --- include/znc/User.h | 3 -- include/znc/znc.h | 10 ++++++ src/ClientCommand.cpp | 14 +++----- src/User.cpp | 27 -------------- src/znc.cpp | 84 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 40 deletions(-) diff --git a/include/znc/User.h b/include/znc/User.h index d4eb4b83..df12adec 100644 --- a/include/znc/User.h +++ b/include/znc/User.h @@ -58,9 +58,6 @@ public: static bool IsValidUserName(const CString& sUserName); static CString MakeCleanUserName(const CString& sUserName); - // Unloads a module on all users who have it loaded and loads it again. - static bool UpdateModule(const CString &sModule); - // Modules CModules& GetModules() { return *m_pModules; } const CModules& GetModules() const { return *m_pModules; } diff --git a/include/znc/znc.h b/include/znc/znc.h index cba22f94..46ead889 100644 --- a/include/znc/znc.h +++ b/include/znc/znc.h @@ -125,6 +125,16 @@ public: CUser* FindUser(const CString& sUsername); CModule* FindModule(const CString& sModName, const CString& sUsername); CModule* FindModule(const CString& sModName, CUser* pUser); + + /** Reload a module everywhere + * + * This method will unload a module globally, for a user and for each + * network. It will then reload them all again. + * + * @param sModule The name of the module to reload + */ + bool UpdateModule(const CString &sModule); + bool DeleteUser(const CString& sUsername); bool AddUser(CUser* pUser, CString& sErrorRet); const map & GetUserMap() const { return(m_msUsers); } diff --git a/src/ClientCommand.cpp b/src/ClientCommand.cpp index 3d7f8cb7..f26046fa 100644 --- a/src/ClientCommand.cpp +++ b/src/ClientCommand.cpp @@ -963,17 +963,11 @@ void CClient::UserCommand(CString& sLine) { return; } - if (m_pUser->DenyLoadMod() || !m_pUser->IsAdmin()) { - PutStatus("Unable to reload [" + sMod + "] Access Denied."); - return; - } - - PutStatus("Reloading [" + sMod + "] on all users..."); - if (CUser::UpdateModule(sMod)) { + PutStatus("Reloading [" + sMod + "] everywhere"); + if (CZNC::Get().UpdateModule(sMod)) { PutStatus("Done"); } else { - PutStatus("Done, but there were errors, some users no longer have [" - + sMod + "] loaded"); + PutStatus("Done, but there were errors, [" + sMod + "] could not be loaded everywhere."); } } else if ((sCommand.Equals("ADDBINDHOST") || sCommand.Equals("ADDVHOST")) && m_pUser->IsAdmin()) { CString sHost = sLine.Token(1); @@ -1476,7 +1470,7 @@ void CClient::HelpUser() { Table.AddRow(); Table.SetCell("Command", "UpdateMod"); Table.SetCell("Arguments", ""); - Table.SetCell("Description", "Reload a module on all users"); + Table.SetCell("Description", "Reload a module everywhere"); } } diff --git a/src/User.cpp b/src/User.cpp index 635db777..978c566a 100644 --- a/src/User.cpp +++ b/src/User.cpp @@ -411,33 +411,6 @@ bool CUser::ParseConfig(CConfig* pConfig, CString& sError) { return true; } -bool CUser::UpdateModule(const CString &sModule) { - const map& Users = CZNC::Get().GetUserMap(); - map::const_iterator it; - map Affected; - map::iterator it2; - bool error = false; - - for (it = Users.begin(); it != Users.end(); ++it) { - CModule *pMod = it->second->GetModules().FindModule(sModule); - if (pMod) { - Affected[it->second] = pMod->GetArgs(); - it->second->GetModules().UnloadModule(pMod->GetModName()); - } - } - - CString sErr; - for (it2 = Affected.begin(); it2 != Affected.end(); ++it2) { - if (!it2->first->GetModules().LoadModule(sModule, it2->second, CModInfo::UserModule, it2->first, NULL, sErr)) { - error = true; - DEBUG("Failed to reload [" << sModule << "] for [" << it2->first->GetUserName() - << "]: " << sErr); - } - } - - return !error; -} - CIRCNetwork* CUser::AddNetwork(const CString &sNetwork) { if (!CIRCNetwork::IsValidNetwork(sNetwork) || FindNetwork(sNetwork)) { return NULL; diff --git a/src/znc.cpp b/src/znc.cpp index ae026f3e..20a188a3 100644 --- a/src/znc.cpp +++ b/src/znc.cpp @@ -1393,6 +1393,90 @@ CModule* CZNC::FindModule(const CString& sModName, CUser* pUser) { return CZNC::Get().GetModules().FindModule(sModName); } +bool CZNC::UpdateModule(const CString &sModule) { + CModule *pModule; + + map::const_iterator it; + map musLoaded; + map::iterator musIt; + map mnsLoaded; + map::iterator mnsIt; + + // Unload the module for every user and network + for (it = m_msUsers.begin(); it != m_msUsers.end(); ++it) { + CUser *pUser = it->second; + + pModule = pUser->GetModules().FindModule(sModule); + if (pModule) { + musLoaded[pUser] = pModule->GetArgs(); + pUser->GetModules().UnloadModule(sModule); + } + + // See if the user has this module loaded to a network + vector vNetworks = pUser->GetNetworks(); + vector::iterator it2; + for (it2 = vNetworks.begin(); it2 != vNetworks.end(); ++it2) { + CIRCNetwork *pNetwork = *it2; + + pModule = pNetwork->GetModules().FindModule(sModule); + if (pModule) { + mnsLoaded[pNetwork] = pModule->GetArgs(); + pNetwork->GetModules().UnloadModule(sModule); + } + } + } + + // Unload the global module + bool bGlobal = false; + CString sGlobalArgs; + + pModule = GetModules().FindModule(sModule); + if (pModule) { + bGlobal = true; + sGlobalArgs = pModule->GetArgs(); + GetModules().UnloadModule(sModule); + } + + // Lets reload everything + bool bError = false; + CString sErr; + + // Reload the global module + if (bGlobal) { + if (!GetModules().LoadModule(sModule, sGlobalArgs, CModInfo::GlobalModule, NULL, NULL, sErr)) { + DEBUG("Failed to reload [" << sModule << "] globally [" << sErr << "]"); + bError = true; + } + } + + // Reload the module for all users + for (musIt = musLoaded.begin(); musIt != musLoaded.end(); ++musIt) { + CUser *pUser = musIt->first; + CString& sArgs = musIt->second; + + if (!pUser->GetModules().LoadModule(sModule, sArgs, CModInfo::UserModule, pUser, NULL, sErr)) { + DEBUG("Failed to reload [" << sModule << "] for [" + << pUser->GetUserName() << "] [" << sErr << "]"); + bError = true; + } + } + + // Reload the module for all networks + for (mnsIt = mnsLoaded.begin(); mnsIt != mnsLoaded.end(); ++mnsIt) { + CIRCNetwork *pNetwork = mnsIt->first; + CString& sArgs = mnsIt->second; + + if (!pNetwork->GetModules().LoadModule(sModule, sArgs, CModInfo::NetworkModule, pNetwork->GetUser(), pNetwork, sErr)) { + DEBUG("Failed to reload [" << sModule << "] for [" + << pNetwork->GetUser()->GetUserName() << "/" + << pNetwork->GetName() << "] [" << sErr << "]"); + bError = true; + } + } + + return !bError; +} + CUser* CZNC::FindUser(const CString& sUsername) { map::iterator it = m_msUsers.find(sUsername);