diff --git a/ClientCommand.cpp b/ClientCommand.cpp index 06f1b7b42d..b265df12f2 100644 --- a/ClientCommand.cpp +++ b/ClientCommand.cpp @@ -562,11 +562,20 @@ void CClient::UserCommand(CString& sLine) { } return; } else if (sCommand.Equals("LOADMOD") || sCommand.Equals("LOADMODULE")) { - CString sMod; - CString sArgs; - - sMod = sLine.Token(1); - sArgs = sLine.Token(2, true); + EModuleType eType; + CString sType = sLine.Token(1); + CString sMod = sLine.Token(2); + CString sArgs = sLine.Token(3, true); + + if (sType.Equals("global")) { + eType = ModuleTypeGlobal; + } else if (sType.Equals("user")) { + eType = ModuleTypeUser; + } else { + sMod = sType; + sArgs = sLine.Token(2, true); + sType = "default"; + } if (m_pUser->DenyLoadMod()) { PutStatus("Unable to load [" + sMod + "] Access Denied."); @@ -574,7 +583,7 @@ void CClient::UserCommand(CString& sLine) { } if (sMod.empty()) { - PutStatus("Usage: LoadMod [args]"); + PutStatus("Usage: LoadMod [type] [args]"); return; } @@ -585,23 +594,28 @@ void CClient::UserCommand(CString& sLine) { return; } + if (sType.Equals("default")) { + eType = ModInfo.DefaultType(); + } + + if (eType == ModuleTypeGlobal && !m_pUser->IsAdmin()) { + PutStatus("Unable to load global module [" + sMod + "] Access Denied."); + return; + } + CString sModRet; bool b = false; - switch (ModInfo.GetType()) { + switch (eType) { case ModuleTypeGlobal: - if (m_pUser->IsAdmin()) { - b = CZNC::Get().GetModules().LoadModule(sMod, sArgs, ModuleTypeGlobal, NULL, sModRet); - } else { - sModRet = "Unable to load global module [" + sMod + "] Access Denied."; - } + b = CZNC::Get().GetModules().LoadModule(sMod, sArgs, eType, NULL, sModRet); break; case ModuleTypeUser: - b = m_pUser->GetModules().LoadModule(sMod, sArgs, ModuleTypeUser, m_pUser, sModRet); + b = m_pUser->GetModules().LoadModule(sMod, sArgs, eType, m_pUser, sModRet); break; default: sModRet = "Unable to load module [" + sMod + "] Unknown module type"; - break; + } if (b) @@ -610,44 +624,84 @@ void CClient::UserCommand(CString& sLine) { PutStatus(sModRet); return; } else if (sCommand.Equals("UNLOADMOD") || sCommand.Equals("UNLOADMODULE")) { - CString sMod; - sMod = sLine.Token(1); + EModuleType eType = ModuleTypeUser; + CString sType = sLine.Token(1); + CString sMod = sLine.Token(2); + + if (sType.Equals("global")) { + eType = ModuleTypeGlobal; + } else if (sType.Equals("user")) { + eType = ModuleTypeUser; + } else { + sMod = sType; + sType = "default"; + } if (m_pUser->DenyLoadMod()) { PutStatus("Unable to unload [" + sMod + "] Access Denied."); return; } + if (sMod.empty()) { - PutStatus("Usage: UnloadMod "); + PutStatus("Usage: UnloadMod [type] "); + return; + } + + CModInfo ModInfo; + CString sRetMsg; + if (!CZNC::Get().GetModules().GetModInfo(ModInfo, sMod, sRetMsg)) { + PutStatus("Unable to find modinfo [" + sMod + "] [" + sRetMsg + "]"); + return; + } + + if (sType.Equals("default")) { + eType = ModInfo.DefaultType(); + } + + if (eType == ModuleTypeGlobal && !m_pUser->IsAdmin()) { + PutStatus("Unable to unload global module [" + sMod + "] Access Denied."); return; } CString sModRet; - bool b; - // First, try to unload the user module - b = m_pUser->GetModules().UnloadModule(sMod, sModRet); - if (!b && m_pUser->IsAdmin()) { - // If that failed and the user is an admin, try to unload a global module - b = CZNC::Get().GetModules().UnloadModule(sMod, sModRet); + switch (eType) { + case ModuleTypeGlobal: + CZNC::Get().GetModules().UnloadModule(sMod, sModRet); + break; + case ModuleTypeUser: + m_pUser->GetModules().UnloadModule(sMod, sModRet); + break; + default: + sModRet = "Unable to unload module [" + sMod + "] Unknown module type"; + } PutStatus(sModRet); return; } else if (sCommand.Equals("RELOADMOD") || sCommand.Equals("RELOADMODULE")) { - CString sMod; - CString sArgs; - - sMod = sLine.Token(1); - sArgs = sLine.Token(2, true); + EModuleType eType; + CString sType = sLine.Token(1); + CString sMod = sLine.Token(2); + CString sArgs = sLine.Token(3, true); if (m_pUser->DenyLoadMod()) { PutStatus("Unable to reload modules. Access Denied."); return; } + if (sType.Equals("global")) { + eType = ModuleTypeGlobal; + } else if (sType.Equals("user")) { + eType = ModuleTypeUser; + } else { + sMod = sType; + sArgs = sLine.Token(2, true); + sType = "default"; + } + if (sMod.empty()) { - PutStatus("Usage: ReloadMod [args]"); + PutStatus("Usage: ReloadMod [type] [args]"); return; } @@ -658,14 +712,19 @@ void CClient::UserCommand(CString& sLine) { return; } + if (sType.Equals("default")) { + eType = ModInfo.DefaultType(); + } + + if (eType == ModuleTypeGlobal && !m_pUser->IsAdmin()) { + PutStatus("Unable to reload global module [" + sMod + "] Access Denied."); + return; + } + CString sModRet; - switch (ModInfo.GetType()) { + switch (eType) { case ModuleTypeGlobal: - if (!m_pUser->IsAdmin()) { - PutStatus("Unable to reload modules. Access Denied."); - return; - } CZNC::Get().GetModules().ReloadModule(sMod, sArgs, NULL, sModRet); break; case ModuleTypeUser: @@ -673,7 +732,7 @@ void CClient::UserCommand(CString& sLine) { break; default: sModRet = "Unable to reload module [" + sMod + "] Unknown module type"; - break; + } PutStatus(sModRet); @@ -1143,17 +1202,17 @@ void CClient::HelpUser() { if (!m_pUser->DenyLoadMod()) { Table.AddRow(); Table.SetCell("Command", "LoadMod"); - Table.SetCell("Arguments", ""); + Table.SetCell("Arguments", "[type] "); Table.SetCell("Description", "Load a module"); Table.AddRow(); Table.SetCell("Command", "UnloadMod"); - Table.SetCell("Arguments", ""); + Table.SetCell("Arguments", "[type] "); Table.SetCell("Description", "Unload a module"); Table.AddRow(); Table.SetCell("Command", "ReloadMod"); - Table.SetCell("Arguments", ""); + Table.SetCell("Arguments", "[type] "); Table.SetCell("Description", "Reload a module"); if (m_pUser->IsAdmin()) { diff --git a/Modules.cpp b/Modules.cpp index 07e2c07b6c..89f7ff7ca3 100644 --- a/Modules.cpp +++ b/Modules.cpp @@ -830,9 +830,9 @@ bool CModules::LoadModule(const CString& sModule, const CString& sArgs, EModuleT return false; } - if (!Info.SupportsModule(eType)) { + if (!Info.SupportsType(eType)) { dlclose(p); - sRetMsg = "Module [ + sModule + ] does not support module type."; + sRetMsg = "Module [" + sModule + "] does not support module type."; return false; } @@ -858,7 +858,7 @@ bool CModules::LoadModule(const CString& sModule, const CString& sArgs, EModuleT } pModule->SetDescription(Info.GetDescription()); - pModule->SetType(Info.GetType()); + pModule->SetType(eType); pModule->SetArgs(sArgs); pModule->SetModPath(CDir::ChangeDir(CZNC::Get().GetCurPath(), sModPath)); push_back(pModule); @@ -1007,7 +1007,7 @@ void CModules::GetAvailableMods(set& ssMods, EModuleType eType) { CString sIgnoreRetMsg; if (GetModPathInfo(ModInfo, sName, sPath, sIgnoreRetMsg)) { - if (ModInfo.GetType() == eType) { + if (ModInfo.SupportsType(eType)) { ssMods.insert(ModInfo); } } diff --git a/Modules.h b/Modules.h index f1bc9d24a9..aa4011831d 100644 --- a/Modules.h +++ b/Modules.h @@ -70,7 +70,7 @@ template CModule* TModLoadGlobal(ModHandle p, if (dCoreVersion != VERSION) \ return false; \ Info.SetDescription(DESCRIPTION); \ - Info.SetType(TYPE); \ + Info.AddType(TYPE); \ LOADER; \ TModInfo(Info); \ return true; \ @@ -195,8 +195,16 @@ class CModInfo { return (GetName() < Info.GetName()); } - bool SupportsModule(EModuleType eType) { - return eType == m_eType; + bool SupportsType(EModuleType eType) { + return m_seType.find(eType) != m_seType.end(); + } + + void AddType(EModuleType eType) { + m_seType.insert(eType); + } + + EModuleType DefaultType() { + return *m_seType.begin(); } // Getters @@ -204,7 +212,6 @@ class CModInfo { const CString& GetPath() const { return m_sPath; } const CString& GetDescription() const { return m_sDescription; } const CString& GetWikiPage() const { return m_sWikiPage; } - EModuleType GetType() const { return m_eType; } ModLoader GetLoader() const { return m_fLoader; } GlobalModLoader GetGlobalLoader() const { return m_fGlobalLoader; } // !Getters @@ -214,13 +221,12 @@ class CModInfo { void SetPath(const CString& s) { m_sPath = s; } void SetDescription(const CString& s) { m_sDescription = s; } void SetWikiPage(const CString& s) { m_sWikiPage = s; } - void SetType(EModuleType eType) { m_eType = eType; } void SetLoader(ModLoader fLoader) { m_fLoader = fLoader; } void SetGlobalLoader(GlobalModLoader fGlobalLoader) { m_fGlobalLoader = fGlobalLoader; } // !Setters private: protected: - EModuleType m_eType; + set m_seType; CString m_sName; CString m_sPath; CString m_sDescription; diff --git a/modules/modperl.cpp b/modules/modperl.cpp index 7798620f82..c7804328bd 100644 --- a/modules/modperl.cpp +++ b/modules/modperl.cpp @@ -148,7 +148,7 @@ class CModPerl: public CModule { case Perl_Loaded: result = HALT; if (4 == ret) { - ModInfo.SetType(ModuleTypeUser); + ModInfo.AddType(ModuleTypeUser); ModInfo.SetDescription(PString(ST(2))); ModInfo.SetName(sModule); ModInfo.SetPath(PString(ST(1))); @@ -203,7 +203,7 @@ class CModPerl: public CModule { PUSH_STR(sName); PCALL("ZNC::Core::ModInfoByPath"); if (!SvTRUE(ERRSV) && ret == 2) { - ModInfo.SetType(ModuleTypeUser); + ModInfo.AddType(ModuleTypeUser); ModInfo.SetDescription(PString(ST(0))); ModInfo.SetName(sName); ModInfo.SetPath(sPath); diff --git a/modules/modpython.cpp b/modules/modpython.cpp index 6cba90d856..748b20ed63 100644 --- a/modules/modpython.cpp +++ b/modules/modpython.cpp @@ -135,10 +135,11 @@ class CModPython: public CModule { bSuccess = false; return HALT; } - PyObject* pyRes = PyObject_CallFunction(pyFunc, const_cast("ssNNN"), + PyObject* pyRes = PyObject_CallFunction(pyFunc, const_cast("ssiNNN"), sModName.c_str(), sArgs.c_str(), - (eType == ModuleTypeUser ? SWIG_NewInstanceObj(GetUser(), SWIG_TypeQuery("CUser*"), 0) : NULL), + (int)eType, + (eType == ModuleTypeUser ? SWIG_NewInstanceObj(GetUser(), SWIG_TypeQuery("CUser*"), 0) : Py_None), CPyRetString::wrap(sRetMsg), SWIG_NewInstanceObj(reinterpret_cast(this), SWIG_TypeQuery("CModule*"), 0)); if (!pyRes) { @@ -279,7 +280,7 @@ class CModPython: public CModule { return; } Py_CLEAR(pyRes); - if (x && ModInfo.GetType() == eType) { + if (x && ModInfo.SupportsType(eType)) { ssMods.insert(ModInfo); ssAlready.insert(sName); } diff --git a/modules/modpython/znc.py b/modules/modpython/znc.py index d102eb3393..f394ef9322 100644 --- a/modules/modpython/znc.py +++ b/modules/modpython/znc.py @@ -150,7 +150,7 @@ def __len__(self): class Module: description = '< Placeholder for a description >' - module_type = ModuleTypeUser + module_types = [ModuleTypeUser] wiki_page = '' @@ -423,7 +423,7 @@ def find_open(modname): return (None, None) -def load_module(modname, args, user, retmsg, modpython): +def load_module(modname, args, module_type, user, retmsg, modpython): '''Returns 0 if not found, 1 on loading error, 2 on success''' if re.search(r'[^a-zA-Z0-9_]', modname) is not None: retmsg.s = 'Module names can only contain letters, numbers and ' \ @@ -437,21 +437,38 @@ def load_module(modname, args, user, retmsg, modpython): pymodule.__file__, modname) return 1 cl = pymodule.__dict__[modname] + + if module_type not in cl.module_types: + retmsg.s = "Module [{}] doesn't support type.".format(modname) + return 1 + module = cl() - if user: + if module_type == ModuleTypeUser: module._cmod = CreateUserPyModule(user, modname, datapath, module, modpython) - else: + elif module_type == ModuleTypeGlobal: module._cmod = CreateGlobalPyModule(modname, datapath, module, modpython) + else: + retmsg.s = "Module [modpython] doesn't support module type." + return 1 + module.nv = ModuleNV(module._cmod) module.SetDescription(cl.description) module.SetArgs(args) module.SetModPath(pymodule.__file__) - module.SetType(cl.module_type) + module.SetType(module_type) - if user: + if module_type == ModuleTypeUser: + if not user: + retmsg.s = "Module [modpython] needs user for for ModuleTypeUser." + unload_module(module) + return 1 user.GetModules().push_back(module._cmod) - else: + elif module_type == ModuleTypeGlobal: CZNC.Get().GetModules().push_back(module._cmod) + else: + retmsg.s = "Module [modpython] doesn't support module type." + unload_module(module) + return 1 try: loaded = True @@ -511,7 +528,8 @@ def get_mod_info(modname, retmsg, modinfo): pymodule.__file__, modname) return 1 cl = pymodule.__dict__[modname] - modinfo.SetType(cl.module_type) + for module_type in cl.module_types: + modinfo.AddType(module_type) modinfo.SetDescription(cl.description) modinfo.SetWikiPage(cl.wiki_page) modinfo.SetName(modname) @@ -539,11 +557,13 @@ def get_mod_info_path(path, modname, modinfo): if modname not in pymodule.__dict__: return 0 cl = pymodule.__dict__[modname] - modinfo.SetType(cl.module_type) modinfo.SetDescription(cl.description) modinfo.SetWikiPage(cl.wiki_page) modinfo.SetName(modname) modinfo.SetPath(pymodule.__file__) + for module_type in cl.module_types: + modinfo.AddType(module_type) + return 1