diff --git a/Modules.cpp b/Modules.cpp index 063b2fee..f8364be4 100644 --- a/Modules.cpp +++ b/Modules.cpp @@ -106,8 +106,8 @@ const CString& CTimer::GetDescription() const { return m_sDescription; } CModule::CModule(void* pDLL, CUser* pUser, const CString& sModName) { m_pDLL = pDLL; - m_pZNC = pUser->GetZNC(); - m_pManager = pUser->GetManager(); + m_pZNC = (pUser) ? pUser->GetZNC() : NULL; + m_pManager = (pUser) ? pUser->GetManager() : NULL; m_pUser = pUser; m_sModName = sModName; LoadRegistry(); @@ -116,7 +116,7 @@ CModule::CModule(void* pDLL, CUser* pUser, const CString& sModName) { CModule::CModule(void* pDLL, CZNC* pZNC, const CString& sModName) { m_pDLL = pDLL; m_pZNC = pZNC; - m_pManager = &pZNC->GetManager(); + m_pManager = (pZNC) ? &pZNC->GetManager() : NULL; m_pUser = NULL; m_sModName = sModName; LoadRegistry(); @@ -134,6 +134,10 @@ void CModule::SetUser(CUser* pUser) { m_pUser = pUser; } void CModule::Unload() { throw UNLOAD; } bool CModule::LoadRegistry() { + if (!m_pZNC) { + return false; + } + CString sRegistryDir = m_pZNC->GetDataPath() + "/" + m_sModName; CUtils::MakeDir(sRegistryDir); CString sPrefix = (m_pUser) ? m_pUser->GetUserName() : ".global"; @@ -142,6 +146,10 @@ bool CModule::LoadRegistry() { } bool CModule::SaveRegistry() { + if (!m_pZNC) { + return false; + } + CString sRegistryDir = m_pZNC->GetDataPath() + "/" + m_sModName; CUtils::MakeDir(sRegistryDir); CString sPrefix = (m_pUser) ? m_pUser->GetUserName() : ".global"; @@ -530,12 +538,6 @@ bool CModules::LoadModule(const CString& sModule, const CString& sArgs, CUser* p #else sRetMsg = ""; - /* Assume global for now - if (!pUser) { - sRetMsg = "Unable to load module [" + sModule + "] Internal Error 1."; - return false; - }*/ - for (unsigned int a = 0; a < sModule.length(); a++) { if (((sModule[a] < '0') || (sModule[a] > '9')) && ((sModule[a] < 'a') || (sModule[a] > 'z')) && ((sModule[a] < 'A') || (sModule[a] > 'Z')) && (sModule[a] != '_')) { sRetMsg = "Unable to load module [" + sModule + "] module names can only be letters, numbers, or underscores."; @@ -577,7 +579,7 @@ bool CModules::LoadModule(const CString& sModule, const CString& sArgs, CUser* p return false; } - if (CModule::GetVersion() != Version()) { + if (CModule::GetCoreVersion() != Version()) { dlclose(p); sRetMsg = "Version mismatch, recompile this module."; throw CException(CException::EX_BadModVersion); @@ -718,26 +720,109 @@ CString CModules::FindModPath(const CString& sModule, CUser* pUser) { return (m_pZNC) ? m_pZNC->FindModPath(sModule) : ""; } +bool CModules::GetModInfo(CModInfo& ModInfo, const CString& sModule) { + for (unsigned int a = 0; a < sModule.length(); a++) { + const char& c = sModule[a]; + + if ((c < '0' || c > '9') && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && c != '_') { + return false; + } + } + + CString sModPath = FindModPath(sModule, NULL); + + if (sModPath.empty()) { + return false; + } + + unsigned int uDLFlags = RTLD_LAZY | RTLD_GLOBAL; + + void* p = dlopen((sModPath).c_str(), uDLFlags); + + if (!p) { + return false; + } + + typedef double (*dFP)(); + dFP Version = (dFP) dlsym(p, "GetVersion"); + + if (!Version) { + dlclose(p); + return false; + } + + typedef bool (*bFP)(); + bFP IsGlobal = (bFP) dlsym(p, "IsGlobal"); + + if (!IsGlobal) { + dlclose(p); + return false; + } + + typedef CModule* (*fp)(void*, CZNC*, const CString&); + fp Load = (fp) dlsym(p, "Load"); + + if (!Load) { + dlclose(p); + return false; + } + + ModInfo.SetGlobal(IsGlobal()); + ModInfo.SetName(sModule); + ModInfo.SetPath(sModPath); + dlclose(p); + + return true; +} + void CModules::GetAvailableMods(set& ssMods, CZNC* pZNC, bool bGlobal) { ssMods.clear(); unsigned int a = 0; CDir Dir; - Dir.FillByWildcard(pZNC->GetModPath(), "*.so"); - + Dir.FillByWildcard(pZNC->GetCurPath() + "/modules", "*.so"); for (a = 0; a < Dir.size(); a++) { CFile& File = *Dir[a]; - if ((File.GetShortName().Left(2).CaseCmp("g_") == 0) == bGlobal) { - ssMods.insert(CModInfo(File.GetShortName(), File.GetLongName(), false, bGlobal)); + CString sName = File.GetShortName(); + CModInfo ModInfo; + sName.RightChomp(3); + + if (GetModInfo(ModInfo, sName)) { + if (ModInfo.IsGlobal() == bGlobal) { + ModInfo.SetSystem(false); + ssMods.insert(ModInfo); + } + } + } + + Dir.FillByWildcard(pZNC->GetModPath(), "*.so"); + for (a = 0; a < Dir.size(); a++) { + CFile& File = *Dir[a]; + CString sName = File.GetShortName(); + CModInfo ModInfo; + sName.RightChomp(3); + + if (GetModInfo(ModInfo, sName)) { + if (ModInfo.IsGlobal() == bGlobal) { + ModInfo.SetSystem(false); + ssMods.insert(ModInfo); + } } } Dir.FillByWildcard(_MODDIR_, "*.so"); for (a = 0; a < Dir.size(); a++) { CFile& File = *Dir[a]; - if ((File.GetShortName().Left(2).CaseCmp("g_") == 0) == bGlobal) { - ssMods.insert(CModInfo(File.GetShortName(), File.GetLongName(), true, bGlobal)); + CString sName = File.GetShortName(); + CModInfo ModInfo; + sName.RightChomp(3); + + if (GetModInfo(ModInfo, sName)) { + if (ModInfo.IsGlobal() == bGlobal) { + ModInfo.SetSystem(true); + ssMods.insert(ModInfo); + } } } } diff --git a/Modules.h b/Modules.h index f820f2ae..1cea96cd 100644 --- a/Modules.h +++ b/Modules.h @@ -95,7 +95,7 @@ private: class CModInfo { public: - + CModInfo() {} CModInfo(const CString& sName, const CString& sPath, bool bSystem, bool bGlobal) { m_bSystem = bSystem; m_bGlobal = bGlobal; @@ -114,6 +114,13 @@ public: bool IsSystem() const { return m_bSystem; } bool IsGlobal() const { return m_bGlobal; } // !Getters + + // Setters + void SetName(const CString& s) { m_sName = s; } + void SetPath(const CString& s) { m_sPath = s; } + void SetSystem(bool b) { m_bSystem = b; } + void SetGlobal(bool b) { m_bGlobal = b; } + // !Setters private: protected: bool m_bSystem; @@ -186,7 +193,7 @@ public: virtual EModRet OnChanNotice(const CNick& Nick, CChan& Channel, CString& sMessage); void * GetDLL(); - static double GetVersion() { return VERSION; } + static double GetCoreVersion() { return VERSION; } virtual bool PutIRC(const CString& sLine); virtual bool PutUser(const CString& sLine); @@ -285,7 +292,8 @@ public: bool ReloadModule(const CString& sModule, const CString& sArgs, CUser* pUser, CString& sRetMsg); CString FindModPath(const CString& sModule, CUser* pUser = NULL); - static void GetAvailableMods(set& ssMods, CZNC* pZNC, bool bGlobal = false); + bool GetModInfo(CModInfo& ModInfo, const CString& sModule); + void GetAvailableMods(set& ssMods, CZNC* pZNC, bool bGlobal = false); protected: CZNC* m_pZNC; diff --git a/znc.cpp b/znc.cpp index f5dfd6d0..95ad580c 100644 --- a/znc.cpp +++ b/znc.cpp @@ -286,7 +286,7 @@ bool CZNC::WriteNewConfig(const CString& sConfig) { #ifdef _MODULES set ssGlobalMods; - CModules::GetAvailableMods(ssGlobalMods, this, true); + GetModules().GetAvailableMods(ssGlobalMods, this, true); if (ssGlobalMods.size()) { CUtils::PrintMessage(""); @@ -352,7 +352,7 @@ bool CZNC::WriteNewConfig(const CString& sConfig) { #ifdef _MODULES set ssUserMods; - CModules::GetAvailableMods(ssUserMods, this); + GetModules().GetAvailableMods(ssUserMods, this); if (ssUserMods.size()) { vsLines.push_back(""); @@ -365,10 +365,6 @@ bool CZNC::WriteNewConfig(const CString& sConfig) { const CModInfo& Info = *it; CString sName = Info.GetName(); - if (sName.Right(3).CaseCmp(".so") == 0) { - sName.RightChomp(3); - } - if (CUtils::GetBoolInput("Load " + CString((Info.IsSystem()) ? "system" : "local") + " module <\033[1m" + sName + "\033[22m>?", false)) { vsLines.push_back("\tLoadModule = " + sName); }