diff --git a/include/znc/Modules.h b/include/znc/Modules.h index a12095c5..24185535 100644 --- a/include/znc/Modules.h +++ b/include/znc/Modules.h @@ -764,6 +764,19 @@ public: */ virtual EModRet OnTimerAutoJoin(CChan& Channel); + /** This module hook is called when a network is being added. + * @param Network The new IRC network. + * @param sErrorRet A message that may be displayed to the user if + * the module stops adding the network. + * @return See CModule::EModRet. + */ + virtual EModRet OnAddNetwork(CIRCNetwork& Network, CString& sErrorRet); + /** This module hook is called when a network is deleted. + * @param Network The IRC network which is going to be deleted. + * @return See CModule::EModRet. + */ + virtual EModRet OnDeleteNetwork(CIRCNetwork& Network); + ModHandle GetDLL() { return m_pDLL; } static double GetCoreVersion() { return VERSION; } @@ -1105,6 +1118,9 @@ public: bool OnTopic(CNick& Nick, CChan& Channel, CString& sTopic); bool OnTimerAutoJoin(CChan& Channel); + bool OnAddNetwork(CIRCNetwork& Network, CString& sErrorRet); + bool OnDeleteNetwork(CIRCNetwork& Network); + bool OnServerCapAvailable(const CString& sCap); bool OnServerCapResult(const CString& sCap, bool bSuccess); diff --git a/include/znc/User.h b/include/znc/User.h index ca482824..1a5cee88 100644 --- a/include/znc/User.h +++ b/include/znc/User.h @@ -71,7 +71,7 @@ public: // !Modules // Networks - CIRCNetwork* AddNetwork(const CString &sNetwork); + CIRCNetwork* AddNetwork(const CString &sNetwork, CString& sErrorRet); bool DeleteNetwork(const CString& sNetwork); bool AddNetwork(CIRCNetwork *pNetwork); void RemoveNetwork(CIRCNetwork *pNetwork); diff --git a/modules/controlpanel.cpp b/modules/controlpanel.cpp index f1fdcf81..e3101d0a 100644 --- a/modules/controlpanel.cpp +++ b/modules/controlpanel.cpp @@ -741,10 +741,11 @@ class CAdminMod : public CModule { return; } - if (pUser->AddNetwork(sNetwork)) { + CString sNetworkAddError; + if (pUser->AddNetwork(sNetwork, sNetworkAddError)) { PutModule("Network [" + sNetwork + "] added for user [" + pUser->GetUserName() + "]."); } else { - PutModule("Network [" + sNetwork + "] could not be added for user [" + pUser->GetUserName() + "]."); + PutModule("Network [" + sNetwork + "] could not be added for user [" + pUser->GetUserName() + "]: " + sNetworkAddError); } } diff --git a/modules/webadmin.cpp b/modules/webadmin.cpp index 7cab4f82..ae3ad3ee 100644 --- a/modules/webadmin.cpp +++ b/modules/webadmin.cpp @@ -861,9 +861,10 @@ public: WebSock.PrintErrorPage("Network name should be alphanumeric"); return true; } - pNetwork = pUser->AddNetwork(sName); + CString sNetworkAddError; + pNetwork = pUser->AddNetwork(sName, sNetworkAddError); if (!pNetwork) { - WebSock.PrintErrorPage("Network [" + sName.Token(0) + "] already exists"); + WebSock.PrintErrorPage(sNetworkAddError); return true; } } diff --git a/src/ClientCommand.cpp b/src/ClientCommand.cpp index 050fe782..3b4f7825 100644 --- a/src/ClientCommand.cpp +++ b/src/ClientCommand.cpp @@ -482,11 +482,12 @@ void CClient::UserCommand(CString& sLine) { return; } - if (m_pUser->AddNetwork(sNetwork)) { + CString sNetworkAddError; + if (m_pUser->AddNetwork(sNetwork, sNetworkAddError)) { PutStatus("Network added. Use /znc JumpNetwork " + sNetwork + ", or connect to ZNC with username " + m_pUser->GetUserName() + "/" + sNetwork + " (instead of just " + m_pUser->GetUserName() + ") to connect to it."); } else { PutStatus("Unable to add that network"); - PutStatus("Perhaps that network is already added"); + PutStatus(sNetworkAddError); } } else if (sCommand.Equals("DELNETWORK")) { CString sNetwork = sLine.Token(1); @@ -614,10 +615,11 @@ void CClient::UserCommand(CString& sLine) { fOldNVFile.Copy(sNewModPath + "/.registry"); } - CIRCNetwork* pNewNetwork = pNewUser->AddNetwork(sNewNetwork); + CString sNetworkAddError; + CIRCNetwork* pNewNetwork = pNewUser->AddNetwork(sNewNetwork, sNetworkAddError); if (!pNewNetwork) { - PutStatus("Error adding network."); + PutStatus("Error adding network:" + sNetworkAddError); return; } diff --git a/src/Modules.cpp b/src/Modules.cpp index d8f24266..e25de03c 100644 --- a/src/Modules.cpp +++ b/src/Modules.cpp @@ -600,6 +600,8 @@ CModule::EModRet CModule::OnPrivNotice(CNick& Nick, CString& sMessage) { return CModule::EModRet CModule::OnChanNotice(CNick& Nick, CChan& Channel, CString& sMessage) { return CONTINUE; } CModule::EModRet CModule::OnTopic(CNick& Nick, CChan& Channel, CString& sTopic) { return CONTINUE; } CModule::EModRet CModule::OnTimerAutoJoin(CChan& Channel) { return CONTINUE; } +CModule::EModRet CModule::OnAddNetwork(CIRCNetwork& Network, CString& sErrorRet) { return CONTINUE; } +CModule::EModRet CModule::OnDeleteNetwork(CIRCNetwork& Network) { return CONTINUE; } bool CModule::OnServerCapAvailable(const CString& sCap) { return false; } void CModule::OnServerCapResult(const CString& sCap, bool bSuccess) {} @@ -758,6 +760,8 @@ bool CModules::OnPrivNotice(CNick& Nick, CString& sMessage) { MODHALTCHK(OnPrivN bool CModules::OnChanNotice(CNick& Nick, CChan& Channel, CString& sMessage) { MODHALTCHK(OnChanNotice(Nick, Channel, sMessage)); } bool CModules::OnTopic(CNick& Nick, CChan& Channel, CString& sTopic) { MODHALTCHK(OnTopic(Nick, Channel, sTopic)); } bool CModules::OnTimerAutoJoin(CChan& Channel) { MODHALTCHK(OnTimerAutoJoin(Channel)); } +bool CModules::OnAddNetwork(CIRCNetwork& Network, CString& sErrorRet) { MODHALTCHK(OnAddNetwork(Network, sErrorRet)); } +bool CModules::OnDeleteNetwork(CIRCNetwork& Network) { MODHALTCHK(OnDeleteNetwork(Network)); } bool CModules::OnStatusCommand(CString& sCommand) { MODHALTCHK(OnStatusCommand(sCommand)); } bool CModules::OnModCommand(const CString& sCommand) { MODUNLOADCHK(OnModCommand(sCommand)); return false; } bool CModules::OnModNotice(const CString& sMessage) { MODUNLOADCHK(OnModNotice(sMessage)); return false; } diff --git a/src/User.cpp b/src/User.cpp index 78730d93..df850ae4 100644 --- a/src/User.cpp +++ b/src/User.cpp @@ -357,7 +357,8 @@ bool CUser::ParseConfig(CConfig* pConfig, CString& sError) { if (pConfig->FindStringVector("server", vsList, false) || pConfig->FindStringVector("chan", vsList, false) || pConfig->FindSubConfig("chan", subConf, false)) { CIRCNetwork *pNetwork = FindNetwork("default"); if (!pNetwork) { - pNetwork = AddNetwork("default"); + CString sErrorDummy; + pNetwork = AddNetwork("default", sErrorDummy); } if (pNetwork) { @@ -459,12 +460,23 @@ bool CUser::ParseConfig(CConfig* pConfig, CString& sError) { return true; } -CIRCNetwork* CUser::AddNetwork(const CString &sNetwork) { +CIRCNetwork* CUser::AddNetwork(const CString &sNetwork, CString& sErrorRet) { if (!CIRCNetwork::IsValidNetwork(sNetwork) || FindNetwork(sNetwork)) { + sErrorRet = "Network [" + sNetwork.Token(0) + "] already exists"; return NULL; } - return new CIRCNetwork(this, sNetwork); + CIRCNetwork* pNetwork = new CIRCNetwork(this, sNetwork); + + bool bCancel = false; + USERMODULECALL(OnAddNetwork(*pNetwork, sErrorRet), this, NULL, &bCancel); + if(bCancel) { + RemoveNetwork(pNetwork); + delete pNetwork; + return NULL; + } + + return pNetwork; } bool CUser::AddNetwork(CIRCNetwork *pNetwork) { @@ -490,8 +502,12 @@ bool CUser::DeleteNetwork(const CString& sNetwork) { CIRCNetwork *pNetwork = FindNetwork(sNetwork); if (pNetwork) { - delete pNetwork; - return true; + bool bCancel = false; + USERMODULECALL(OnDeleteNetwork(*pNetwork), this, NULL, &bCancel); + if (!bCancel) { + delete pNetwork; + return true; + } } return false;