diff --git a/modules/data/webadmin/tmpl/add_edit_chan.tmpl b/modules/data/webadmin/tmpl/add_edit_chan.tmpl index a9f6920a..f0d5e001 100644 --- a/modules/data/webadmin/tmpl/add_edit_chan.tmpl +++ b/modules/data/webadmin/tmpl/add_edit_chan.tmpl @@ -5,6 +5,7 @@
+

Channel Info

diff --git a/modules/data/webadmin/tmpl/add_edit_network.tmpl b/modules/data/webadmin/tmpl/add_edit_network.tmpl new file mode 100644 index 00000000..942ad87b --- /dev/null +++ b/modules/data/webadmin/tmpl/add_edit_network.tmpl @@ -0,0 +1,108 @@ + + +
+ +
+ + + + +

Network Info

+
+
+
+
Servers:
+
+
One server per line, host [[+]port] [password] +
+
+
+
+
+ +
+

Channels

+ + You will be able to add + modify channels here after you created the network.
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
[Add]SaveNameCurModesDefModesBufferCountOptions  <- Add a channel (opens in same page)  
+ + [Edit] [Del] + checked="checked" />
+
+
+ +
+ +
+

Modules

+
+
+ + + + + + + + + + + + + + + + + + + +
NameArgumentsDescription
+ checked="checked" disabled="disabled" /> + + +
+
+
+
+ +
+ +
+
+ + diff --git a/modules/data/webadmin/tmpl/add_edit_user.tmpl b/modules/data/webadmin/tmpl/add_edit_user.tmpl index ab7c1310..562a5b85 100644 --- a/modules/data/webadmin/tmpl/add_edit_user.tmpl +++ b/modules/data/webadmin/tmpl/add_edit_user.tmpl @@ -99,15 +99,6 @@
-
-
Servers:
-
-
One server per line, host [[+]port] [password] -
-
-
Active:
checked="checked" /> @@ -119,6 +110,42 @@
+
+

Networks

+ + You will be able to add + modify networks here after you created the user.
+ +
+
+ + + + + + + + + + + + + + + + + + + + +
[Add]Name  <- Add a network (opens in same page)  
+ + [Edit] [Del] +
+
+
+ +
+

Modules

@@ -151,52 +178,6 @@
-
-

Channels

- - You will be able to add + modify channels here after you created the user.
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[Add]SaveNameCurModesDefModesBufferCountOptions  <- Add a channel (opens in same page)  
- - [Edit] [Del] - checked="checked" />
-
-
- -
-

Default Channel Settings

diff --git a/modules/data/webadmin/tmpl/listusers.tmpl b/modules/data/webadmin/tmpl/listusers.tmpl index 157746b8..2e3ef583 100644 --- a/modules/data/webadmin/tmpl/listusers.tmpl +++ b/modules/data/webadmin/tmpl/listusers.tmpl @@ -11,9 +11,8 @@ Action Username + Networks Clients - Current Server - IRC Nick @@ -27,9 +26,8 @@ + - - diff --git a/modules/data/webadmin/tmpl/traffic.tmpl b/modules/data/webadmin/tmpl/traffic.tmpl index ca6f9a8e..368f09b4 100644 --- a/modules/data/webadmin/tmpl/traffic.tmpl +++ b/modules/data/webadmin/tmpl/traffic.tmpl @@ -17,15 +17,19 @@ Total Users - - Attached Users - + + Total Networks + + Attached Networks + + + Total Client Connections - + Total IRC Connections diff --git a/modules/webadmin.cpp b/modules/webadmin.cpp index 4a41e63b..f54fda63 100644 --- a/modules/webadmin.cpp +++ b/modules/webadmin.cpp @@ -15,6 +15,7 @@ #include "WebModules.h" #include "ZNCString.h" #include "Listener.h" +#include "IRCNetwork.h" #include #include @@ -177,13 +178,8 @@ public: } VCString vsArgs; - WebSock.GetRawParam("servers").Split("\n", vsArgs); unsigned int a = 0; - for (a = 0; a < vsArgs.size(); a++) { - pNewUser->AddServer(vsArgs[a].Trim_n()); - } - WebSock.GetRawParam("allowedips").Split("\n", vsArgs); if (vsArgs.size()) { for (a = 0; a < vsArgs.size(); a++) { @@ -254,12 +250,6 @@ public: pNewUser->SetAdmin(pUser->IsAdmin()); } - WebSock.GetParamValues("channel", vsArgs); - for (a = 0; a < vsArgs.size(); a++) { - const CString& sChan = vsArgs[a]; - pNewUser->AddChan(sChan.TrimRight_n("\r"), WebSock.GetParam("save_" + sChan).ToBool()); - } - if (spSession->IsAdmin() || (pUser && !pUser->DenyLoadMod())) { WebSock.GetParamValues("loadmod", vsArgs); @@ -272,7 +262,7 @@ public: CString sArgs = WebSock.GetParam("modargs_" + sModName); try { - if (!pNewUser->GetModules().LoadModule(sModName, sArgs, CModInfo::UserModule, pNewUser, sModRet)) { + if (!pNewUser->GetModules().LoadModule(sModName, sArgs, CModInfo::UserModule, pNewUser, NULL, sModRet)) { sModLoadError = "Unable to load module [" + sModName + "] [" + sModRet + "]"; } } catch (...) { @@ -295,7 +285,7 @@ public: CString sModLoadError; try { - if (!pNewUser->GetModules().LoadModule(sModName, sArgs, CModInfo::UserModule, pNewUser, sModRet)) { + if (!pNewUser->GetModules().LoadModule(sModName, sArgs, CModInfo::UserModule, pNewUser, NULL, sModRet)) { sModLoadError = "Unable to load module [" + sModName + "] [" + sModRet + "]"; } } catch (...) { @@ -322,10 +312,31 @@ public: return sUserName; } + CString SafeGetNetworkParam(CWebSock& WebSock) { + CString sNetwork = WebSock.GetParam("network"); // check for POST param + if(sNetwork.empty() && !WebSock.IsPost()) { + // if no POST param named user has been given and we are not + // saving this form, fall back to using the GET parameter. + sNetwork = WebSock.GetParam("network", false); + } + return sNetwork; + } + CUser* SafeGetUserFromParam(CWebSock& WebSock) { return CZNC::Get().FindUser(SafeGetUserNameParam(WebSock)); } + CIRCNetwork* SafeGetNetworkFromParam(CWebSock& WebSock) { + CUser* pUser = CZNC::Get().FindUser(SafeGetUserNameParam(WebSock)); + CIRCNetwork* pNetwork = NULL; + + if (pUser) { + pNetwork = pUser->FindNetwork(SafeGetNetworkParam(WebSock)); + } + + return pNetwork; + } + virtual CString GetWebMenuTitle() { return "webadmin"; } virtual bool OnWebRequest(CWebSock& WebSock, const CString& sPageName, CTemplate& Tmpl) { CSmartPtr spSession = WebSock.GetSession(); @@ -344,31 +355,7 @@ public: } return UserPage(WebSock, Tmpl); - } else if (sPageName == "editchan") { - CUser* pUser = SafeGetUserFromParam(WebSock); - - // Admin||Self Check - if (!spSession->IsAdmin() && (!spSession->GetUser() || spSession->GetUser() != pUser)) { - return false; - } - - if (!pUser) { - WebSock.PrintErrorPage("No such username"); - return true; - } - - CString sChan = WebSock.GetParam("name"); - if(sChan.empty() && !WebSock.IsPost()) { - sChan = WebSock.GetParam("name", false); - } - CChan* pChan = pUser->FindChan(sChan); - if (!pChan) { - WebSock.PrintErrorPage("No such channel"); - return true; - } - - return ChanPage(WebSock, Tmpl, pUser, pChan); - } else if (sPageName == "addchan") { + } else if (sPageName == "addnetwork") { CUser* pUser = SafeGetUserFromParam(WebSock); // Admin||Self Check @@ -377,12 +364,27 @@ public: } if (pUser) { - return ChanPage(WebSock, Tmpl, pUser); + return NetworkPage(WebSock, Tmpl, pUser); } WebSock.PrintErrorPage("No such username"); return true; - } else if (sPageName == "delchan") { + } else if (sPageName == "editnetwork") { + CIRCNetwork* pNetwork = SafeGetNetworkFromParam(WebSock); + + // Admin||Self Check + if (!spSession->IsAdmin() && (!spSession->GetUser() || spSession->GetUser() != pNetwork->GetUser())) { + return false; + } + + if (!pNetwork) { + WebSock.PrintErrorPage("No such username or network"); + return true; + } + + return NetworkPage(WebSock, Tmpl, pNetwork->GetUser(), pNetwork); + + } else if (sPageName == "delnetwork") { CUser* pUser = CZNC::Get().FindUser(WebSock.GetParam("user", false)); // Admin||Self Check @@ -390,11 +392,58 @@ public: return false; } - if (pUser) { - return DelChan(WebSock, pUser); + return DelNetwork(WebSock, pUser); + } else if (sPageName == "editchan") { + CIRCNetwork* pNetwork = SafeGetNetworkFromParam(WebSock); + + // Admin||Self Check + if (!spSession->IsAdmin() && (!spSession->GetUser() || spSession->GetUser() != pNetwork->GetUser())) { + return false; } - WebSock.PrintErrorPage("No such username"); + if (!pNetwork) { + WebSock.PrintErrorPage("No such username or network"); + return true; + } + + CString sChan = WebSock.GetParam("name"); + if(sChan.empty() && !WebSock.IsPost()) { + sChan = WebSock.GetParam("name", false); + } + CChan* pChan = pNetwork->FindChan(sChan); + if (!pChan) { + WebSock.PrintErrorPage("No such channel"); + return true; + } + + return ChanPage(WebSock, Tmpl, pNetwork, pChan); + } else if (sPageName == "addchan") { + CIRCNetwork* pNetwork = SafeGetNetworkFromParam(WebSock); + + // Admin||Self Check + if (!spSession->IsAdmin() && (!spSession->GetUser() || spSession->GetUser() != pNetwork->GetUser())) { + return false; + } + + if (pNetwork) { + return ChanPage(WebSock, Tmpl, pNetwork); + } + + WebSock.PrintErrorPage("No such username or network"); + return true; + } else if (sPageName == "delchan") { + CIRCNetwork* pNetwork = SafeGetNetworkFromParam(WebSock); + + // Admin||Self Check + if (!spSession->IsAdmin() && (!spSession->GetUser() || spSession->GetUser() != pNetwork->GetUser())) { + return false; + } + + if (pNetwork) { + return DelChan(WebSock, pNetwork); + } + + WebSock.PrintErrorPage("No such username or network"); return true; } else if (sPageName == "deluser") { if (!spSession->IsAdmin()) { @@ -465,9 +514,10 @@ public: return false; } - bool ChanPage(CWebSock& WebSock, CTemplate& Tmpl, CUser* pUser, CChan* pChan = NULL) { + bool ChanPage(CWebSock& WebSock, CTemplate& Tmpl, CIRCNetwork* pNetwork, CChan* pChan = NULL) { CSmartPtr spSession = WebSock.GetSession(); Tmpl.SetFile("add_edit_chan.tmpl"); + CUser* pUser = pNetwork->GetUser(); if (!pUser) { WebSock.PrintErrorPage("That user doesn't exist"); @@ -476,6 +526,7 @@ public: if (!WebSock.GetParam("submitted").ToUInt()) { Tmpl["User"] = pUser->GetUserName(); + Tmpl["Network"] = pNetwork->GetName(); if (pChan) { Tmpl["Action"] = "editchan"; @@ -530,13 +581,13 @@ public: return true; } - if (pUser->FindChan(sChanName.Token(0))) { + if (pNetwork->FindChan(sChanName.Token(0))) { WebSock.PrintErrorPage("Channel [" + sChanName.Token(0) + "] already exists"); return true; } - pChan = new CChan(sChanName, pUser, true); - pUser->AddChan(pChan); + pChan = new CChan(sChanName, pNetwork, true); + pNetwork->AddChan(pChan); } pChan->SetBufferCount(WebSock.GetParam("buffercount").ToUInt(), spSession->IsAdmin()); @@ -568,32 +619,204 @@ public: return true; } + WebSock.Redirect("editnetwork?user=" + pUser->GetUserName().Escape_n(CString::EURL) + "&network=" + pNetwork->GetName().Escape_n(CString::EURL)); + return true; + } + + bool NetworkPage(CWebSock& WebSock, CTemplate& Tmpl, CUser* pUser, CIRCNetwork* pNetwork = NULL) { + CSmartPtr spSession = WebSock.GetSession(); + Tmpl.SetFile("add_edit_network.tmpl"); + + if (!WebSock.GetParam("submitted").ToUInt()) { + Tmpl["Username"] = pUser->GetUserName(); + + set ssNetworkMods; + CZNC::Get().GetModules().GetAvailableMods(ssNetworkMods, CModInfo::NetworkModule); + for (set::iterator it = ssNetworkMods.begin(); it != ssNetworkMods.end(); ++it) { + const CModInfo& Info = *it; + CTemplate& l = Tmpl.AddRow("ModuleLoop"); + + l["Name"] = Info.GetName(); + l["Description"] = Info.GetDescription(); + l["Wiki"] = Info.GetWikiPage(); + + if (pNetwork) { + CModule *pModule = pNetwork->GetModules().FindModule(Info.GetName()); + if (pModule) { + l["Checked"] = "true"; + l["Args"] = pModule->GetArgs(); + } + } + + if (!spSession->IsAdmin() && pUser->DenyLoadMod()) { + l["Disabled"] = "true"; + } + } + + if (pNetwork) { + Tmpl["Action"] = "editnetwork"; + Tmpl["Edit"] = "true"; + Tmpl["Title"] = "Edit Network" + CString(" [" + pNetwork->GetName() + "]"); + Tmpl["Name"] = pNetwork->GetName(); + + const vector& vServers = pNetwork->GetServers(); + for (unsigned int a = 0; a < vServers.size(); a++) { + CTemplate& l = Tmpl.AddRow("ServerLoop"); + l["Server"] = vServers[a]->GetString(); + } + + const vector& Channels = pNetwork->GetChans(); + for (unsigned int c = 0; c < Channels.size(); c++) { + CChan* pChan = Channels[c]; + CTemplate& l = Tmpl.AddRow("ChannelLoop"); + + l["Network"] = pNetwork->GetName(); + l["Username"] = pUser->GetUserName(); + l["Name"] = pChan->GetName(); + l["Perms"] = pChan->GetPermStr(); + l["CurModes"] = pChan->GetModeString(); + l["DefModes"] = pChan->GetDefaultModes(); + l["BufferCount"] = CString(pChan->GetBufferCount()); + l["Options"] = pChan->GetOptions(); + + if (pChan->InConfig()) { + l["InConfig"] = "true"; + } + } + } else { + Tmpl["Action"] = "addnetwork"; + Tmpl["Title"] = "Add Network for User [" + pUser->GetUserName() + "]"; + } + + return true; + } + + CString sName = WebSock.GetParam("network").Trim_n(); + if (sName.empty()) { + WebSock.PrintErrorPage("Network name is a required argument"); + return true; + } + + if (!pNetwork) { + pNetwork = pUser->AddNetwork(sName); + if (!pNetwork) { + WebSock.PrintErrorPage("Network [" + sName.Token(0) + "] already exists"); + return true; + } + } + + VCString vsArgs; + + WebSock.GetRawParam("servers").Split("\n", vsArgs); + for (unsigned int a = 0; a < vsArgs.size(); a++) { + pNetwork->AddServer(vsArgs[a].Trim_n()); + } + + WebSock.GetParamValues("channel", vsArgs); + for (unsigned int a = 0; a < vsArgs.size(); a++) { + const CString& sChan = vsArgs[a]; + CChan *pChan = pNetwork->FindChan(sChan.TrimRight_n("\r")); + if (pChan) { + pChan->SetInConfig(WebSock.GetParam("save_" + sChan).ToBool()); + } + } + + set ssArgs; + WebSock.GetParamValues("loadmod", ssArgs); + if (spSession->IsAdmin() || !pUser->DenyLoadMod()) { + for (set::iterator it = ssArgs.begin(); it != ssArgs.end(); ++it) { + CString sModRet; + CString sModName = (*it).TrimRight_n("\r"); + CString sModLoadError; + + if (!sModName.empty()) { + CString sArgs = WebSock.GetParam("modargs_" + sModName); + + CModule *pMod = pNetwork->GetModules().FindModule(sModName); + + if (!pMod) { + if (!pNetwork->GetModules().LoadModule(sModName, sArgs, CModInfo::NetworkModule, pUser, pNetwork, sModRet)) { + sModLoadError = "Unable to load module [" + sModName + "] [" + sModRet + "]"; + } + } else if (pMod->GetArgs() != sArgs) { + if (!pNetwork->GetModules().ReloadModule(sModName, sArgs, pUser, pNetwork, sModRet)) { + sModLoadError = "Unable to reload module [" + sModName + "] [" + sModRet + "]"; + } + } + + if (!sModLoadError.empty()) { + DEBUG(sModLoadError); + WebSock.GetSession()->AddError(sModLoadError); + } + } + } + } + + const CModules& vCurMods = pNetwork->GetModules(); + set ssUnloadMods; + + for (unsigned int a = 0; a < vCurMods.size(); a++) { + CModule* pCurMod = vCurMods[a]; + + if (ssArgs.find(pCurMod->GetModName()) == ssArgs.end() && pCurMod->GetModName() != GetModName()) { + ssUnloadMods.insert(pCurMod->GetModName()); + } + } + + for (set::iterator it2 = ssUnloadMods.begin(); it2 != ssUnloadMods.end(); it2++) { + pNetwork->GetModules().UnloadModule(*it2); + } + + if (!CZNC::Get().WriteConfig()) { + WebSock.PrintErrorPage("Network added/modified, but config was not written"); + return true; + } + WebSock.Redirect("edituser?user=" + pUser->GetUserName().Escape_n(CString::EURL)); return true; } - bool DelChan(CWebSock& WebSock, CUser* pUser) { - CString sChan = WebSock.GetParam("name", false); + bool DelNetwork(CWebSock& WebSock, CUser* pUser) { + CString sNetwork = WebSock.GetParam("name", false); if (!pUser) { WebSock.PrintErrorPage("That user doesn't exist"); return true; } + if (sNetwork.empty()) { + WebSock.PrintErrorPage("That network doesn't exist for this user"); + return true; + } + + pUser->DeleteNetwork(sNetwork); + + if (!CZNC::Get().WriteConfig()) { + WebSock.PrintErrorPage("Network deleted, but config was not written"); + return true; + } + + WebSock.Redirect("edituser?user=" + pUser->GetUserName().Escape_n(CString::EURL)); + return false; + } + + bool DelChan(CWebSock& WebSock, CIRCNetwork* pNetwork) { + CString sChan = WebSock.GetParam("name", false); + if (sChan.empty()) { WebSock.PrintErrorPage("That channel doesn't exist for this user"); return true; } - pUser->DelChan(sChan); - pUser->PutIRC("PART " + sChan); + pNetwork->DelChan(sChan); + pNetwork->PutIRC("PART " + sChan); if (!CZNC::Get().WriteConfig()) { WebSock.PrintErrorPage("Channel deleted, but config was not written"); return true; } - WebSock.Redirect("edituser?user=" + pUser->GetUserName().Escape_n(CString::EURL)); + WebSock.Redirect("edituser?user=" + pNetwork->GetUser()->GetUserName().Escape_n(CString::EURL) + "&network=" + pNetwork->GetName().Escape_n(CString::EURL)); return false; } @@ -629,10 +852,11 @@ public: l["Host"] = *it; } - const vector& vServers = pUser->GetServers(); - for (unsigned int a = 0; a < vServers.size(); a++) { - CTemplate& l = Tmpl.AddRow("ServerLoop"); - l["Server"] = vServers[a]->GetString(); + const vector& vNetworks = pUser->GetNetworks(); + for (unsigned int a = 0; a < vNetworks.size(); a++) { + CTemplate& l = Tmpl.AddRow("NetworkLoop"); + l["Name"] = vNetworks[a]->GetName(); + l["Username"] = pUser->GetUserName(); } const MCString& msCTCPReplies = pUser->GetCTCPReplies(); @@ -640,24 +864,6 @@ public: CTemplate& l = Tmpl.AddRow("CTCPLoop"); l["CTCP"] = it2->first + " " + it2->second; } - - const vector& Channels = pUser->GetChans(); - for (unsigned int c = 0; c < Channels.size(); c++) { - CChan* pChan = Channels[c]; - CTemplate& l = Tmpl.AddRow("ChannelLoop"); - - l["Username"] = pUser->GetUserName(); - l["Name"] = pChan->GetName(); - l["Perms"] = pChan->GetPermStr(); - l["CurModes"] = pChan->GetModeString(); - l["DefModes"] = pChan->GetDefaultModes(); - l["BufferCount"] = CString(pChan->GetBufferCount()); - l["Options"] = pChan->GetOptions(); - - if (pChan->InConfig()) { - l["InConfig"] = "true"; - } - } } else { Tmpl["Action"] = "adduser"; Tmpl["Title"] = "Add User"; @@ -863,21 +1069,16 @@ public: unsigned int a = 0; for (map::const_iterator it = msUsers.begin(); it != msUsers.end(); ++it, a++) { - CServer* pServer = it->second->GetCurrentServer(); CTemplate& l = Tmpl.AddRow("UserLoop"); CUser& User = *it->second; l["Username"] = User.GetUserName(); - l["Clients"] = CString(User.GetClients().size()); - l["IRCNick"] = User.GetIRCNick().GetNick(); + l["Clients"] = CString(User.GetAllClients().size()); + l["Networks"] = CString(User.GetNetworks().size()); if (&User == spSession->GetUser()) { l["IsSelf"] = "true"; } - - if (pServer) { - l["Server"] = pServer->GetName(); - } } return true; @@ -890,20 +1091,32 @@ public: const map& msUsers = CZNC::Get().GetUserMap(); Tmpl["TotalUsers"] = CString(msUsers.size()); - unsigned int uiAttached = 0, uiClients = 0, uiServers = 0; + unsigned int uiNetworks = 0, uiAttached = 0, uiClients = 0, uiServers = 0; for (map::const_iterator it = msUsers.begin(); it != msUsers.end(); ++it) { CUser& User = *it->second; - if (User.IsUserAttached()) { - uiAttached++; + vector vNetworks = User.GetNetworks(); + + for (vector::const_iterator it2 = vNetworks.begin(); it2 != vNetworks.end(); ++it2) { + CIRCNetwork *pNetwork = *it2; + uiNetworks++; + + if (pNetwork->IsIRCConnected()) { + uiServers++; + } + + if (pNetwork->IsNetworkAttached()) { + uiAttached++; + } + + uiClients += pNetwork->GetClients().size(); } - if (User.IsIRCConnected()) { - uiServers++; - } - uiClients += User.GetClients().size(); + + uiClients += User.GetUserClients().size(); } - Tmpl["AttachedUsers"] = CString(uiAttached); + Tmpl["TotalNetworks"] = CString(uiNetworks); + Tmpl["AttachedNetworks"] = CString(uiAttached); Tmpl["TotalCConnections"] = CString(uiClients); Tmpl["TotalIRCConnections"] = CString(uiServers); @@ -1071,11 +1284,11 @@ public: CModule *pMod = CZNC::Get().GetModules().FindModule(sModName); if (!pMod) { - if (!CZNC::Get().GetModules().LoadModule(sModName, sArgs, CModInfo::GlobalModule, NULL, sModRet)) { + if (!CZNC::Get().GetModules().LoadModule(sModName, sArgs, CModInfo::GlobalModule, NULL, NULL, sModRet)) { sModLoadError = "Unable to load module [" + sModName + "] [" + sModRet + "]"; } } else if (pMod->GetArgs() != sArgs) { - if (!CZNC::Get().GetModules().ReloadModule(sModName, sArgs, NULL, sModRet)) { + if (!CZNC::Get().GetModules().ReloadModule(sModName, sArgs, NULL, NULL, sModRet)) { sModLoadError = "Unable to reload module [" + sModName + "] [" + sModRet + "]"; } }