mirror of
https://github.com/znc/znc.git
synced 2026-07-04 00:41:38 +02:00
Make modpython support different module types
This commit is contained in:
+96
-37
@@ -562,11 +562,20 @@ void CClient::UserCommand(CString& sLine) {
|
||||
}
|
||||
return;
|
||||
} else if (sCommand.Equals("LOADMOD") || sCommand.Equals("LOADMODULE")) {
|
||||
CString sMod;
|
||||
CString sArgs;
|
||||
EModuleType eType;
|
||||
CString sType = sLine.Token(1);
|
||||
CString sMod = sLine.Token(2);
|
||||
CString sArgs = sLine.Token(3, true);
|
||||
|
||||
sMod = sLine.Token(1);
|
||||
sArgs = sLine.Token(2, 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 <module> [args]");
|
||||
PutStatus("Usage: LoadMod [type] <module> [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 <module>");
|
||||
PutStatus("Usage: UnloadMod [type] <module>");
|
||||
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 <module> [args]");
|
||||
PutStatus("Usage: ReloadMod [type] <module> [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", "<module>");
|
||||
Table.SetCell("Arguments", "[type] <module>");
|
||||
Table.SetCell("Description", "Load a module");
|
||||
|
||||
Table.AddRow();
|
||||
Table.SetCell("Command", "UnloadMod");
|
||||
Table.SetCell("Arguments", "<module>");
|
||||
Table.SetCell("Arguments", "[type] <module>");
|
||||
Table.SetCell("Description", "Unload a module");
|
||||
|
||||
Table.AddRow();
|
||||
Table.SetCell("Command", "ReloadMod");
|
||||
Table.SetCell("Arguments", "<module>");
|
||||
Table.SetCell("Arguments", "[type] <module>");
|
||||
Table.SetCell("Description", "Reload a module");
|
||||
|
||||
if (m_pUser->IsAdmin()) {
|
||||
|
||||
+4
-4
@@ -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<CModInfo>& ssMods, EModuleType eType) {
|
||||
|
||||
CString sIgnoreRetMsg;
|
||||
if (GetModPathInfo(ModInfo, sName, sPath, sIgnoreRetMsg)) {
|
||||
if (ModInfo.GetType() == eType) {
|
||||
if (ModInfo.SupportsType(eType)) {
|
||||
ssMods.insert(ModInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ template<class M> CModule* TModLoadGlobal(ModHandle p,
|
||||
if (dCoreVersion != VERSION) \
|
||||
return false; \
|
||||
Info.SetDescription(DESCRIPTION); \
|
||||
Info.SetType(TYPE); \
|
||||
Info.AddType(TYPE); \
|
||||
LOADER; \
|
||||
TModInfo<CLASS>(Info); \
|
||||
return true; \
|
||||
@@ -195,8 +195,16 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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<EModuleType> m_seType;
|
||||
CString m_sName;
|
||||
CString m_sPath;
|
||||
CString m_sDescription;
|
||||
|
||||
+2
-2
@@ -148,7 +148,7 @@ public:
|
||||
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 @@ public:
|
||||
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);
|
||||
|
||||
@@ -135,10 +135,11 @@ public:
|
||||
bSuccess = false;
|
||||
return HALT;
|
||||
}
|
||||
PyObject* pyRes = PyObject_CallFunction(pyFunc, const_cast<char*>("ssNNN"),
|
||||
PyObject* pyRes = PyObject_CallFunction(pyFunc, const_cast<char*>("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<CModule*>(this), SWIG_TypeQuery("CModule*"), 0));
|
||||
if (!pyRes) {
|
||||
@@ -279,7 +280,7 @@ public:
|
||||
return;
|
||||
}
|
||||
Py_CLEAR(pyRes);
|
||||
if (x && ModInfo.GetType() == eType) {
|
||||
if (x && ModInfo.SupportsType(eType)) {
|
||||
ssMods.insert(ModInfo);
|
||||
ssAlready.insert(sName);
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ class ModuleNV(collections.MutableMapping):
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user