#include "main.h" #include "User.h" #include "Nick.h" #include "Modules.h" #include "Chan.h" #include "znc.h" #include "HTTPSock.h" #include "Server.h" class CAdminMod; class CAdminSock : public CHTTPSock { public: CAdminSock(CAdminMod* pModule); CAdminSock(CAdminMod* pModule, const CString& sHostname, unsigned short uPort, int iTimeout = 60); virtual ~CAdminSock(); virtual bool OnPageRequest(const CString& sURI, CString& sPageRet); virtual bool OnLogin(const CString& sUser, const CString& sPass); CString Header(const CString& sTitle) { return "\r\n" "\r\n" + sTitle + "\r\n" "\r\n" "

" + sTitle + "



\r\n"; } CString Footer() { return "\r\n\r\n"; } void PrintMainPage(CString& sPageRet) { sPageRet = Header("Main Page"); sPageRet += "Add a user
\r\n" "List all users
\r\n"; sPageRet += Footer(); } void GetErrorPage(CString& sPageRet, const CString& sError) { sPageRet = Header("Error"); sPageRet += "

" + sError.Escape_n(CString::EHTML) + "

\r\n"; sPageRet += Footer(); } void ListUsersPage(CString& sPageRet); bool UserPage(CString& sPageRet, CUser* pUser = NULL); bool AddNewUser(CString& sPageRet); void ListPage(CString& sPageRet) { VCString vsParams; const map& msvsParams = GetParams(); sPageRet = Header("fooooooo"); if (msvsParams.empty()) { sPageRet += "You passed in no params.\r\n"; } else { for (map::const_iterator it = msvsParams.begin(); it != msvsParams.end(); it++) { sPageRet += "

" + it->first + "

\r\n\r\n"; } } sPageRet += Footer(); } virtual Csock* GetSockObj(const CString& sHost, unsigned short uPort); private: protected: CAdminMod* m_pModule; }; class CAdminMod : public CGlobalModule { public: CAdminMod(void *pDLL, CZNC* pZNC, const CString& sModName) : CGlobalModule(pDLL, pZNC, sModName) { m_uPort = 8080; } virtual ~CAdminMod() { for (set::iterator it = m_sSocks.begin(); it != m_sSocks.end(); it++) { m_pManager->DelSockByAddr(*it); } } virtual bool OnBoot() { return true; } virtual bool OnLoad(const CString& sArgs) { m_uPort = sArgs.Token(0).ToUInt(); m_sUser = sArgs.Token(1); m_sPass = sArgs.Token(2); if (m_sPass.empty()) { return false; } CAdminSock* pListenSock = new CAdminSock(this); //pListenSock->SetPemLocation(m_pZNC->GetPemLocation()); return m_pManager->ListenAll(m_uPort, "Admin::Listener", false, SOMAXCONN, pListenSock); } void AddSock(CAdminSock* pSock) { m_sSocks.insert(pSock); } void SockDestroyed(CAdminSock* pSock) { m_sSocks.erase(pSock); } const CString& GetUser() const { return m_sUser; } const CString& GetPass() const { return m_sPass; } private: unsigned int m_uPort; CString m_sUser; CString m_sPass; set m_sSocks; }; bool CAdminSock::OnLogin(const CString& sUser, const CString& sPass) { if (GetUser() == m_pModule->GetUser() && GetPass() == m_pModule->GetPass()) { return true; } return false; } void CAdminSock::ListUsersPage(CString& sPageRet) { const map& msUsers = m_pModule->GetZNC()->GetUserMap(); sPageRet = Header("List Users"); if (!msUsers.size()) { sPageRet += "There are no users defined. Click here if you would like to add one.\r\n"; } else { sPageRet += "\r\n" "\t\r\n"; unsigned int a = 0; for (map::const_iterator it = msUsers.begin(); it != msUsers.end(); it++, a++) { CServer* pServer = it->second->GetCurrentServer(); sPageRet += "\t\r\n\t\t\r\n" "\t\t\r\n" "\t\t\r\n" "\t"; } sPageRet +="\r\n
ActionUsernameCurrent Server
[second->GetUserName().Escape_n(CString::EURL) + "\">Edit] [second->GetUserName().Escape_n(CString::EURL) + "\">Delete]" + it->second->GetUserName().Escape_n(CString::EHTML) + "" + CString((pServer) ? pServer->GetName().Escape_n(CString::EHTML) : "-N/A-") + "
\r\n"; } sPageRet += Footer(); } Csock* CAdminSock::GetSockObj(const CString& sHost, unsigned short uPort) { CAdminSock* pSock = new CAdminSock(m_pModule, sHost, uPort); pSock->SetSockName("Admin::Client"); pSock->SetTimeout(120); m_pModule->AddSock(pSock); return pSock; } CAdminSock::CAdminSock(CAdminMod* pModule) : CHTTPSock() { m_pModule = pModule; m_pModule->AddSock(this); } CAdminSock::CAdminSock(CAdminMod* pModule, const CString& sHostname, unsigned short uPort, int iTimeout) : CHTTPSock(sHostname, uPort, iTimeout) { m_pModule = pModule; m_pModule->AddSock(this); } CAdminSock::~CAdminSock() { m_pModule->SockDestroyed(this); } bool CAdminSock::OnPageRequest(const CString& sURI, CString& sPageRet) { DEBUG_ONLY(cout << "Request for [" << sURI << "] "); if (!ForceLogin()) { DEBUG_ONLY(cout << "- User not logged in!" << endl); return false; } if (sURI == "/") { PrintMainPage(sPageRet); } else if (sURI == "/adduser") { if (!UserPage(sPageRet)) { DEBUG_ONLY(cout << "- 302 Redirect" << endl); return false; } } else if (sURI == "/edituser") { CUser* pUser = m_pModule->GetZNC()->FindUser(GetParam("user")); if (pUser) { if (!UserPage(sPageRet, pUser)) { DEBUG_ONLY(cout << "- 302 Redirect" << endl); return false; } } else { GetErrorPage(sPageRet, "No such username"); } } else if (sURI == "/listusers") { ListUsersPage(sPageRet); } else if (sURI == "/deluser") { if (m_pModule->GetZNC()->DeleteUser(GetParam("user"))) { DEBUG_ONLY(cout << "- 302 Redirect" << endl); Redirect("/listusers"); return false; } else { GetErrorPage(sPageRet, "No such username"); } } else if (sURI == "/list") { ListPage(sPageRet); } else { DEBUG_ONLY(cout << "- 404 Not Found!" << endl); return false; } DEBUG_ONLY(cout << "- 200 OK!" << endl); return true; } bool CAdminSock::UserPage(CString& sPageRet, CUser* pUser) { if (!GetParam("submitted").ToUInt()) { sPageRet = Header((pUser) ? "Edit User" : "Add User"); CString sAllowedHosts, sServers, sChans, sCTCPReplies; if (pUser) { const set& ssAllowedHosts = pUser->GetAllowedHosts(); for (set::const_iterator it = ssAllowedHosts.begin(); it != ssAllowedHosts.end(); it++) { sAllowedHosts += *it + "\r\n"; } const vector& vServers = pUser->GetServers(); for (unsigned int a = 0; a < vServers.size(); a++) { sServers += vServers[a]->GetName() + "\r\n"; } const vector& vChans = pUser->GetChans(); for (unsigned int b = 0; b < vChans.size(); b++) { sChans += vChans[b]->GetName() + "\r\n"; } const MCString& msCTCPReplies = pUser->GetCTCPReplies(); for (MCString::const_iterator it2 = msCTCPReplies.begin(); it2 != msCTCPReplies.end(); it2++) { sCTCPReplies += it2->first + " " + it2->second + "\r\n"; } } sPageRet += "
\r\n" "\r\n" "
Authentication
\r\n" "
Username:
\r\n"; if (pUser) { sPageRet += "\r\n" "
\r\n"; } else { sPageRet += "
\r\n"; } sPageRet += "Password:

\r\n" "Confirm Password:
\r\n" "
Allowed IPs:
\r\n" "


\r\n" "
IRC Information
\r\n" "
Nick:
\r\n" "
\r\n" "
AltNick:
\r\n" "
\r\n" "
AwaySuffix:
\r\n" "
\r\n" "
StatusPrefix:
\r\n" "

\r\n" "
Ident:
\r\n" "
\r\n" "
RealName:
\r\n" "

\r\n" "VHost:
\r\n" "

\r\n" "QuitMsg:
\r\n" "

\r\n" "
Servers:
\r\n" "
\r\n" "


\r\n" "
Modules
\r\n"; set ssUserMods; m_pModule->GetZNC()->GetModules().GetAvailableMods(ssUserMods, m_pModule->GetZNC()); for (set::iterator it = ssUserMods.begin(); it != ssUserMods.end(); it++) { const CModInfo& Info = *it; sPageRet += "" " (" + Info.GetDescription().Escape_n(CString::EHTML) + ")
"; } sPageRet += "


\r\n" "
Channels
\r\n" "Default Modes:
\r\n" "

\r\n" "
Channels:
\r\n" "
\r\n" "


\r\n" "
ZNC Behavior
\r\n" "Playback Buffer Size:
\r\n" "

\r\n" "Options:
\r\n" "  \r\n" "  \r\n" "  \r\n" "  \r\n" "  \r\n" "  \r\n" "

" "
CTCP Replies:
" "
\r\n" "


\r\n" "\r\n" "
\r\n"; sPageRet += Footer(); return true; } if (!pUser) { // Add User Submission if (AddNewUser(sPageRet)) { return true; } } else { // Edit User Submission GetErrorPage(sPageRet, "Sorry... the editing of users has not been implemented yet."); return true; } Redirect("/listusers"); return false; } bool CAdminSock::AddNewUser(CString& sPageRet) { CString sUsername = GetParam("user"); if (sUsername.empty()) { GetErrorPage(sPageRet, "Invalid Submission [Username is required]"); return true; } if (m_pModule->GetZNC()->FindUser(sUsername)) { GetErrorPage(sPageRet, "Invalid Submission [User " + sUsername.Escape_n(CString::EHTML) + " already exists]"); return true; } CString sArg = GetParam("password"); if (sArg != GetParam("password2")) { GetErrorPage(sPageRet, "Invalid Submission [Passwords do not match]"); return true; } CUser* pNewUser = new CUser(sUsername, m_pModule->GetZNC()); if (!sArg.empty()) { pNewUser->SetPass(sArg.MD5(), true); } VCString vsArgs; GetParam("servers").Split("\n", vsArgs); unsigned int a = 0; for (a = 0; a < vsArgs.size(); a++) { pNewUser->AddServer(vsArgs[a].Trim_n()); } GetParam("allowedips").Split("\n", vsArgs); for (a = 0; a < vsArgs.size(); a++) { pNewUser->AddAllowedHost(vsArgs[a].Trim_n()); } GetParam("ctcpreplies").Split("\n", vsArgs); for (a = 0; a < vsArgs.size(); a++) { CString sReply = vsArgs[a].TrimRight_n("\r"); pNewUser->AddCTCPReply(sReply.Token(0).Trim_n(), sReply.Token(1, true).Trim_n()); } GetParamValues("loadmod", vsArgs); for (a = 0; a < vsArgs.size(); a++) { CString sModRet; CString sArg = vsArgs[a].TrimRight_n("\r"); if (!sArg.empty()) { pNewUser->GetModules().LoadModule(sArg, "", pNewUser, sModRet); } } sArg = GetParam("nick"); if (!sArg.empty()) { pNewUser->SetNick(sArg); } sArg = GetParam("altnick"); if (!sArg.empty()) { pNewUser->SetAltNick(sArg); } sArg = GetParam("awaysuffix"); if (!sArg.empty()) { pNewUser->SetAwaySuffix(sArg); } sArg = GetParam("statusprefix"); if (!sArg.empty()) { pNewUser->SetStatusPrefix(sArg); } sArg = GetParam("ident"); if (!sArg.empty()) { pNewUser->SetIdent(sArg); } sArg = GetParam("realname"); if (!sArg.empty()) { pNewUser->SetRealName(sArg); } sArg = GetParam("vhost"); if (!sArg.empty()) { pNewUser->SetVHost(sArg); } sArg = GetParam("quitmsg"); if (!sArg.empty()) { pNewUser->SetQuitMsg(sArg); } sArg = GetParam("chanmodes"); if (!sArg.empty()) { pNewUser->SetDefaultChanModes(sArg); } pNewUser->SetBufferCount(GetParam("bufsize").ToUInt()); pNewUser->SetKeepBuffer(GetParam("keepbuffer").ToBool()); pNewUser->SetBounceDCCs(GetParam("bouncedccs").ToBool()); pNewUser->SetAutoCycle(GetParam("autocycle").ToBool()); pNewUser->SetKeepNick(GetParam("keepnick").ToBool()); pNewUser->SetUseClientIP(GetParam("useclientip").ToBool()); pNewUser->SetDenyLoadMod(GetParam("denyloadmod").ToBool()); GetParam("channels").Split("\n", vsArgs); for (a = 0; a < vsArgs.size(); a++) { pNewUser->AddChan(vsArgs[a].TrimRight_n("\r")); } CString sErr; if (!pNewUser->IsValid(sErr)) { delete pNewUser; GetErrorPage(sPageRet, "Invalid submission [" + sErr.Escape_n(CString::EHTML) + "]"); return true; } m_pModule->GetZNC()->AddUser(pNewUser); return false; } GLOBALMODULEDEFS(CAdminMod, "Add, Edit, Remove users on the fly")