From: <ps...@us...> - 2010-07-07 16:01:24
|
Revision: 2071 http://znc.svn.sourceforge.net/znc/?rev=2071&view=rev Author: psychon Date: 2010-07-07 16:01:15 +0000 (Wed, 07 Jul 2010) Log Message: ----------- Add module calls for client CAPs This commit adds new module calls which make it possibly to announce new capabilities from a module. Thanks to DarthGandalf for the patch and for not going mad from my comments. :) Modified Paths: -------------- trunk/Client.cpp trunk/Client.h trunk/Modules.cpp trunk/Modules.h Modified: trunk/Client.cpp =================================================================== --- trunk/Client.cpp 2010-07-06 15:38:21 UTC (rev 2070) +++ trunk/Client.cpp 2010-07-07 16:01:15 UTC (rev 2071) @@ -783,33 +783,29 @@ CString sSubCmd = sLine.Token(1); if (sSubCmd.Equals("LS")) { - RespondCap("LS :userhost-in-names multi-prefix"); + SCString ssOfferCaps; + CZNC::Get().GetModules().OnClientCapLs(ssOfferCaps); + CString sRes; + for (SCString::iterator i = ssOfferCaps.begin(); i != ssOfferCaps.end(); ++i) { + sRes += *i + " "; + } + RespondCap("LS :" + sRes + "userhost-in-names multi-prefix"); m_bInCap = true; } else if (sSubCmd.Equals("END")) { m_bInCap = false; AuthUser(); } else if (sSubCmd.Equals("REQ")) { - bool bReqUHNames = false; - bool bReqNamesx = false; - bool bValueUHNames = false; - bool bValueNamesx = false; - VCString vsTokens; VCString::iterator it; sLine.Token(2, true).TrimPrefix_n(":").Split(" ", vsTokens, false); for (it = vsTokens.begin(); it != vsTokens.end(); ++it) { bool bVal = true; - if (it->TrimPrefix("-")) + CString sCap = *it; + if (sCap.TrimPrefix("-")) bVal = false; - if (*it == "multi-prefix") { - bReqNamesx = true; - bValueNamesx = bVal; - } else if (*it == "userhost-in-names") { - bReqUHNames = true; - bValueUHNames = bVal; - } else { + if ("multi-prefix" != sCap && "userhost-in-names" != sCap && !CZNC::Get().GetModules().IsClientCapSupported(sCap, bVal)) { // Some unsupported capability is requested RespondCap("NAK :" + sLine.Token(2, true).TrimPrefix_n(":")); return; @@ -817,17 +813,32 @@ } // All is fine, we support what was requested + for (it = vsTokens.begin(); it != vsTokens.end(); ++it) { + bool bVal = true; + if (it->TrimPrefix("-")) + bVal = false; + + if ("multi-prefix" == *it) { + m_bNamesx = bVal; + } else if ("userhost-in-names" == *it) { + m_bUHNames = bVal; + } else { + CZNC::Get().GetModules().OnClientCapRequest(this, *it, bVal); + } + + if (bVal) { + m_ssAcceptedCaps.insert(*it); + } else { + m_ssAcceptedCaps.erase(*it); + } + } + RespondCap("ACK :" + sLine.Token(2, true).TrimPrefix_n(":")); - if (bReqUHNames) - m_bUHNames = bValueUHNames; - if (bReqNamesx) - m_bNamesx = bValueNamesx; } else if (sSubCmd.Equals("LIST")) { CString sList = ""; - if (m_bNamesx) - sList += "multi-prefix "; - if (m_bUHNames) - sList += "userhost-in-names "; + for (SCString::iterator i = m_ssAcceptedCaps.begin(); i != m_ssAcceptedCaps.end(); ++i) { + sList += *i + " "; + } RespondCap("LIST :" + sList.TrimSuffix_n(" ")); } } Modified: trunk/Client.h =================================================================== --- trunk/Client.h 2010-07-06 15:38:21 UTC (rev 2070) +++ trunk/Client.h 2010-07-07 16:01:15 UTC (rev 2071) @@ -113,6 +113,8 @@ void PutModule(const CString& sModule, const CString& sLine); void PutModNotice(const CString& sModule, const CString& sLine); + bool IsCapEnabled(const CString& sCap) { return 1 == m_ssAcceptedCaps.count(sCap); } + virtual void ReadLine(const CString& sData); bool SendMotd(); void HelpUser(); @@ -143,6 +145,7 @@ CString m_sPass; CString m_sUser; CSmartPtr<CAuthBase> m_spAuth; + SCString m_ssAcceptedCaps; }; #endif // !_CLIENT_H Modified: trunk/Modules.cpp =================================================================== --- trunk/Modules.cpp 2010-07-06 15:38:21 UTC (rev 2070) +++ trunk/Modules.cpp 2010-07-07 16:01:15 UTC (rev 2071) @@ -503,6 +503,9 @@ CModule::EModRet CGlobalModule::OnLoginAttempt(CSmartPtr<CAuthBase> Auth) { return CONTINUE; } void CGlobalModule::OnFailedLogin(const CString& sUsername, const CString& sRemoteIP) {} CModule::EModRet CGlobalModule::OnUnknownUserRaw(CClient* pClient, CString& sLine) { return CONTINUE; } +void CGlobalModule::OnClientCapLs(SCString& ssCaps) {} +bool CGlobalModule::IsClientCapSupported(const CString& sCap, bool bState) { return false; } +void CGlobalModule::OnClientCapRequest(CClient* pClient, const CString& sCap, bool bState) {} CModules::CModules() { @@ -627,6 +630,42 @@ GLOBALMODHALTCHK(OnUnknownUserRaw(pClient, sLine)); } +void CGlobalModules::OnClientCapLs(SCString& ssCaps) { + GLOBALMODCALL(OnClientCapLs(ssCaps)); +} + +// Maybe create new macro for this? +bool CGlobalModules::IsClientCapSupported(const CString& sCap, bool bState) { + bool bResult = false; + for (unsigned int a = 0; a < size(); ++a) { + try { + CGlobalModule* pMod = (CGlobalModule*) (*this)[a]; + CClient* pOldClient = pMod->GetClient(); + pMod->SetClient(m_pClient); + if (m_pUser) { + CUser* pOldUser = pMod->GetUser(); + pMod->SetUser(m_pUser); + bResult |= pMod->IsClientCapSupported(sCap, bState); + pMod->SetUser(pOldUser); + } else { + // WTF? Is that possible? + bResult |= pMod->IsClientCapSupported(sCap, bState); + } + pMod->SetClient(pOldClient); + } catch (CModule::EModException e) { + if (CModule::UNLOAD == e) { + UnloadModule((*this)[a]->GetModName()); + } + } + } + return bResult; +} + +void CGlobalModules::OnClientCapRequest(CClient* pClient, const CString& sCap, bool bState) { + GLOBALMODCALL(OnClientCapRequest(pClient, sCap, bState)); +} + + CModule* CModules::FindModule(const CString& sModule) const { for (unsigned int a = 0; a < size(); a++) { if (sModule.Equals((*this)[a]->GetModName())) { Modified: trunk/Modules.h =================================================================== --- trunk/Modules.h 2010-07-06 15:38:21 UTC (rev 2070) +++ trunk/Modules.h 2010-07-07 16:01:15 UTC (rev 2071) @@ -959,6 +959,24 @@ * (Well, ok, m_pUser isn't known yet...) */ virtual EModRet OnUnknownUserRaw(CClient* pClient, CString& sLine); + + /** Called when a client told us CAP LS. Use ssCaps.insert("cap-name") + * for announcing capabilities which your module supports. + * @param pClient client which wants caps. + */ + virtual void OnClientCapLs(SCString& ssCaps); + /** Called only to check if your module supports turning on/off named capability. + * @param sCap name of capability. + * @param bState On or off, depending on which case is interesting for client. + * @return true if your module supports this capability in the specified state. + */ + virtual bool IsClientCapSupported(const CString& sCap, bool bState); + /** Called when we actually need to turn a capability on or off for a client. + * @param pClient client which requested this. + * @param sCap name of wanted capability. + * @param bState On or off, depending on which case client needs. + */ + virtual void OnClientCapRequest(CClient* pClient, const CString& sCap, bool bState); private: }; @@ -974,6 +992,9 @@ bool OnLoginAttempt(CSmartPtr<CAuthBase> Auth); void OnFailedLogin(const CString& sUsername, const CString& sRemoteIP); bool OnUnknownUserRaw(CClient* pClient, CString& sLine); + void OnClientCapLs(SCString& ssCaps); + bool IsClientCapSupported(const CString& sCap, bool bState); + void OnClientCapRequest(CClient* pClient, const CString& sCap, bool bState); private: }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |