Logo Search packages:      
Sourcecode: znc version File versions  Download package

webadmin.cpp

#include "main.h"
#include "User.h"
#include "Nick.h"
#include "Modules.h"
#include "Chan.h"
#include "znc.h"
#include "HTTPSock.h"
#include "Server.h"
#include "Template.h"

class CWebAdminMod;

class CWebAdminSock : public CHTTPSock {
public:
      CWebAdminSock(CWebAdminMod* pModule);
      CWebAdminSock(CWebAdminMod* pModule, const CString& sHostname, unsigned short uPort, int iTimeout = 60);
      virtual ~CWebAdminSock();

      virtual bool OnPageRequest(const CString& sURI, CString& sPageRet);
      virtual bool OnLogin(const CString& sUser, const CString& sPass);

      CString GetSkinDir();
      void PrintPage(CString& sPageRet, const CString& sTmplName);

      void GetErrorPage(CString& sPageRet, const CString& sError) {
            m_Template["Action"] = "error";
            m_Template["Title"] = "Error";
            m_Template["Error"] = sError;

            PrintPage(sPageRet, "Error.tmpl");
      }

      void ListUsersPage(CString& sPageRet);
      bool SettingsPage(CString& sPageRet);
      bool ChanPage(CString& sPageRet, CChan* = NULL);
      bool DelChan(CString& sPageRet);
      bool UserPage(CString& sPageRet, CUser* pUser = NULL);
      CUser* GetNewUser(CString& sPageRet, CUser* pUser);

      CString GetModArgs(const CString& sModName, bool bGlobal = false) {
            if (!bGlobal && !m_pUser) {
                  return "";
            }

            CModules& Modules = (bGlobal) ? CZNC::Get().GetModules() : m_pUser->GetModules();

            for (unsigned int a = 0; a < Modules.size(); a++) {
                  CModule* pModule = Modules[a];

                  if (pModule->GetModName() == sModName) {
                        return pModule->GetArgs();
                  }
            }

            return "";
      }

      virtual Csock* GetSockObj(const CString& sHost, unsigned short uPort);
      bool IsAdmin(bool bAllowUserAdmin = true) const { return m_bAdmin; }

private:
protected:
      CWebAdminMod*     m_pModule;
      CUser*                  m_pUser;
      bool              m_bAdmin;
      CTemplate         m_Template;
};

class CWebAdminMod : public CGlobalModule {
public:
      CWebAdminMod(void *pDLL, const CString& sModName) : CGlobalModule(pDLL, sModName) {
            m_uPort = 8080;
            m_sSkinName = GetNV("SkinName");
      }

      virtual ~CWebAdminMod() {
            while (m_spSocks.size()) {                                        // Loop through the sockets that we have created
                  m_pManager->DelSockByAddr(*m_spSocks.begin());  // Delete each one which will call SockDestroyed() and erase it from the set
            }                                                                             // This way we don't want to erase it ourselves, that's why we're using the funky while loop

            m_spSocks.clear();
      }

      virtual bool OnBoot() {
            return true;
      }

      virtual bool OnLoad(const CString& sArgs) {
            bool bSSL = false;
            CString sPort;

            if (sArgs.find(" ") != CString::npos) {
                  m_sListenHost = sArgs.Token(0);
                  sPort = sArgs.Token(1);
            } else {
                  sPort = sArgs.Token(0);
            }

            if (sPort.Left(1) == "+") {
#ifdef HAVE_LIBSSL
                  sPort.TrimLeft("+");
                  bSSL = true;
#else
                  return false;
#endif
            }

            if (!sPort.empty()) {
                  m_uPort = sPort.ToUInt();
            }

            CWebAdminSock* pListenSock = new CWebAdminSock(this);
#ifdef HAVE_LIBSSL
            if (bSSL) {
                  pListenSock->SetPemLocation(CZNC::Get().GetPemLocation());
            }
#endif

            return m_pManager->ListenHost(m_uPort, "WebAdmin::Listener", m_sListenHost, bSSL, SOMAXCONN, pListenSock);
      }

      void AddSock(CWebAdminSock* pSock) {
            m_spSocks.insert(pSock);
      }

      void SockDestroyed(CWebAdminSock* pSock) {
            m_spSocks.erase(pSock);
      }

      void SetSkinName(const CString& s) {
            m_sSkinName = s;
            SetNV("SkinName", m_sSkinName);
      }

      CString GetSkinName() const { return (m_sSkinName.empty()) ? CString("default") : m_sSkinName; }
      unsigned int GetSwitchCounter(const CString& sToken) {
            map<CString, unsigned int>::iterator it = m_suSwitchCounters.find(sToken);

            if (it == m_suSwitchCounters.end()) {
                  m_suSwitchCounters[sToken] = 1;
                  return 1;
            }

            return it->second;
      }

      unsigned int IncSwitchCounter(const CString& sToken) {
            map<CString, unsigned int>::iterator it = m_suSwitchCounters.find(sToken);

            if (it == m_suSwitchCounters.end()) {
                  m_suSwitchCounters[sToken] = 2;
                  return 2;
            }

            return ++it->second;
      }

private:
      unsigned int                        m_uPort;
      CString                                   m_sSkinName;
      set<CWebAdminSock*>                 m_spSocks;
      CString                                   m_sListenHost;
      map<CString, unsigned int>    m_suSwitchCounters;
};
 
CString CWebAdminSock::GetSkinDir() {
      CString sModPath = CZNC::Get().FindModPath(m_pModule->GetModName());    // @todo store the path to the module at load time and store it in a member var which can be used here

      // Remove the file.so portion from the path
      while (!sModPath.empty() && sModPath.Right(1) != "/") {
            sModPath.RightChomp();
      }

      // Remove the last /
      sModPath.RightChomp();

      CString sSkinDir = sModPath + "/" + m_pModule->GetModName() + "/skins/" + m_pModule->GetSkinName() + "/";

      if (CDir::Exists(sSkinDir)) {
            return sSkinDir;
      }

      return sModPath + "/" + m_pModule->GetModName() + "/skins/default/";
}

void CWebAdminSock::PrintPage(CString& sPageRet, const CString& sTmplName) {
      sPageRet.clear();
      // @todo possibly standardize the location of meta files such as these skins
      // @todo give an option for changing the current skin from 'default'
      CString sTmpl;

      if (IsAdmin()) {
            sTmpl = GetSkinDir();
      }

      sTmpl += sTmplName;

      if (!m_Template.SetFile(GetSkinDir() + sTmplName)) {
            sPageRet = CHTTPSock::GetErrorPage(404, "Not Found", "The template for this page [" + sTmpl + "] (or a template that it includes) was not found.");
            return;
      }

      stringstream oStr;
      if (!m_Template.Print(oStr)) {
            sPageRet = CHTTPSock::GetErrorPage(403, "Forbidden", "The template for this page [" + sTmpl + "] (or a template that it includes) can not be opened.");
            return;
      }

      sPageRet = oStr.str();
}

bool CWebAdminSock::OnLogin(const CString& sUser, const CString& sPass) {
      CUser* pUser = CZNC::Get().FindUser(GetUser());

      if (pUser) {
            CString sHost = GetRemoteIP();

            if (pUser->IsHostAllowed(sHost) && pUser->CheckPass(GetPass())) {
                  if (pUser->IsAdmin()) {
                        m_bAdmin = true;
                  } else {
                        m_pUser = pUser;
                  }

                  return true;
            }
      }

      return false;
}

void CWebAdminSock::ListUsersPage(CString& sPageRet) {
      const map<CString,CUser*>& msUsers = CZNC::Get().GetUserMap();
      m_Template["Title"] = "List Users";
      m_Template["Action"] = "listusers";

      unsigned int a = 0;

      for (map<CString,CUser*>::const_iterator it = msUsers.begin(); it != msUsers.end(); it++, a++) {
            CServer* pServer = it->second->GetCurrentServer();
            CTemplate& l = m_Template.AddRow("UserLoop");
            CUser& User = *it->second;

            l["Username"] = User.GetUserName();
            l["Clients"] = CString::ToString(User.GetClients().size());
            l["IRCNick"] = User.GetIRCNick().GetNick();

            if (pServer) {
                  l["Server"] = pServer->GetName();
            }
      }

      PrintPage(sPageRet, "ListUsers.tmpl");
}

Csock* CWebAdminSock::GetSockObj(const CString& sHost, unsigned short uPort) {
      CWebAdminSock* pSock = new CWebAdminSock(m_pModule, sHost, uPort);
      pSock->SetSockName("WebAdmin::Client");
      pSock->SetTimeout(120);
      m_pModule->AddSock(pSock);

      return pSock;
}

CWebAdminSock::CWebAdminSock(CWebAdminMod* pModule) : CHTTPSock() {
      m_pModule = pModule;
      m_pUser = NULL;
      m_bAdmin = false;
      m_pModule->AddSock(this);
      SetDocRoot(GetSkinDir());
}

CWebAdminSock::CWebAdminSock(CWebAdminMod* pModule, const CString& sHostname, unsigned short uPort, int iTimeout) : CHTTPSock(sHostname, uPort, iTimeout) {
      m_pModule = pModule;
      m_pUser = NULL;
      m_bAdmin = false;
      m_pModule->AddSock(this);
      SetDocRoot(GetSkinDir());
}

CWebAdminSock::~CWebAdminSock() {
      m_pModule->SockDestroyed(this);
}

bool CWebAdminSock::OnPageRequest(const CString& sURI, CString& sPageRet) {
      if (!ForceLogin()) {
            return false;
      }

      m_Template["SessionUser"] = GetUser();
      m_Template["SessionIP"] = GetRemoteIP();
      m_Template["Tag"] = CZNC::GetTag();

      if (IsAdmin()) {
            m_Template["IsAdmin"] = "true";
      }

      if (sURI == "/") {
            if (!IsAdmin()) {
                  Redirect("/edituser");
                  return false;
            }

            m_Template["Title"] = "Main Page";
            m_Template["Action"] = "home";
            PrintPage(sPageRet, "Main.tmpl");
      } else if (sURI.Left(5).CaseCmp("/css/") == 0) {
            SetDocRoot(GetSkinDir() + "/css");
            PrintFile(sURI.substr(5), "text/css");
            return false;
      } else if (sURI.Left(5).CaseCmp("/img/") == 0) {
            SetDocRoot(GetSkinDir() + "/img");
            PrintFile(sURI.substr(5));
            return false;
      } else if (sURI.Left(4).CaseCmp("/js/") == 0) {
            SetDocRoot(GetSkinDir() + "/js");
            PrintFile(sURI.substr(4), "application/x-javascript");
            return false;
      } else if (sURI == "/home") {
            m_Template["Title"] = "Main Page";
            m_Template["Action"] = "home";
            PrintPage(sPageRet, "Main.tmpl");
      } else if (sURI == "/settings") {
            if (!IsAdmin()) {
                  return false;
            }

            if (!SettingsPage(sPageRet)) {
                  return false;
            }
      } else if (sURI == "/switchuser") {
            unsigned int uCurCnt = GetParam("cnt").ToUInt();
            unsigned int uCounter = m_pModule->GetSwitchCounter(GetRemoteIP());

            if (!uCurCnt) {
                  Redirect("/switchuser?cnt=" + CString::ToString(uCounter));
                  return false;
            }

            if (uCurCnt >= uCounter) {
                  m_bLoggedIn = false;
                  m_pModule->IncSwitchCounter(GetRemoteIP());
                  ForceLogin();
            } else {
                  Redirect("/home");
            }

            return false;
      } else if (sURI == "/adduser") {
            if (!IsAdmin()) {
                  return false;
            }

            if (!UserPage(sPageRet)) {
                  return false;
            }
      } else if (sURI == "/edituser") {
            if (!m_pUser) {
                  m_pUser = CZNC::Get().FindUser(GetParam("user"));
            }

            if (m_pUser) {
                  if (!UserPage(sPageRet, m_pUser)) {
                        return false;
                  }
            } else {
                  GetErrorPage(sPageRet, "No such username");
            }
      } else if (sURI == "/editchan") {
            if (!m_pUser) {
                  m_pUser = CZNC::Get().FindUser(GetParam("user"));
            }

            if (!m_pUser) {
                  GetErrorPage(sPageRet, "No such username");
                  return true;
            }

            CChan* pChan = m_pUser->FindChan(GetParam("name"));
            if (!pChan) {
                  GetErrorPage(sPageRet, "No such channel");
                  return true;
            }

            if (!ChanPage(sPageRet, pChan)) {
                  return false;
            }
      } else if (sURI == "/addchan") {
            if (!m_pUser) {
                  m_pUser = CZNC::Get().FindUser(GetParam("user"));
            }

            if (m_pUser) {
                  if (!ChanPage(sPageRet)) {
                        return false;
                  }
            } else {
                  GetErrorPage(sPageRet, "No such username");
            }
      } else if (sURI == "/delchan") {
            if (!m_pUser) {
                  m_pUser = CZNC::Get().FindUser(GetParam("user"));
            }

            if (m_pUser) {
                  if (!DelChan(sPageRet)) {
                        return false;
                  }
            } else {
                  GetErrorPage(sPageRet, "No such username");
            }
      } else if (sURI == "/favicon.ico") {
            PrintFile("/img/favicon.ico", "image/x-icon");
            return false;
      } else if (sURI == "/listusers") {
            if (!IsAdmin()) {
                  return false;
            }

            ListUsersPage(sPageRet);
      } else if (sURI == "/deluser") {
            if (!IsAdmin()) {
                  return false;
            }

            if (CZNC::Get().DeleteUser(GetParam("user"))) {
                  Redirect("/listusers");
                  return false;
            } else {
                  GetErrorPage(sPageRet, "No such username");
            }
      } else {
            return false;
      }

      return true;
}

bool CWebAdminSock::SettingsPage(CString& sPageRet) {
      if (!GetParam("submitted").ToUInt()) {
            CString sVHosts, sMotd;
            m_Template["Action"] = "settings";
            m_Template["Title"] = "Settings";
            m_Template["StatusPrefix"] = CZNC::Get().GetStatusPrefix();
            m_Template["ISpoofFile"] = CZNC::Get().GetISpoofFile();
            m_Template["ISpoofFormat"] = CZNC::Get().GetISpoofFormat();

            const VCString& vsVHosts = CZNC::Get().GetVHosts();
            for (unsigned int a = 0; a < vsVHosts.size(); a++) {
                  CTemplate& l = m_Template.AddRow("VHostLoop");
                  l["VHost"] = vsVHosts[a];
            }

            const VCString& vsMotd = CZNC::Get().GetMotd();
            for (unsigned int b = 0; b < vsMotd.size(); b++) {
                  CTemplate& l = m_Template.AddRow("MOTDLoop");
                  l["Line"] = vsMotd[b];
            }

            const vector<CListener*>& vpListeners = CZNC::Get().GetListeners();
            for (unsigned int c = 0; c < vpListeners.size(); c++) {
                  CListener* pListener = vpListeners[c];
                  CTemplate& l = m_Template.AddRow("ListenLoop");

                  l["Port"] = CString::ToString(pListener->GetPort());
                  l["BindHost"] = pListener->GetBindHost();

#ifdef HAVE_LIBSSL
                  if (pListener->IsSSL()) {
                        l["IsSSL"] = "true";
                  }
#endif

#ifdef HAVE_IPV6
                  if (pListener->IsIPV6()) {
                        l["IsIPV6"] = "true";
                  }
#endif
            }

            CString sDir(GetSkinDir() + "/..");

            if (CDir::Exists(sDir)) {
                  CDir Dir(sDir);

                  m_Template.AddRow("SkinLoop")["Name"] = "default";

                  for (unsigned int d = 0; d < Dir.size(); d++) {
                        const CFile& SubDir = *Dir[d];

                        if (SubDir.IsDir() && SubDir.GetShortName() != "CVS" && SubDir.GetShortName() != "default") {
                              CTemplate& l = m_Template.AddRow("SkinLoop");
                              l["Name"] = SubDir.GetShortName();

                              if (SubDir.GetShortName() == m_pModule->GetSkinName()) {
                                    l["Checked"] = "true";
                              }
                        }
                  }
            }

            set<CModInfo> ssGlobalMods;
            CZNC::Get().GetModules().GetAvailableMods(ssGlobalMods, true);

            for (set<CModInfo>::iterator it = ssGlobalMods.begin(); it != ssGlobalMods.end(); it++) {
                  const CModInfo& Info = *it;
                  CTemplate& l = m_Template.AddRow("ModuleLoop");

                  if (CZNC::Get().GetModules().FindModule(Info.GetName())) {
                        l["Checked"] = "true";
                  }

                  if (Info.GetName() == m_pModule->GetModName()) {
                        l["Disabled"] = "true";
                  }

                  l["Name"] = Info.GetName();
                  l["Description"] = Info.GetDescription();
                  l["Args"] = GetModArgs(Info.GetName(), true);
            }

            PrintPage(sPageRet, "Settings.tmpl");
            return true;
      }

      CString sArg;
      sArg = GetParam("statusprefix"); CZNC::Get().SetStatusPrefix(sArg);
      sArg = GetParam("ispooffile"); CZNC::Get().SetISpoofFile(sArg);
      sArg = GetParam("ispoofformat"); CZNC::Get().SetISpoofFormat(sArg);
      //sArg = GetParam(""); if (!sArg.empty()) { CZNC::Get().Set(sArg); }

      VCString vsArgs;
      GetRawParam("motd").Split("\n", vsArgs);
      CZNC::Get().ClearMotd();

      unsigned int a = 0;
      for (a = 0; a < vsArgs.size(); a++) {
            CZNC::Get().AddMotd(vsArgs[a].TrimRight_n());
      }

      GetRawParam("vhosts").Split("\n", vsArgs);
      CZNC::Get().ClearVHosts();

      for (a = 0; a < vsArgs.size(); a++) {
            CZNC::Get().AddVHost(vsArgs[a].Trim_n());
      }

      m_pModule->SetSkinName(GetParam("skin"));

      set<CString> ssArgs;
      GetParamValues("loadmod", ssArgs);

      for (set<CString>::iterator it = ssArgs.begin(); it != ssArgs.end(); it++) {
            CString sModRet;
            CString sModName = (*it).TrimRight_n("\r");

            if (!sModName.empty()) {
                  CString sArgs = GetParam("modargs_" + sModName);

                  try {
                        if (!CZNC::Get().GetModules().FindModule(sModName)) {
                              if (!CZNC::Get().GetModules().LoadModule(sModName, sArgs, NULL, sModRet)) {
                                    DEBUG_ONLY(cerr << "Unable to load module [" << sModName << "] [" << sModRet << "]" << endl);
                              }
                        } else {
                              DEBUG_ONLY(cerr << "Unable to load module [" << sModName << "] because it is already loaded" << endl);
                        }
                  } catch(...) {
                        DEBUG_ONLY(cerr << "Unable to load module [" << sModName << "] [" << sArgs << "]" << endl);
                  }
            }
      }

      const CModules& vCurMods = CZNC::Get().GetModules();
      set<CString> ssUnloadMods;

      for (a = 0; a < vCurMods.size(); a++) {
            CModule* pCurMod = vCurMods[a];

            if (ssArgs.find(pCurMod->GetModName()) == ssArgs.end() && pCurMod->GetModName() != m_pModule->GetModName()) {
                  ssUnloadMods.insert(pCurMod->GetModName());
            }
      }

      for (set<CString>::iterator it2 = ssUnloadMods.begin(); it2 != ssUnloadMods.end(); it2++) {
            CZNC::Get().GetModules().UnloadModule(*it2);
      }

      if (!CZNC::Get().WriteConfig()) {
            GetErrorPage(sPageRet, "Settings changed, but config was not written");
            return true;
      }

      Redirect("/settings");
      return false;
}

bool CWebAdminSock::ChanPage(CString& sPageRet, CChan* pChan) {
      if (!m_pUser) {
            GetErrorPage(sPageRet, "That user doesn't exist");
            return true;
      }

      if (!GetParam("submitted").ToUInt()) {
            m_Template["User"] = m_pUser->GetUserName();

            if (pChan) {
                  m_Template["Action"] = "editchan";
                  m_Template["Edit"] = "true";
                  m_Template["Title"] = "Edit Channel" + CString(" [" + pChan->GetName() + "]");
                  m_Template["ChanName"] = pChan->GetName();
                  m_Template["BufferCount"] = CString::ToString(pChan->GetBufferCount());
                  m_Template["DefModes"] = pChan->GetDefaultModes();

                  if (pChan->InConfig()) {
                        m_Template["InConfig"] = "true";
                  }
            } else {
                  m_Template["Action"] = "addchan";
                  m_Template["Title"] = "Add Channel" + CString(" for User [" + m_pUser->GetUserName() + "]");
                  m_Template["BufferCount"] = "50";
                  m_Template["DefModes"] = "+stn";
                  m_Template["InConfig"] = "true";
            }

            CTemplate& o1 = m_Template.AddRow("OptionLoop");
            o1["Name"] = "autocycle";
            o1["DisplayName"] = "Auto Cycle";
            if (!pChan || pChan->AutoCycle()) { o1["Checked"] = "true"; }

            CTemplate& o2 = m_Template.AddRow("OptionLoop");
            o2["Name"] = "keepbuffer";
            o2["DisplayName"] = "Keep Buffer";
            if (!pChan || pChan->KeepBuffer()) { o2["Checked"] = "true"; }

            CTemplate& o3 = m_Template.AddRow("OptionLoop");
            o3["Name"] = "detached";
            o3["DisplayName"] = "Detached";
            if (pChan && pChan->IsDetached()) { o3["Checked"] = "true"; }

            PrintPage(sPageRet, "Channel.tmpl");
            return true;
      }

      CString sChanName = GetParam("name").Trim_n();

      if (!pChan) {
            if (sChanName.empty()) {
                  GetErrorPage(sPageRet, "Channel name is a required argument");
                  return true;
            }

            if (m_pUser->FindChan(sChanName.Token(0))) {
                  GetErrorPage(sPageRet, "Channel [" + sChanName.Token(0) + "] already exists");
                  return true;
            }

            pChan = new CChan(sChanName, m_pUser, true);
            m_pUser->AddChan(pChan);
      }

      pChan->SetDefaultModes(GetParam("defmodes"));
      pChan->SetBufferCount(GetParam("buffercount").ToUInt());
      pChan->SetInConfig(GetParam("save").ToBool());
      pChan->SetAutoCycle(GetParam("autocycle").ToBool());
      pChan->SetKeepBuffer(GetParam("keepbuffer").ToBool());

      bool bDetached = GetParam("detached").ToBool();

      if (pChan->IsDetached() != bDetached) {
            if (bDetached) {
                  pChan->DetachUser();
            } else {
                  pChan->AttachUser();
            }
      }

      m_pUser->JoinChans();

      if (!CZNC::Get().WriteConfig()) {
            GetErrorPage(sPageRet, "Channel added/modified, but config was not written");
            return true;
      }

      Redirect("/edituser?user=" + m_pUser->GetUserName().Escape_n(CString::EURL));
      return false;
}

bool CWebAdminSock::DelChan(CString& sPageRet) {
      CString sChan = GetParam("name");

      if (!m_pUser) {
            GetErrorPage(sPageRet, "That user doesn't exist");
            return true;
      }

      if (sChan.empty()) {
            GetErrorPage(sPageRet, "That channel doesn't exist for this user");
            return true;
      }

      m_pUser->DelChan(sChan);
      m_pUser->PutIRC("PART " + sChan);

      if (!CZNC::Get().WriteConfig()) {
            GetErrorPage(sPageRet, "Channel deleted, but config was not written");
            return true;
      }

      Redirect("/edituser?user=" + m_pUser->GetUserName().Escape_n(CString::EURL));
      return false;
}

bool CWebAdminSock::UserPage(CString& sPageRet, CUser* pUser) {
      if (!GetParam("submitted").ToUInt()) {
            CString sAllowedHosts, sServers, sChans, sCTCPReplies;

            if (pUser) {
                  m_Template["Action"] = "edituser";
                  m_Template["Title"] = "Edit User [" + pUser->GetUserName() + "]";
                  m_Template["Edit"] = "true";
                  m_Template["Username"] = pUser->GetUserName();
                  m_Template["Nick"] = pUser->GetNick();
                  m_Template["AltNick"] = pUser->GetAltNick();
                  m_Template["AwaySuffix"] = pUser->GetAwaySuffix();
                  m_Template["StatusPrefix"] = pUser->GetStatusPrefix();
                  m_Template["Ident"] = pUser->GetIdent();
                  m_Template["RealName"] = pUser->GetRealName();
                  m_Template["QuitMsg"] = pUser->GetQuitMsg();
                  m_Template["DefaultChanModes"] = pUser->GetDefaultChanModes();
                  m_Template["BufferCount"] = CString::ToString(pUser->GetBufferCount());

                  const set<CString>& ssAllowedHosts = pUser->GetAllowedHosts();
                  for (set<CString>::const_iterator it = ssAllowedHosts.begin(); it != ssAllowedHosts.end(); it++) {
                        CTemplate& l = m_Template.AddRow("AllowedHostLoop");
                        l["Host"] = *it;
                  }

                  const vector<CServer*>& vServers = pUser->GetServers();
                  for (unsigned int a = 0; a < vServers.size(); a++) {
                        CTemplate& l = m_Template.AddRow("ServerLoop");
                        l["Server"] = vServers[a]->GetString();
                  }

                  const MCString& msCTCPReplies = pUser->GetCTCPReplies();
                  for (MCString::const_iterator it2 = msCTCPReplies.begin(); it2 != msCTCPReplies.end(); it2++) {
                        CTemplate& l = m_Template.AddRow("CTCPLoop");
                        l["CTCP"] = it2->first + " " + it2->second;
                  }

                  if (pUser == CZNC::Get().FindUser(GetUser())) {
                        CString sIP = GetRemoteIP();

                        if (!sIP.empty()) {
                              m_Template["OwnIP"] = sIP.Token(0, false, ".") + "." + sIP.Token(1, false, ".") + "." + sIP.Token(2, false, ".") + ".*";
                        }
                  }

                  const VCString& vsVHosts = CZNC::Get().GetVHosts();
                  for (unsigned int b = 0; b < vsVHosts.size(); b++) {
                        const CString& sVHost = vsVHosts[b];
                        CTemplate& l = m_Template.AddRow("VHostLoop");

                        l["VHost"] = sVHost;

                        if (pUser && pUser->GetVHost() == sVHost) {
                              l["Checked"] = "true";
                        }
                  }

                  const vector<CChan*>& Channels = pUser->GetChans();
                  for (unsigned int c = 0; c < Channels.size(); c++) {
                        CChan* pChan = Channels[c];
                        CTemplate& l = m_Template.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::ToString(pChan->GetBufferCount());
                        l["Options"] = pChan->GetOptions();

                        if (pChan->InConfig()) {
                              l["InConfig"] = "true";
                        }
                  }
            } else {
                  m_Template["Action"] = "adduser";
                  m_Template["Title"] = "Add User";
                  m_Template["StatusPrefix"] = "*";
            }

            set<CModInfo> ssUserMods;
            CZNC::Get().GetModules().GetAvailableMods(ssUserMods);

            for (set<CModInfo>::iterator it = ssUserMods.begin(); it != ssUserMods.end(); it++) {
                  const CModInfo& Info = *it;
                  CTemplate& l = m_Template.AddRow("ModuleLoop");

                  l["Name"] = Info.GetName();
                  l["Description"] = Info.GetDescription();
                  l["Args"] = GetModArgs(Info.GetName());

                  if (pUser && pUser->GetModules().FindModule(Info.GetName())) {
                        l["Checked"] = "true";
                  }

                  if (!IsAdmin() && pUser && pUser->DenyLoadMod()) {
                        l["Disabled"] = "true";
                  }
            }

            CTemplate& o1 = m_Template.AddRow("OptionLoop");
            o1["Name"] = "keepbuffer";
            o1["DisplayName"] = "Keep Buffer";
            if (!pUser || pUser->KeepBuffer()) { o1["Checked"] = "true"; }

            CTemplate& o2 = m_Template.AddRow("OptionLoop");
            o2["Name"] = "autocycle";
            o2["DisplayName"] = "Auto Cycle";
            if (!pUser || pUser->AutoCycle()) { o2["Checked"] = "true"; }

            CTemplate& o3 = m_Template.AddRow("OptionLoop");
            o3["Name"] = "keepnick";
            o3["DisplayName"] = "Keep Nick";
            if (!pUser || pUser->GetKeepNick()) { o3["Checked"] = "true"; }

            CTemplate& o4 = m_Template.AddRow("OptionLoop");
            o4["Name"] = "multiclients";
            o4["DisplayName"] = "Multi Clients";
            if (!pUser || pUser->MultiClients()) { o4["Checked"] = "true"; }

            CTemplate& o5 = m_Template.AddRow("OptionLoop");
            o5["Name"] = "bouncedccs";
            o5["DisplayName"] = "Bounce DCCs";
            if (!pUser || pUser->BounceDCCs()) { o5["Checked"] = "true"; }

            CTemplate& o6 = m_Template.AddRow("OptionLoop");
            o6["Name"] = "useclientip";
            o6["DisplayName"] = "Use Client IP";
            if (pUser && pUser->UseClientIP()) { o6["Checked"] = "true"; }

            if (IsAdmin()) {
                  CTemplate& o7 = m_Template.AddRow("OptionLoop");
                  o7["Name"] = "denyloadmod";
                  o7["DisplayName"] = "Deny LoadMod";
                  if (pUser && pUser->DenyLoadMod()) { o7["Checked"] = "true"; }

                  CTemplate& o8 = m_Template.AddRow("OptionLoop");
                  o8["Name"] = "isadmin";
                  o8["DisplayName"] = "Admin";
                  if (pUser && pUser->IsAdmin()) { o8["Checked"] = "true"; }
                  if (pUser && pUser == CZNC::Get().FindUser(GetUser())) { o8["Disabled"] = "true"; }
            }

            PrintPage(sPageRet, "UserPage.tmpl");
            return true;
      }

      CString sUsername = GetParam("user");
      if (!pUser && CZNC::Get().FindUser(sUsername)) {
            GetErrorPage(sPageRet, "Invalid Submission [User " + sUsername + " already exists]");
            return true;
      }

      CUser* pNewUser = GetNewUser(sPageRet, pUser);
      if (!pNewUser) {
            return true;
      }

      CString sErr;

      if (!pUser) {
            // Add User Submission
            if (!pNewUser->IsValid(sErr)) {
                  delete pNewUser;
                  GetErrorPage(sPageRet, "Invalid submission [" + sErr + "]");
                  return true;
            }

            CZNC::Get().AddUser(pNewUser);
            if (!CZNC::Get().WriteConfig()) {
                  GetErrorPage(sPageRet, "User added, but config was not written");
                  return true;
            }
      } else {
            // Edit User Submission
            if (!pUser->Clone(*pNewUser, sErr)) {
                  delete pNewUser;
                  GetErrorPage(sPageRet, "Invalid Submission [" + sErr + "]");
                  return true;
            }

            delete pNewUser;
            if (!CZNC::Get().WriteConfig()) {
                  GetErrorPage(sPageRet, "User edited, but config was not written");
                  return true;
            }
      }

      if (!IsAdmin()) {
            Redirect("/edituser");
      } else {
            Redirect("/listusers");
      }

      return false;
}

CUser* CWebAdminSock::GetNewUser(CString& sPageRet, CUser* pUser) {
      CString sUsername = GetParam("newuser");

      if (sUsername.empty()) {
            sUsername = GetParam("user");
      }

      if (sUsername.empty()) {
            GetErrorPage(sPageRet, "Invalid Submission [Username is required]");
            return NULL;
      }

      CString sArg = GetParam("password");

      if (sArg != GetParam("password2")) {
            GetErrorPage(sPageRet, "Invalid Submission [Passwords do not match]");
            return NULL;
      }

      CUser* pNewUser = new CUser(sUsername);

      if (!sArg.empty()) {
            pNewUser->SetPass(sArg.MD5(), true);
      }

      VCString vsArgs;
      GetRawParam("servers").Split("\n", vsArgs);
      unsigned int a = 0;

      for (a = 0; a < vsArgs.size(); a++) {
            pNewUser->AddServer(vsArgs[a].Trim_n());
      }

      GetRawParam("allowedips").Split("\n", vsArgs);
      if (vsArgs.size()) {
            for (a = 0; a < vsArgs.size(); a++) {
                  pNewUser->AddAllowedHost(vsArgs[a].Trim_n());
            }
      } else {
            pNewUser->AddAllowedHost("*");
      }

      if (HasParam("ownip")) {
            pNewUser->AddAllowedHost(GetParam("ownip"));
      }

      GetRawParam("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());
      }

      if (IsAdmin() || (pUser && !pUser->DenyLoadMod())) {
            GetParamValues("loadmod", vsArgs);

            for (a = 0; a < vsArgs.size(); a++) {
                  CString sModRet;
                  CString sModName = vsArgs[a].TrimRight_n("\r");

                  if (!sModName.empty()) {
                        CString sArgs = GetParam("modargs_" + sModName);

                        try {
                              if (!pNewUser->GetModules().LoadModule(sModName, sArgs, pNewUser, sModRet, (pUser != NULL))) {
                                    DEBUG_ONLY(cerr << "Unable to load module [" << sModName << "] [" << sModRet << "]" << endl);
                              }
                        } catch (...) {
                              DEBUG_ONLY(cerr << "Unable to load module [" << sModName << "] [" << sArgs << "]" << endl);
                        }
                  }
            }
      } else if (pUser) {
            CModules& Modules = pUser->GetModules();

            for (a = 0; a < Modules.size(); a++) {
                  CString sModName = Modules[a]->GetModName();
                  CString sArgs = Modules[a]->GetArgs();
                  CString sModRet;

                  try {
                        if (!pNewUser->GetModules().LoadModule(sModName, sArgs, pNewUser, sModRet, (pUser != NULL))) {
                              DEBUG_ONLY(cerr << "Unable to load module [" << sModName << "] [" << sModRet << "]" << endl);
                        }
                  } catch (...) {
                        DEBUG_ONLY(cerr << "Unable to load module [" << sModName << "]" << endl);
                  }
            }
      }

      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->SetMultiClients(GetParam("multiclients").ToBool());
      pNewUser->SetBounceDCCs(GetParam("bouncedccs").ToBool());
      pNewUser->SetAutoCycle(GetParam("autocycle").ToBool());
      pNewUser->SetKeepNick(GetParam("keepnick").ToBool());
      pNewUser->SetUseClientIP(GetParam("useclientip").ToBool());

      if (IsAdmin()) {
            pNewUser->SetDenyLoadMod(GetParam("denyloadmod").ToBool());
      } else if (pUser) {
            pNewUser->SetDenyLoadMod(pUser->DenyLoadMod());
      }

      if (pUser && pUser != CZNC::Get().FindUser(GetUser())) {
            pNewUser->SetAdmin(GetParam("isadmin").ToBool());
      } else if (pUser) {
            pNewUser->SetAdmin(pUser->IsAdmin());
      }

      GetParamValues("channel", vsArgs);
      for (a = 0; a < vsArgs.size(); a++) {
            const CString& sChan = vsArgs[a];
            pNewUser->AddChan(sChan.TrimRight_n("\r"), GetParam("save_" + sChan).ToBool());
      }

      return pNewUser;
}

GLOBALMODULEDEFS(CWebAdminMod, "Dynamic configuration of users/settings through a web browser")

Generated by  Doxygen 1.6.0   Back to index