From 3dde793e62dd2c39e6109fcc2ddae1c622cedc16 Mon Sep 17 00:00:00 2001 From: prozacx Date: Sun, 22 May 2005 00:47:36 +0000 Subject: [PATCH] Added global module functionality git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@348 726aef4b-f618-498e-8847-2d620e286838 --- Chan.cpp | 12 ++--- IRCSock.cpp | 84 ++++++++++++----------------------- Modules.cpp | 122 +++++++++++++++++++++++++++++++++++++++++++-------- Modules.h | 57 ++++++++++++++++++++++-- User.cpp | 7 ++- User.h | 4 +- UserSock.cpp | 64 ++++++--------------------- main.h | 41 +++++++++++++++++ znc.cpp | 56 +++++++++++++++++++++++ znc.h | 4 ++ 10 files changed, 313 insertions(+), 138 deletions(-) diff --git a/Chan.cpp b/Chan.cpp index d254e5f5..51d0ed2b 100644 --- a/Chan.cpp +++ b/Chan.cpp @@ -168,7 +168,7 @@ void CChan::ModeChange(const CString& sModes, const CString& sOpNick) { #ifdef _MODULES if (pOpNick) { - m_pUser->GetModules().OnRawMode(*pOpNick, *this, sModeArg, sArgs); + VOIDMODULECALL(OnRawMode(*pOpNick, *this, sModeArg, sArgs)); } #endif @@ -208,19 +208,19 @@ void CChan::ModeChange(const CString& sModes, const CString& sOpNick) { #ifdef _MODULES if (uMode && pOpNick) { - m_pUser->GetModules().OnChanPermission(*pOpNick, *pNick, *this, uMode, bAdd, bNoChange); + VOIDMODULECALL(OnChanPermission(*pOpNick, *pNick, *this, uMode, bAdd, bNoChange)); if (uMode == CChan::M_Op) { if (bAdd) { - m_pUser->GetModules().OnOp(*pOpNick, *pNick, *this, bNoChange); + VOIDMODULECALL(OnOp(*pOpNick, *pNick, *this, bNoChange)); } else { - m_pUser->GetModules().OnDeop(*pOpNick, *pNick, *this, bNoChange); + VOIDMODULECALL(OnDeop(*pOpNick, *pNick, *this, bNoChange)); } } else if (uMode == CChan::M_Voice) { if (bAdd) { - m_pUser->GetModules().OnVoice(*pOpNick, *pNick, *this, bNoChange); + VOIDMODULECALL(OnVoice(*pOpNick, *pNick, *this, bNoChange)); } else { - m_pUser->GetModules().OnDevoice(*pOpNick, *pNick, *this, bNoChange); + VOIDMODULECALL(OnDevoice(*pOpNick, *pNick, *this, bNoChange)); } } } diff --git a/IRCSock.cpp b/IRCSock.cpp index 6e514277..68c62099 100644 --- a/IRCSock.cpp +++ b/IRCSock.cpp @@ -67,9 +67,12 @@ void CIRCSock::ReadLine(const CString& sData) { DEBUG_ONLY(cout << GetSockName() << " <- [" << sLine << "]" << endl); #ifdef _MODULES - if (m_pUser->GetModules().OnRaw(sLine)) { + CGlobalModules& GMods = m_pZNC->GetModules(); + GMods.SetUser(m_pUser); + if (GMods.OnRaw(sLine) || m_pUser->GetModules().OnRaw(sLine)) { return; } + GMods.SetUser(NULL); #endif if (strncasecmp(sLine.c_str(), "PING ", 5) == 0) { @@ -88,9 +91,9 @@ void CIRCSock::ReadLine(const CString& sData) { SetTimeout(900); // Now that we are connected, let nature take its course PutServ("WHO " + sNick); m_pZNC->GetManager().AddCron(new CAwayNickTimer(m_pUser)); -#ifdef _MODULES - m_pUser->GetModules().OnIRCConnected(); -#endif + + VOIDMODULECALL(OnIRCConnected()); + m_bAuthed = true; m_pUser->PutStatus("Connected!"); @@ -383,9 +386,8 @@ void CIRCSock::ReadLine(const CString& sData) { } else if (sNick.CaseCmp(m_pUser->GetNick()) == 0) { KeepNick(); } -#ifdef _MODULES - m_pUser->GetModules().OnNick(sNickMask, sNewNick, vFoundChans); -#endif + + VOIDMODULECALL(OnNick(sNickMask, sNewNick, vFoundChans)); if (!bIsVisible) { return; @@ -420,9 +422,7 @@ void CIRCSock::ReadLine(const CString& sData) { KeepNick(); } -#ifdef _MODULES - m_pUser->GetModules().OnQuit(Nick, sMessage, vFoundChans); -#endif + VOIDMODULECALL(OnQuit(Nick, sMessage, vFoundChans)); if (!bIsVisible) { return; @@ -440,9 +440,8 @@ void CIRCSock::ReadLine(const CString& sData) { CChan* pChan = m_pUser->FindChan(sChan); if (pChan) { pChan->AddNick(sNickMask); -#ifdef _MODULES - m_pUser->GetModules().OnJoin(sNickMask, *pChan); -#endif + VOIDMODULECALL(OnJoin(sNickMask, *pChan)); + if (pChan->IsDetached()) { return; } @@ -456,9 +455,7 @@ void CIRCSock::ReadLine(const CString& sData) { CChan* pChan = m_pUser->FindChan(sChan); if (pChan) { pChan->RemNick(sNick); -#ifdef _MODULES - m_pUser->GetModules().OnPart(sNickMask, *pChan); -#endif + VOIDMODULECALL(OnPart(sNickMask, *pChan)); } if (sNick.CaseCmp(GetNick()) == 0) { @@ -491,9 +488,7 @@ void CIRCSock::ReadLine(const CString& sData) { if (pChan) { pChan->RemNick(sKickedNick); -#ifdef _MODULES - m_pUser->GetModules().OnKick(sNickMask, sKickedNick, *pChan, sMsg); -#endif + VOIDMODULECALL(OnKick(sNickMask, sKickedNick, *pChan, sMsg)); } if (GetNick().CaseCmp(sKickedNick) == 0) { @@ -615,21 +610,13 @@ void CIRCSock::KeepNick() { } bool CIRCSock::OnCTCPReply(const CString& sNickMask, CString& sMessage) { -#ifdef _MODULES - if (m_pUser->GetModules().OnCTCPReply(sNickMask, sMessage)) { - return true; - } -#endif + MODULECALL(OnCTCPReply(sNickMask, sMessage)); return false; } bool CIRCSock::OnPrivCTCP(const CString& sNickMask, CString& sMessage) { -#ifdef _MODULES - if (m_pUser->GetModules().OnPrivCTCP(sNickMask, sMessage)) { - return true; - } -#endif + MODULECALL(OnPrivCTCP(sNickMask, sMessage)); if (sMessage.CaseCmp("VERSION") == 0) { if (!IsUserAttached()) { @@ -690,11 +677,8 @@ bool CIRCSock::OnPrivCTCP(const CString& sNickMask, CString& sMessage) { } bool CIRCSock::OnPrivNotice(const CString& sNickMask, CString& sMessage) { -#ifdef _MODULES - if (m_pUser->GetModules().OnPrivNotice(sNickMask, sMessage)) { - return true; - } -#endif + MODULECALL(OnPrivNotice(sNickMask, sMessage)); + if (!m_pUserSock) { // If the user is detached, add to the buffer m_QueryBuffer.AddLine(":" + sNickMask + " NOTICE ", " :" + sMessage); @@ -704,11 +688,8 @@ bool CIRCSock::OnPrivNotice(const CString& sNickMask, CString& sMessage) { } bool CIRCSock::OnPrivMsg(const CString& sNickMask, CString& sMessage) { -#ifdef _MODULES - if (m_pUser->GetModules().OnPrivMsg(sNickMask, sMessage)) { - return true; - } -#endif + MODULECALL(OnPrivMsg(sNickMask, sMessage)); + if (!m_pUserSock) { // If the user is detached, add to the buffer m_QueryBuffer.AddLine(":" + sNickMask + " PRIVMSG ", " :" + sMessage); @@ -720,11 +701,11 @@ bool CIRCSock::OnPrivMsg(const CString& sNickMask, CString& sMessage) { bool CIRCSock::OnChanCTCP(const CString& sNickMask, const CString& sChan, CString& sMessage) { CChan* pChan = m_pUser->FindChan(sChan); if (pChan) { -#ifdef _MODULES - if ((m_pUser->GetModules().OnChanCTCP(sNickMask, *pChan, sMessage)) || (pChan->IsDetached())) { + MODULECALL(OnChanCTCP(sNickMask, *pChan, sMessage)); + + if (pChan->IsDetached()) { return true; } -#endif } return false; @@ -733,11 +714,8 @@ bool CIRCSock::OnChanCTCP(const CString& sNickMask, const CString& sChan, CStrin bool CIRCSock::OnChanNotice(const CString& sNickMask, const CString& sChan, CString& sMessage) { CChan* pChan = m_pUser->FindChan(sChan); if (pChan) { -#ifdef _MODULES - if (m_pUser->GetModules().OnChanNotice(sNickMask, *pChan, sMessage)) { - return true; - } -#endif + MODULECALL(OnChanNotice(sNickMask, *pChan, sMessage)); + if ((pChan->KeepBuffer()) || (!m_pUserSock)) { pChan->AddBuffer(":" + sNickMask + " NOTICE " + sChan + " :" + sMessage); } @@ -749,11 +727,8 @@ bool CIRCSock::OnChanNotice(const CString& sNickMask, const CString& sChan, CStr bool CIRCSock::OnChanMsg(const CString& sNickMask, const CString& sChan, CString& sMessage) { CChan* pChan = m_pUser->FindChan(sChan); if (pChan) { -#ifdef _MODULES - if (m_pUser->GetModules().OnChanMsg(sNickMask, *pChan, sMessage)) { - return true; - } -#endif + MODULECALL(OnChanMsg(sNickMask, *pChan, sMessage)); + if ((pChan->KeepBuffer()) || (!m_pUserSock)) { pChan->AddBuffer(":" + sNickMask + " PRIVMSG " + sChan + " :" + sMessage); } @@ -863,10 +838,7 @@ void CIRCSock::Connected() { } void CIRCSock::Disconnected() { -#ifdef _MODULES - DEBUG_ONLY(cout << "OnIRCDisconnected()" << endl); - m_pUser->GetModules().OnIRCDisconnected(); -#endif + VOIDMODULECALL(OnIRCDisconnected()); DEBUG_ONLY(cout << GetSockName() << " == Disconnected()" << endl); m_pUser->PutStatus("Disconnected from IRC. Reconnecting..."); diff --git a/Modules.cpp b/Modules.cpp index 934f7969..13da3f4e 100644 --- a/Modules.cpp +++ b/Modules.cpp @@ -9,7 +9,14 @@ #define MODUNLOADCHK(func) \ for (unsigned int a = 0; a < size(); a++) { \ try { \ - (*this)[a]->func; \ + CModule* pMod = (*this)[a]; \ + if (m_pUser) { \ + pMod->SetUser(m_pUser); \ + pMod->func; \ + pMod->SetUser(NULL); \ + } else { \ + pMod->func; \ + } \ } catch (CModule::EModException e) { \ if (e == CModule::UNLOAD) { \ UnloadModule((*this)[a]->GetModName()); \ @@ -21,7 +28,15 @@ bool bHaltCore = false; \ for (unsigned int a = 0; a < size(); a++) { \ try { \ - CModule::EModRet e = (*this)[a]->func; \ + CModule* pMod = (*this)[a]; \ + CModule::EModRet e = CModule::CONTINUE; \ + if (m_pUser) { \ + pMod->SetUser(m_pUser); \ + e = pMod->func; \ + pMod->SetUser(NULL); \ + } else { \ + e = pMod->func; \ + } \ if (e == CModule::HALTMODS) { \ break; \ } else if (e == CModule::HALTCORE) { \ @@ -63,12 +78,22 @@ 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_pUser = pUser; m_sModName = sModName; LoadRegistry(); } +CModule::CModule(void* pDLL, CZNC* pZNC, const CString& sModName) { + m_pDLL = pDLL; + m_pZNC = pZNC; + m_pManager = &pZNC->GetManager(); + m_pUser = NULL; + m_sModName = sModName; + LoadRegistry(); +} + CModule::~CModule() { while (m_vTimers.size()) { RemTimer(m_vTimers[0]->GetName()); @@ -77,20 +102,23 @@ CModule::~CModule() { SaveRegistry(); } +void CModule::SetUser(CUser* pUser) { m_pUser = pUser; } void CModule::Unload() { throw UNLOAD; } bool CModule::LoadRegistry() { - CString sRegistryDir = m_pUser->GetDataPath() + "/" + m_sModName; + CString sRegistryDir = m_pZNC->GetDataPath() + "/" + m_sModName; CUtils::MakeDir(sRegistryDir); + CString sPrefix = (m_pUser) ? m_pUser->GetUserName() : ".global"; - return (m_mssRegistry.ReadFromDisk(sRegistryDir + "/" + m_pUser->GetUserName() + "-registry.txt", 0600) == MCString::MCS_SUCCESS); + return (m_mssRegistry.ReadFromDisk(sRegistryDir + "/" + sPrefix + "-registry.txt", 0600) == MCString::MCS_SUCCESS); } bool CModule::SaveRegistry() { - CString sRegistryDir = m_pUser->GetDataPath() + "/" + m_sModName; + CString sRegistryDir = m_pZNC->GetDataPath() + "/" + m_sModName; CUtils::MakeDir(sRegistryDir); + CString sPrefix = (m_pUser) ? m_pUser->GetUserName() : ".global"; - return (m_mssRegistry.WriteToDisk(sRegistryDir + "/" + m_pUser->GetUserName() + "-registry.txt", 0600) == MCString::MCS_SUCCESS); + return (m_mssRegistry.WriteToDisk(sRegistryDir + "/" + sPrefix + "-registry.txt", 0600) == MCString::MCS_SUCCESS); } bool CModule::SetNV(const CString & sName, const CString & sValue, bool bWriteToDisk) { @@ -113,7 +141,7 @@ CString CModule::GetNV(const CString & sName) { } bool CModule::DelNV(const CString & sName, bool bWriteToDisk) { - MCString::iterator it = m_mssRegistry.find( sName ); + MCString::iterator it = m_mssRegistry.find(sName); if (it != m_mssRegistry.end()) { m_mssRegistry.erase(it); @@ -271,14 +299,17 @@ bool CModule::PutStatus(const CString& sLine) { return (m_pUser) ? m_pUser->PutStatus(sLine) : false; } bool CModule::PutModule(const CString& sLine, const CString& sIdent, const CString& sHost) { - cerr << "PutModule [" << sLine << "]" << endl; return (m_pUser) ? m_pUser->PutUser(":" + GetModNick() + "!" + sIdent + "@" + sHost + " PRIVMSG " + m_pUser->GetCurNick() + " :" + sLine) : false; } bool CModule::PutModNotice(const CString& sLine, const CString& sIdent, const CString& sHost) { return (m_pUser) ? m_pUser->PutUser(":" + GetModNick() + "!" + sIdent + "@" + sHost + " NOTICE " + m_pUser->GetCurNick() + " :" + sLine) : false; } -CModules::CModules() {} +CModules::CModules(CZNC* pZNC) { + m_pZNC = pZNC; + m_pUser = NULL; +} + CModules::~CModules() {} void CModules::UnloadAll() { @@ -458,10 +489,11 @@ 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] != '_')) { @@ -475,22 +507,28 @@ bool CModules::LoadModule(const CString& sModule, const CString& sArgs, CUser* p return false; } - CString sModPath = pUser->FindModPath(sModule); + CString sModPath = FindModPath(sModule, pUser); if (sModPath.empty()) { sRetMsg = "Unable to find module [" + sModule + "]"; return false; } - void* p = dlopen((sModPath).c_str(), RTLD_LAZY); + unsigned int uDLFlags = RTLD_LAZY; + + if (!pUser) { + uDLFlags |= RTLD_GLOBAL; + } + + void* p = dlopen((sModPath).c_str(), uDLFlags); if (!p) { sRetMsg = "Unable to load module [" + sModule + "] [" + dlerror() + "]"; return false; } - typedef double (*fpp)(); - fpp Version = (fpp) dlsym(p, "GetVersion"); + typedef double (*dFP)(); + dFP Version = (dFP) dlsym(p, "GetVersion"); if (!Version) { dlclose(p); @@ -505,16 +543,50 @@ bool CModules::LoadModule(const CString& sModule, const CString& sArgs, CUser* p return false; } - typedef CModule* (*fp)(void*, CUser* pUser, const CString& sModName); - fp Load = (fp) dlsym(p, "Load"); + typedef bool (*bFP)(); + bFP IsGlobal = (bFP) dlsym(p, "IsGlobal"); - if (!Load) { + if (!IsGlobal) { dlclose(p); - sRetMsg = "Could not find Load() in module [" + sModule + "]"; + sRetMsg = "Could not find IsGlobal() in module [" + sModule + "]"; return false; } - CModule* pModule = Load(p, pUser, sModule); + bool bIsGlobal = IsGlobal(); + if ((pUser == NULL) != bIsGlobal) { + dlclose(p); + sRetMsg = "Module [" + sModule + "] is "; + sRetMsg += (bIsGlobal) ? "" : "not "; + sRetMsg += "a global module."; + return false; + } + + CModule* pModule = NULL; + + if (pUser) { + typedef CModule* (*fp)(void*, CUser* pUser, const CString& sModName); + fp Load = (fp) dlsym(p, "Load"); + + if (!Load) { + dlclose(p); + sRetMsg = "Could not find Load() in module [" + sModule + "]"; + return false; + } + + pModule = Load(p, pUser, sModule); + } else { + typedef CModule* (*fp)(void*, CZNC* pZNC, const CString& sModName); + fp Load = (fp) dlsym(p, "Load"); + + if (!Load) { + dlclose(p); + sRetMsg = "Could not find Load() in module [" + sModule + "]"; + return false; + } + + pModule = Load(p, m_pZNC, sModule); + } + push_back(pModule); if (!pModule->OnLoad(sArgs)) { @@ -593,6 +665,18 @@ bool CModules::ReloadModule(const CString& sModule, const CString& sArgs, CUser* return true; } +CString CModules::FindModPath(const CString& sModule, CUser* pUser) { + if (pUser) { + return pUser->FindModPath(sModule); + } + + if (!m_pZNC) { + DEBUG_ONLY(cerr << "CModules::FindModPath() m_pZNC is NULL!" << endl); + } + + return (m_pZNC) ? m_pZNC->FindModPath(sModule) : ""; +} + void CModules::GetAvailableMods(set& ssMods, CZNC* pZNC) { ssMods.clear(); diff --git a/Modules.h b/Modules.h index 73f3de50..b3354dc7 100644 --- a/Modules.h +++ b/Modules.h @@ -8,8 +8,33 @@ using std::vector; using std::set; -#define MODULEDEFS(CLASS) extern "C" { CModule* Load(void* p, CUser* pUser, const CString& sModName); void Unload(CModule* pMod); double GetVersion(); } double GetVersion() { return VERSION; } CModule* Load(void* p, CUser* pUser, const CString& sModName) { return new CLASS(p, pUser, sModName); } void Unload(CModule* pMod) { if (pMod) { delete pMod; } } -#define MODCONSTRUCTOR(CLASS) CLASS(void *pDLL, CUser* pUser, const CString& sModName) : CModule(pDLL, pUser, sModName) +// User Module Macros +#define MODCONSTRUCTOR(CLASS) \ + CLASS(void *pDLL, CUser* pUser, const CString& sModName) : CModule(pDLL, pUser, sModName) +#define MODULEDEFS(CLASS) \ + extern "C" { \ + bool IsGlobal() { return false; } \ + CModule* Load(void* p, CUser* pUser, const CString& sModName); \ + void Unload(CModule* pMod); double GetVersion(); } \ + double GetVersion() { return VERSION; } \ + CModule* Load(void* p, CUser* pUser, const CString& sModName) { return new CLASS(p, pUser, sModName); } \ + void Unload(CModule* pMod) { if (pMod) { delete pMod; } \ + } +// !User Module Macros + +// Global Module Macros +#define GLOBALMODCONSTRUCTOR(CLASS) \ + CLASS(void *pDLL, CZNC* pZNC, const CString& sModName) : CGlobalModule(pDLL, pZNC, sModName) +#define GLOBALMODULEDEFS(CLASS) \ + extern "C" { \ + bool IsGlobal() { return true; } \ + CGlobalModule* Load(void* p, CZNC* pZNC, const CString& sModName); \ + void Unload(CGlobalModule* pMod); double GetVersion(); } \ + double GetVersion() { return VERSION; } \ + CGlobalModule* Load(void* p, CZNC* pZNC, const CString& sModName) { return new CLASS(p, pZNC, sModName); } \ + void Unload(CGlobalModule* pMod) { if (pMod) { delete pMod; } \ + } +// !Global Module Macros // Forward Declarations class CZNC; @@ -97,6 +122,7 @@ protected: class CModule { public: CModule(void* pDLL, CUser* pUser, const CString& sModName); + CModule(void* pDLL, CZNC* pZNC, const CString& sModName); virtual ~CModule(); typedef enum { @@ -110,6 +136,7 @@ public: UNLOAD } EModException; + void SetUser(CUser* pUser); void Unload(); virtual CString GetDescription(); @@ -191,6 +218,7 @@ protected: void* m_pDLL; TSocketManager* m_pManager; CUser* m_pUser; + CZNC* m_pZNC; CString m_sModName; private: MCString m_mssRegistry; //!< way to save name/value pairs. Note there is no encryption involved in this @@ -198,9 +226,11 @@ private: class CModules : public vector { public: - CModules(); + CModules(CZNC* pZNC); virtual ~CModules(); + void SetUser(CUser* pUser) { m_pUser = pUser; } + void UnloadAll(); virtual bool OnLoad(const CString& sArgs); // Return false to abort @@ -250,8 +280,29 @@ public: bool UnloadModule(const CString& sModule); bool UnloadModule(const CString& sModule, CString& sRetMsg); 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); + +private: + CZNC* m_pZNC; + CUser* m_pUser; +}; + +class CGlobalModule : public CModule { +public: + CGlobalModule(void* pDLL, CZNC* pZNC, const CString& sModName) : CModule(pDLL, pZNC, sModName) {} + virtual ~CGlobalModule() {} + +private: +}; + +class CGlobalModules : public CModules { +public: + CGlobalModules(CZNC* pZNC) : CModules(pZNC) {} + virtual ~CGlobalModules() {} + +private: }; #endif // !_MODULES_H diff --git a/User.cpp b/User.cpp index 1cddc317..7bfa51b8 100644 --- a/User.cpp +++ b/User.cpp @@ -16,6 +16,9 @@ CUser::CUser(const CString& sUserName, CZNC* pZNC) { m_sRealName = sUserName; m_uServerIdx = 0; m_pZNC = pZNC; +#ifdef _MODULES + m_pModules = new CModules(pZNC); +#endif m_bPassHashed = false; m_bUseClientIP = false; m_bKeepNick = false; @@ -29,7 +32,7 @@ CUser::CUser(const CString& sUserName, CZNC* pZNC) { CUser::~CUser() { #ifdef _MODULES - m_Modules.UnloadAll(); + delete m_pModules; #endif for (unsigned int a = 0; a < m_vServers.size(); a++) { delete m_vServers[a]; @@ -42,7 +45,7 @@ CUser::~CUser() { bool CUser::OnBoot() { #ifdef _MODULES - return m_Modules.OnBoot(); + return GetModules().OnBoot(); #endif return true; } diff --git a/User.h b/User.h index 00efd96c..f7d12174 100644 --- a/User.h +++ b/User.h @@ -41,7 +41,7 @@ public: #ifdef _MODULES // Modules - CModules& GetModules() { return m_Modules; } + CModules& GetModules() { return *m_pModules; } // !Modules #endif @@ -149,7 +149,7 @@ protected: unsigned int m_uBufferCount; #ifdef _MODULES - CModules m_Modules; + CModules* m_pModules; #endif }; diff --git a/UserSock.cpp b/UserSock.cpp index f90250c9..aae666f6 100644 --- a/UserSock.cpp +++ b/UserSock.cpp @@ -16,13 +16,9 @@ void CUserSock::ReadLine(const CString& sData) { DEBUG_ONLY(cout << GetSockName() << " <- [" << sLine << "]" << endl); -#ifdef _MODULES if (m_bAuthed) { - if ((m_pUser) && (m_pUser->GetModules().OnUserRaw(sLine))) { - return; - } + MODULECALLRET(OnUserRaw(sLine)); } -#endif CString sCommand = sLine.Token(0); @@ -151,9 +147,12 @@ void CUserSock::ReadLine(const CString& sData) { CString sModule = sTarget; sModule.LeftChomp(m_pUser->GetStatusPrefix().length()); - CModule* pModule = m_pUser->GetModules().FindModule(sModule); + CModule* pModule = m_pUser->GetZNC()->GetModules().FindModule(sModule); + if (pModule) { pModule->OnModNotice(sMsg); + } else if ((pModule = m_pUser->GetModules().FindModule(sModule))) { + pModule->OnModNotice(sMsg); } else { PutStatus("No such module [" + sModule + "]"); } @@ -178,15 +177,11 @@ void CUserSock::ReadLine(const CString& sData) { sCTCP.LeftChomp(); sCTCP.RightChomp(); - if ((m_pUser) && (m_pUser->GetModules().OnUserCTCPReply(sTarget, sCTCP))) { - return; - } + MODULECALLRET(OnUserCTCPReply(sTarget, sCTCP)); sMsg = "\001" + sCTCP + "\001"; } else { - if ((m_pUser) && (m_pUser->GetModules().OnUserNotice(sTarget, sMsg))) { - return; - } + MODULECALLRET(OnUserNotice(sTarget, sMsg)); } #endif @@ -249,11 +244,7 @@ void CUserSock::ReadLine(const CString& sData) { m_pUser->GetFile(GetNick(), CUtils::GetIP(uLongIP), uPort, sLocalFile, uFileSize); } } else { -#ifdef _MODULES - if ((m_pUser) && (m_pUser->GetModules().OnDCCUserSend(sTarget, uLongIP, uPort, sFile, uFileSize))) { - return; - } -#endif + MODULECALLRET(OnDCCUserSend(sTarget, uLongIP, uPort, sFile, uFileSize)); } } else { unsigned short uBNCPort = CDCCBounce::DCCRequest(sTarget, uLongIP, uPort, sFile, false, m_pUser, (m_pIRCSock) ? m_pIRCSock->GetLocalIP() : GetLocalIP(), ""); @@ -315,22 +306,13 @@ void CUserSock::ReadLine(const CString& sData) { return; } -#ifdef _MODULES - if ((m_pUser) && (m_pUser->GetModules().OnUserCTCP(sTarget, sCTCP))) { - return; - } -#endif - + MODULECALLRET(OnUserCTCP(sTarget, sCTCP)); PutIRC("PRIVMSG " + sTarget + " :\001" + sCTCP + "\001"); return; } if ((m_pUser) && (sTarget.CaseCmp(CString(m_pUser->GetStatusPrefix() + "status")) == 0)) { -#ifdef _MODULES - if ((m_pUser) && (m_pUser->GetModules().OnStatusCommand(sMsg))) { - return; - } -#endif + MODULECALLRET(OnStatusCommand(sMsg)); UserCommand(sMsg); return; } @@ -358,11 +340,7 @@ void CUserSock::ReadLine(const CString& sData) { pChan->AddBuffer(":" + GetNickMask() + " PRIVMSG " + sTarget + " :" + sMsg); } -#ifdef _MODULES - if ((m_pUser) && (m_pUser->GetModules().OnUserMsg(sTarget, sMsg))) { - return; - } -#endif + MODULECALLRET(OnUserMsg(sTarget, sMsg)); PutIRC("PRIVMSG " + sTarget + " :" + sMsg); return; } @@ -524,15 +502,7 @@ void CUserSock::UserCommand(const CString& sLine) { Table.SetCell("Name", pChan->GetPermStr() + pChan->GetName()); Table.SetCell("Status", ((vChans[a]->IsOn()) ? ((vChans[a]->IsDetached()) ? "Detached" : "Joined") : "Trying")); Table.SetCell("Buf", CString((pChan->KeepBuffer()) ? "*" : "") + CString::ToString(pChan->GetBufferCount())); - - CString sModes = pChan->GetModeString(); - /*unsigned int uLimit = pChan->GetLimit(); - const CString& sKey = pChan->GetKey(); - - if (uLimit) { sModes += " " + CString::ToString(uLimit); } - if (!sKey.empty()) { sModes += " " + sKey; }*/ - - Table.SetCell("Modes", sModes); + Table.SetCell("Modes", pChan->GetModeString()); Table.SetCell("Users", CString::ToString(pChan->GetNickCount())); for (unsigned int b = 0; b < sPerms.size(); b++) { @@ -964,9 +934,7 @@ void CUserSock::AuthUser() { pIRCSock->UserConnected(this); } -#ifdef _MODULES - m_pUser->GetModules().OnUserAttached(); -#endif + VOIDMODULECALL(OnUserAttached()); } } @@ -985,11 +953,7 @@ void CUserSock::Disconnected() { m_pIRCSock = NULL; } -#ifdef _MODULES - if (m_pUser) { - m_pUser->GetModules().OnUserDetached(); - } -#endif + VOIDMODULECALL(OnUserDetached()); } void CUserSock::IRCConnected(CIRCSock* pIRCSock) { diff --git a/main.h b/main.h index 8d8f6cff..c06682c6 100644 --- a/main.h +++ b/main.h @@ -5,6 +5,47 @@ #define _MODDIR_ "/usr/share/znc" #endif +#ifdef _MODULES +#define VOIDMODULECALL(func) \ + if (m_pUser) { \ + CGlobalModules& GMods = m_pUser->GetZNC()->GetModules(); \ + GMods.SetUser(m_pUser); \ + GMods.func; \ + m_pUser->GetModules().func; \ + GMods.SetUser(NULL); \ + } +#else +#define VOIDMODULECALL(func) +#endif + +#ifdef _MODULES +#define MODULECALLRET(func) \ + if (m_pUser) { \ + CGlobalModules& GMods = m_pUser->GetZNC()->GetModules(); \ + GMods.SetUser(m_pUser); \ + if (GMods.func || m_pUser->GetModules().func) { \ + return; \ + } \ + GMods.SetUser(NULL); \ + } +#else +#define MODULECALL(func) +#endif + +#ifdef _MODULES +#define MODULECALL(func) \ + if (m_pUser) { \ + CGlobalModules& GMods = m_pUser->GetZNC()->GetModules(); \ + GMods.SetUser(m_pUser); \ + if (GMods.func || m_pUser->GetModules().func) { \ + return true; \ + } \ + GMods.SetUser(NULL); \ + } +#else +#define MODULECALL(func) +#endif + #define VERSION 0.036 #ifndef CS_STRING diff --git a/znc.cpp b/znc.cpp index 2ad45332..747d9dc3 100644 --- a/znc.cpp +++ b/znc.cpp @@ -14,6 +14,7 @@ #endif CZNC::CZNC() { + m_pModules = new CGlobalModules(this); m_uListenPort = 0; m_bISpoofLocked = false; m_sISpoofFormat = "global { reply \"%\" }"; @@ -21,6 +22,8 @@ CZNC::CZNC() { CZNC::~CZNC() { #ifdef _MODULES + delete m_pModules; + for (map::iterator a = m_msUsers.begin(); a != m_msUsers.end(); a++) { a->second->GetModules().UnloadAll(); } @@ -43,6 +46,10 @@ CString CZNC::GetTag(bool bIncludeVersion) { } bool CZNC::OnBoot() { + if (!GetModules().OnBoot()) { + return false; + } + for (map::iterator it = m_msUsers.begin(); it != m_msUsers.end(); it++) { if (!it->second->OnBoot()) { return false; @@ -534,6 +541,7 @@ bool CZNC::ParseConfig(const CString& sConfig) { } pUser = new CUser(sValue, this); + CUtils::PrintMessage("Loading user [" + sValue + "]"); bAutoCycle = true; if (!sStatusPrefix.empty()) { @@ -671,6 +679,9 @@ bool CZNC::ParseConfig(const CString& sConfig) { try { bool bModRet = pUser->GetModules().LoadModule(sModName, sArgs, pUser, sModRet); CUtils::PrintStatus(bModRet, (bModRet) ? "" : sModRet); + if (!bModRet) { + return false; + } } catch (CException e) { CUtils::PrintStatus(false, sModRet); return false; @@ -742,6 +753,27 @@ bool CZNC::ParseConfig(const CString& sConfig) { CUtils::PrintStatus(true); + continue; + } else if (sName.CaseCmp("LoadModule") == 0) { + CString sModName = sValue.Token(0); + CUtils::PrintAction("Loading Global Module [" + sModName + "]"); +#ifdef _MODULES + CString sModRet; + CString sArgs = sValue.Token(1, true); + + try { + bool bModRet = GetModules().LoadModule(sModName, sArgs, NULL, sModRet); + CUtils::PrintStatus(bModRet, (bModRet) ? "" : sModRet); + if (!bModRet) { + return false; + } + } catch (CException e) { + CUtils::PrintStatus(false, sModRet); + return false; + } +#else + CUtils::PrintStatus(false, "Modules are not enabled."); +#endif continue; } else if (sName.CaseCmp("ISpoofFormat") == 0) { m_sISpoofFormat = sValue; @@ -781,3 +813,27 @@ bool CZNC::ParseConfig(const CString& sConfig) { return true; } + +CString CZNC::FindModPath(const CString& sModule) const { + CString sModPath = GetCurPath() + "/modules/" + sModule; + sModPath += (sModule.find(".") == CString::npos) ? ".so" : ""; + + if (!CFile::Exists(sModPath)) { + DEBUG_ONLY(cout << "[" << sModPath << "] Not found..." << endl); + sModPath = GetModPath() + "/" + sModule; + sModPath += (sModule.find(".") == CString::npos) ? ".so" : ""; + + if (!CFile::Exists(sModPath)) { + DEBUG_ONLY(cout << "[" << sModPath << "] Not found..." << endl); + sModPath = _MODDIR_ + CString("/") + sModule; + sModPath += (sModule.find(".") == CString::npos) ? ".so" : ""; + + if (!CFile::Exists(sModPath)) { + DEBUG_ONLY(cout << "[" << sModPath << "] Not found... giving up!" << endl); + return ""; + } + } + } + + return sModPath; +} diff --git a/znc.h b/znc.h index e2c4afd6..0b969cc1 100644 --- a/znc.h +++ b/znc.h @@ -3,6 +3,7 @@ #include "main.h" #include "FileUtils.h" +#include "Modules.h" #include using std::map; @@ -28,9 +29,11 @@ public: CString GetConfigPath(const CString& sConfigFile); bool WriteNewConfig(const CString& sConfig); static CString GetTag(bool bIncludeVersion = true); + CString FindModPath(const CString& sModule) const; // Getters TSocketManager& GetManager() { return m_Manager; } + CGlobalModules& GetModules() { return *m_pModules; } unsigned int GetListenPort() const { return m_uListenPort; } const CString& GetCurPath() const { if (!CFile::Exists(m_sCurPath)) { CUtils::MakeDir(m_sCurPath); } return m_sCurPath; } const CString& GetDLPath() const { if (!CFile::Exists(m_sDLPath)) { CUtils::MakeDir(m_sDLPath); } return m_sDLPath; } @@ -75,6 +78,7 @@ protected: bool m_bISpoofLocked; bool m_bSSL; map::iterator m_itUserIter; // This needs to be reset to m_msUsers.begin() if anything is added or removed to the map + CGlobalModules* m_pModules; }; #endif // !_ZNC_H