diff --git a/modules/webadmin.cpp b/modules/webadmin.cpp
index 15f919b7..f32f56aa 100644
--- a/modules/webadmin.cpp
+++ b/modules/webadmin.cpp
@@ -865,6 +865,18 @@ public:
Tmpl["Action"] = "edituser";
Tmpl["Title"] = "Edit User [" + pUser->GetUserName() + "]";
Tmpl["Edit"] = "true";
+ } else {
+ CString sUsername = WebSock.GetParam("clone", false);
+ pUser = CZNC::Get().FindUser(sUsername);
+
+ if (pUser) {
+ Tmpl["Title"] = "Clone User [" + pUser->GetUserName() + "]";
+ Tmpl["Clone"] = "true";
+ Tmpl["CloneUsername"] = pUser->GetUserName();
+ }
+ }
+
+ if (pUser) {
Tmpl["Username"] = pUser->GetUserName();
Tmpl["Nick"] = pUser->GetNick();
Tmpl["AltNick"] = pUser->GetAltNick();
@@ -1049,6 +1061,11 @@ public:
CString sAction;
if (!pUser) {
+ CString sClone = WebSock.GetParam("clone");
+ if (CUser *pCloneUser = CZNC::Get().FindUser(sClone)) {
+ pNewUser->CloneNetworks(*pCloneUser);
+ }
+
// Add User Submission
if (!CZNC::Get().AddUser(pNewUser, sErr)) {
delete pNewUser;
diff --git a/src/User.cpp b/src/User.cpp
index 52d1309e..882dfd8a 100644
--- a/src/User.cpp
+++ b/src/User.cpp
@@ -566,6 +566,44 @@ void CUser::UserDisconnected(CClient* pClient) {
}
}
+void CUser::CloneNetworks(const CUser& User) {
+ const vector& vNetworks = User.GetNetworks();
+ for (vector::const_iterator it = vNetworks.begin(); it != vNetworks.end(); ++it) {
+ CIRCNetwork *pNetwork = FindNetwork((*it)->GetName());
+
+ if (pNetwork) {
+ pNetwork->Clone(*(*it));
+ } else {
+ new CIRCNetwork(this, *(*it));
+ }
+ }
+
+ set ssDeleteNetworks;
+ for (vector::const_iterator it = m_vIRCNetworks.begin(); it != m_vIRCNetworks.end(); ++it) {
+ if (!(User.FindNetwork((*it)->GetName()))) {
+ ssDeleteNetworks.insert((*it)->GetName());
+ }
+ }
+
+ for (set::const_iterator it = ssDeleteNetworks.begin(); it != ssDeleteNetworks.end(); ++it) {
+ // The following will move all the clients to the user.
+ // So the clients are not disconnected. The client could
+ // have requested the rehash. Then when we do
+ // client->PutStatus("Rehashing succeeded!") we would
+ // crash if there was no client anymore.
+ vector& vClients = FindNetwork(*it)->GetClients();
+
+ while (vClients.begin() != vClients.end()) {
+ CClient *pClient = vClients.front();
+ // This line will remove pClient from vClients,
+ // because it's a reference to the internal Network's vector.
+ pClient->SetNetwork(NULL);
+ }
+
+ DeleteNetwork(*it);
+ }
+}
+
bool CUser::Clone(const CUser& User, CString& sErrorRet, bool bCloneNetworks) {
unsigned int a = 0;
sErrorRet.clear();
@@ -619,41 +657,7 @@ bool CUser::Clone(const CUser& User, CString& sErrorRet, bool bCloneNetworks) {
// Networks
if (bCloneNetworks) {
- const vector& vNetworks = User.GetNetworks();
- for (vector::const_iterator it = vNetworks.begin(); it != vNetworks.end(); ++it) {
- CIRCNetwork *pNetwork = FindNetwork((*it)->GetName());
-
- if (pNetwork) {
- pNetwork->Clone(*(*it));
- } else {
- new CIRCNetwork(this, *(*it));
- }
- }
-
- set ssDeleteNetworks;
- for (vector::const_iterator it = m_vIRCNetworks.begin(); it != m_vIRCNetworks.end(); ++it) {
- if (!(User.FindNetwork((*it)->GetName()))) {
- ssDeleteNetworks.insert((*it)->GetName());
- }
- }
-
- for (set::const_iterator it = ssDeleteNetworks.begin(); it != ssDeleteNetworks.end(); ++it) {
- // The following will move all the clients to the user.
- // So the clients are not disconnected. The client could
- // have requested the rehash. Then when we do
- // client->PutStatus("Rehashing succeeded!") we would
- // crash if there was no client anymore.
- vector& vClients = FindNetwork(*it)->GetClients();
-
- while (vClients.begin() != vClients.end()) {
- CClient *pClient = vClients.front();
- // This line will remove pClient from vClients,
- // because it's a reference to the internal Network's vector.
- pClient->SetNetwork(NULL);
- }
-
- DeleteNetwork(*it);
- }
+ CloneNetworks(User);
}
// !Networks