CWebSock::EPageReqResult CWebSock::OnPageRequestInternal(const CString& sURI, CString& sPageRet) { // Check that their session really belongs to their IP address. IP-based // authentication is bad, but here it's just an extra layer that makes // stealing cookies harder to pull off. // // When their IP is wrong, we give them an invalid cookie. This makes // sure that they will get a new cookie on their next request. if (CZNC::Get().GetProtectWebSessions() && GetSession()->GetIP() != GetRemoteIP()) { DEBUG("Expected IP: " << GetSession()->GetIP()); DEBUG("Remote IP: " << GetRemoteIP()); SendCookie("SessionId", "WRONG_IP_FOR_SESSION"); PrintErrorPage(403, "Access denied", "This session does not belong to your IP."); return PAGE_DONE; } // Check that they really POSTed from one our forms by checking if they // know the "secret" CSRF check value. Don't do this for login since // CSRF against the login form makes no sense and the login form does a // cookies-enabled check which would break otherwise. if (IsPost() && GetParam("_CSRF_Check") != GetCSRFCheck() && sURI != "/login") { DEBUG("Expected _CSRF_Check: " << GetCSRFCheck()); DEBUG("Actual _CSRF_Check: " << GetParam("_CSRF_Check")); PrintErrorPage(403, "Access denied", "POST requests need to send " "a secret token to prevent cross-site request forgery attacks."); return PAGE_DONE; } SendCookie("SessionId", GetSession()->GetId()); if (GetSession()->IsLoggedIn()) { m_sUser = GetSession()->GetUser()->GetUserName(); m_bLoggedIn = true; } // Handle the static pages that don't require a login if (sURI == "/") { if(!m_bLoggedIn && GetParam("cookie_check", false).ToBool() && GetRequestCookie("SessionId").empty()) { GetSession()->AddError("Your browser does not have cookies enabled for this site!"); } return PrintTemplate("index", sPageRet); } else if (sURI == "/favicon.ico") { return PrintStaticFile("/pub/favicon.ico", sPageRet); } else if (sURI == "/robots.txt") { return PrintStaticFile("/pub/robots.txt", sPageRet); } else if (sURI == "/logout") { GetSession()->SetUser(NULL); SetLoggedIn(false); Redirect("/"); // We already sent a reply return PAGE_DONE; } else if (sURI == "/login") { if (GetParam("submitted").ToBool()) { m_sUser = GetParam("user"); m_sPass = GetParam("pass"); m_bLoggedIn = OnLogin(m_sUser, m_sPass); // AcceptedLogin()/RefusedLogin() will call Redirect() return PAGE_DEFERRED; } Redirect("/"); // the login form is here return PAGE_DONE; } else if (sURI.Left(5) == "/pub/") { return PrintStaticFile(sURI, sPageRet); } else if (sURI.Left(11) == "/skinfiles/") { CString sSkinName = sURI.substr(11); CString::size_type uPathStart = sSkinName.find("/"); if (uPathStart != CString::npos) { CString sFilePath = sSkinName.substr(uPathStart + 1); sSkinName.erase(uPathStart); m_Template.ClearPaths(); m_Template.AppendPath(GetSkinPath(sSkinName) + "pub"); if (PrintFile(m_Template.ExpandFile(sFilePath))) { return PAGE_DONE; } else { return PAGE_NOTFOUND; } } return PAGE_NOTFOUND; } else if (sURI.Left(6) == "/mods/" || sURI.Left(10) == "/modfiles/") { // Make sure modules are treated as directories if (sURI.Right(1) != "/" && sURI.find(".") == CString::npos && sURI.TrimLeft_n("/mods/").TrimLeft_n("/").find("/") == CString::npos) { Redirect(sURI + "/"); return PAGE_DONE; } // The URI looks like: // /mods/[type]/([network]/)?[module][/page][?arg1=val1&arg2=val2...] m_sPath = GetPath().TrimLeft_n("/"); m_sPath.TrimPrefix("mods/"); m_sPath.TrimPrefix("modfiles/"); CString sType = m_sPath.Token(0, false, "/"); m_sPath = m_sPath.Token(1, true, "/"); CModInfo::EModuleType eModType; if (sType.Equals("global")) { eModType = CModInfo::GlobalModule; } else if (sType.Equals("user")) { eModType = CModInfo::UserModule; } else if (sType.Equals("network")) { eModType = CModInfo::NetworkModule; } else { PrintErrorPage(403, "Forbidden", "Unknown module type [" + sType + "]"); return PAGE_DONE; } if ((eModType != CModInfo::GlobalModule) && !ForceLogin()) { // Make sure we have a valid user return PAGE_DONE; } CIRCNetwork *pNetwork = NULL; if (eModType == CModInfo::NetworkModule) { CString sNetwork = m_sPath.Token(0, false, "/"); m_sPath = m_sPath.Token(1, true, "/"); pNetwork = GetSession()->GetUser()->FindNetwork(sNetwork); if (!pNetwork) { PrintErrorPage(404, "Not Found", "Network [" + sNetwork + "] not found."); return PAGE_DONE; } } m_sModName = m_sPath.Token(0, false, "/"); m_sPage = m_sPath.Token(1, true, "/"); if (m_sPage.empty()) { m_sPage = "index"; } DEBUG("Path [" + m_sPath + "], Module [" + m_sModName + "], Page [" + m_sPage + "]"); CModule *pModule = NULL; switch (eModType) { case CModInfo::GlobalModule: pModule = CZNC::Get().GetModules().FindModule(m_sModName); break; case CModInfo::UserModule: pModule = GetSession()->GetUser()->GetModules().FindModule(m_sModName); break; case CModInfo::NetworkModule: pModule = pNetwork->GetModules().FindModule(m_sModName); break; } if (!pModule) return PAGE_NOTFOUND; m_Template["ModPath"] = pModule->GetWebPath(); m_Template["ModFilesPath"] = pModule->GetWebFilesPath(); if (pModule->WebRequiresLogin() && !ForceLogin()) { return PAGE_PRINT; } else if (pModule->WebRequiresAdmin() && !GetSession()->IsAdmin()) { PrintErrorPage(403, "Forbidden", "You need to be an admin to access this module"); return PAGE_DONE; } else if (pModule->GetType() != CModInfo::GlobalModule && pModule->GetUser() != GetSession()->GetUser()) { PrintErrorPage(403, "Forbidden", "You must login as " + pModule->GetUser()->GetUserName() + " in order to view this page"); return PAGE_DONE; } else if (pModule->OnWebPreRequest(*this, m_sPage)) { return PAGE_DEFERRED; } VWebSubPages& vSubPages = pModule->GetSubPages(); for (unsigned int a = 0; a < vSubPages.size(); a++) { TWebSubPage& SubPage = vSubPages[a]; bool bActive = (m_sModName == pModule->GetModName() && m_sPage == SubPage->GetName()); if (bActive && SubPage->RequiresAdmin() && !GetSession()->IsAdmin()) { PrintErrorPage(403, "Forbidden", "You need to be an admin to access this page"); return PAGE_DONE; } } if (pModule && pModule->GetType() != CModInfo::GlobalModule && (!IsLoggedIn() || pModule->GetUser() != GetSession()->GetUser())) { AddModLoop("UserModLoop", *pModule); } if (sURI.Left(10) == "/modfiles/") { m_Template.AppendPath(GetSkinPath(GetSkinName()) + "/mods/" + m_sModName + "/files/"); m_Template.AppendPath(pModule->GetModDataDir() + "/files/"); if (PrintFile(m_Template.ExpandFile(m_sPage.TrimLeft_n("/")))) { return PAGE_PRINT; } else { return PAGE_NOTFOUND; } } else { SetPaths(pModule, true); /* if a module returns false from OnWebRequest, it does not want the template to be printed, usually because it did a redirect. */ if (pModule->OnWebRequest(*this, m_sPage, m_Template)) { // If they already sent a reply, let's assume // they did what they wanted to do. if (SentHeader()) { return PAGE_DONE; } return PrintTemplate(m_sPage, sPageRet, pModule); } if (!SentHeader()) { PrintErrorPage(404, "Not Implemented", "The requested module does not acknowledge web requests"); } return PAGE_DONE; } } else { CString sPage(sURI.Trim_n("/")); if (sPage.length() < 32) { for (unsigned int a = 0; a < sPage.length(); a++) { unsigned char c = sPage[a]; if ((c < '0' || c > '9') && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && c != '_') { return PAGE_NOTFOUND; } } return PrintTemplate(sPage, sPageRet); } } return PAGE_NOTFOUND; }
void CIRCNetwork::Clone(const CIRCNetwork& Network) { m_sName = Network.GetName(); SetNick(Network.GetNick()); SetAltNick(Network.GetAltNick()); SetIdent(Network.GetIdent()); SetRealName(Network.GetRealName()); // Servers const vector<CServer*>& vServers = Network.GetServers(); CString sServer; CServer* pCurServ = GetCurrentServer(); if (pCurServ) { sServer = pCurServ->GetName(); } DelServers(); unsigned int a; for (a = 0; a < vServers.size(); a++) { CServer* pServer = vServers[a]; AddServer(pServer->GetName(), pServer->GetPort(), pServer->GetPass(), pServer->IsSSL()); } m_uServerIdx = 0; for (a = 0; a < m_vServers.size(); a++) { if (sServer.Equals(m_vServers[a]->GetName())) { m_uServerIdx = a + 1; break; } } if (m_uServerIdx == 0) { m_uServerIdx = m_vServers.size(); CIRCSock* pSock = GetIRCSock(); if (pSock) { PutStatus("Jumping servers because this server is no longer in the list"); pSock->Quit(); } } // !Servers // Chans const vector<CChan*>& vChans = Network.GetChans(); for (a = 0; a < vChans.size(); a++) { CChan* pNewChan = vChans[a]; CChan* pChan = FindChan(pNewChan->GetName()); if (pChan) { pChan->SetInConfig(pNewChan->InConfig()); } else { AddChan(pNewChan->GetName(), pNewChan->InConfig()); } } for (a = 0; a < m_vChans.size(); a++) { CChan* pChan = m_vChans[a]; CChan* pNewChan = Network.FindChan(pChan->GetName()); if (!pNewChan) { pChan->SetInConfig(false); } else { pChan->Clone(*pNewChan); } } // !Chans // Modules set<CString> ssUnloadMods; CModules& vCurMods = GetModules(); const CModules& vNewMods = Network.GetModules(); for (a = 0; a < vNewMods.size(); a++) { CString sModRet; CModule* pNewMod = vNewMods[a]; CModule* pCurMod = vCurMods.FindModule(pNewMod->GetModName()); if (!pCurMod) { vCurMods.LoadModule(pNewMod->GetModName(), pNewMod->GetArgs(), CModInfo::NetworkModule, m_pUser, this, sModRet); } else if (pNewMod->GetArgs() != pCurMod->GetArgs()) { vCurMods.ReloadModule(pNewMod->GetModName(), pNewMod->GetArgs(), m_pUser, this, sModRet); } } for (a = 0; a < vCurMods.size(); a++) { CModule* pCurMod = vCurMods[a]; CModule* pNewMod = vNewMods.FindModule(pCurMod->GetModName()); if (!pNewMod) { ssUnloadMods.insert(pCurMod->GetModName()); } } for (set<CString>::iterator it = ssUnloadMods.begin(); it != ssUnloadMods.end(); ++it) { vCurMods.UnloadModule(*it); } // !Modules SetIRCConnectEnabled(Network.GetIRCConnectEnabled()); }
bool CUser::ParseConfig(CConfig* pConfig, CString& sError) { TOption<const CString&> StringOptions[] = { { "nick", &CUser::SetNick }, { "quitmsg", &CUser::SetQuitMsg }, { "altnick", &CUser::SetAltNick }, { "ident", &CUser::SetIdent }, { "realname", &CUser::SetRealName }, { "chanmodes", &CUser::SetDefaultChanModes }, { "bindhost", &CUser::SetBindHost }, { "vhost", &CUser::SetBindHost }, { "dccbindhost", &CUser::SetDCCBindHost }, { "dccvhost", &CUser::SetDCCBindHost }, { "timestampformat", &CUser::SetTimestampFormat }, { "skin", &CUser::SetSkinName }, { "language", &CUser::SetLanguage }, }; size_t numStringOptions = sizeof(StringOptions) / sizeof(StringOptions[0]); TOption<unsigned int> UIntOptions[] = { { "jointries", &CUser::SetJoinTries }, { "maxjoins", &CUser::SetMaxJoins }, }; size_t numUIntOptions = sizeof(UIntOptions) / sizeof(UIntOptions[0]); TOption<bool> BoolOptions[] = { { "keepbuffer", &CUser::SetKeepBuffer }, { "multiclients", &CUser::SetMultiClients }, { "denyloadmod", &CUser::SetDenyLoadMod }, { "admin", &CUser::SetAdmin }, { "denysetbindhost", &CUser::SetDenySetBindHost }, { "denysetvhost", &CUser::SetDenySetBindHost }, { "appendtimestamp", &CUser::SetTimestampAppend }, { "prependtimestamp", &CUser::SetTimestampPrepend }, { "ircconnectenabled", &CUser::SetIRCConnectEnabled }, }; size_t numBoolOptions = sizeof(BoolOptions) / sizeof(BoolOptions[0]); for (size_t i = 0; i < numStringOptions; i++) { CString sValue; if (pConfig->FindStringEntry(StringOptions[i].name, sValue)) (this->*StringOptions[i].pSetter)(sValue); } for (size_t i = 0; i < numUIntOptions; i++) { CString sValue; if (pConfig->FindStringEntry(UIntOptions[i].name, sValue)) (this->*UIntOptions[i].pSetter)(sValue.ToUInt()); } for (size_t i = 0; i < numBoolOptions; i++) { CString sValue; if (pConfig->FindStringEntry(BoolOptions[i].name, sValue)) (this->*BoolOptions[i].pSetter)(sValue.ToBool()); } VCString vsList; VCString::const_iterator vit; pConfig->FindStringVector("allow", vsList); for (vit = vsList.begin(); vit != vsList.end(); ++vit) { AddAllowedHost(*vit); } pConfig->FindStringVector("ctcpreply", vsList); for (vit = vsList.begin(); vit != vsList.end(); ++vit) { const CString& sValue = *vit; AddCTCPReply(sValue.Token(0), sValue.Token(1, true)); } CString sValue; CString sDCCLookupValue; pConfig->FindStringEntry("dcclookupmethod", sDCCLookupValue); if (pConfig->FindStringEntry("bouncedccs", sValue)) { if (sValue.ToBool()) { CUtils::PrintAction("Loading Module [bouncedcc]"); CString sModRet; bool bModRet = GetModules().LoadModule("bouncedcc", "", CModInfo::UserModule, this, NULL, sModRet); CUtils::PrintStatus(bModRet, sModRet); if (!bModRet) { sError = sModRet; return false; } if (sDCCLookupValue.Equals("Client")) { GetModules().FindModule("bouncedcc")->SetNV("UseClientIP", "1"); } } } if (pConfig->FindStringEntry("buffer", sValue)) SetBufferCount(sValue.ToUInt(), true); if (pConfig->FindStringEntry("awaysuffix", sValue)) { CUtils::PrintMessage("WARNING: AwaySuffix has been depricated, instead try -> LoadModule = awaynick %nick%_" + sValue); } if (pConfig->FindStringEntry("autocycle", sValue)) { if (sValue.Equals("true")) CUtils::PrintError("WARNING: AutoCycle has been removed, instead try -> LoadModule = autocycle"); } if (pConfig->FindStringEntry("keepnick", sValue)) { if (sValue.Equals("true")) CUtils::PrintError("WARNING: KeepNick has been deprecated, instead try -> LoadModule = keepnick"); } if (pConfig->FindStringEntry("statusprefix", sValue)) { if (!SetStatusPrefix(sValue)) { sError = "Invalid StatusPrefix [" + sValue + "] Must be 1-5 chars, no spaces."; CUtils::PrintError(sError); return false; } } if (pConfig->FindStringEntry("timezoneoffset", sValue)) { SetTimezoneOffset(sValue.ToDouble()); } if (pConfig->FindStringEntry("timestamp", sValue)) { if (!sValue.Trim_n().Equals("true")) { if (sValue.Trim_n().Equals("append")) { SetTimestampAppend(true); SetTimestampPrepend(false); } else if (sValue.Trim_n().Equals("prepend")) { SetTimestampAppend(false); SetTimestampPrepend(true); } else if (sValue.Trim_n().Equals("false")) { SetTimestampAppend(false); SetTimestampPrepend(false); } else { SetTimestampFormat(sValue); } } } pConfig->FindStringEntry("pass", sValue); // There are different formats for this available: // Pass = <plain text> // Pass = <md5 hash> - // Pass = plain#<plain text> // Pass = <hash name>#<hash> // Pass = <hash name>#<salted hash>#<salt># // 'Salted hash' means hash of 'password' + 'salt' // Possible hashes are md5 and sha256 if (sValue.Right(1) == "-") { sValue.RightChomp(); sValue.Trim(); SetPass(sValue, CUser::HASH_MD5); } else { CString sMethod = sValue.Token(0, false, "#"); CString sPass = sValue.Token(1, true, "#"); if (sMethod == "md5" || sMethod == "sha256") { CUser::eHashType type = CUser::HASH_MD5; if (sMethod == "sha256") type = CUser::HASH_SHA256; CString sSalt = sPass.Token(1, false, "#"); sPass = sPass.Token(0, false, "#"); SetPass(sPass, type, sSalt); } else if (sMethod == "plain") { SetPass(sPass, CUser::HASH_NONE); } else { SetPass(sValue, CUser::HASH_NONE); } } CConfig::SubConfig subConf; CConfig::SubConfig::const_iterator subIt; pConfig->FindSubConfig("pass", subConf); if (!sValue.empty() && !subConf.empty()) { sError = "Password defined more than once"; CUtils::PrintError(sError); return false; } subIt = subConf.begin(); if (subIt != subConf.end()) { CConfig* pSubConf = subIt->second.m_pSubConfig; CString sHash; CString sMethod; CString sSalt; CUser::eHashType method; pSubConf->FindStringEntry("hash", sHash); pSubConf->FindStringEntry("method", sMethod); pSubConf->FindStringEntry("salt", sSalt); if (sMethod.empty() || sMethod.Equals("plain")) method = CUser::HASH_NONE; else if (sMethod.Equals("md5")) method = CUser::HASH_MD5; else if (sMethod.Equals("sha256")) method = CUser::HASH_SHA256; else { sError = "Invalid hash method"; CUtils::PrintError(sError); return false; } SetPass(sHash, method, sSalt); if (!pSubConf->empty()) { sError = "Unhandled lines in config!"; CUtils::PrintError(sError); CZNC::DumpConfig(pSubConf); return false; } subIt++; } if (subIt != subConf.end()) { sError = "Password defined more than once"; CUtils::PrintError(sError); return false; } pConfig->FindSubConfig("network", subConf); for (subIt = subConf.begin(); subIt != subConf.end(); ++subIt) { const CString& sNetworkName = subIt->first; CIRCNetwork *pNetwork = FindNetwork(sNetworkName); if (!pNetwork) { pNetwork = new CIRCNetwork(this, sNetworkName); } if (!pNetwork->ParseConfig(subIt->second.m_pSubConfig, sError)) { return false; } } if (pConfig->FindStringVector("server", vsList, false) || pConfig->FindStringVector("chan", vsList, false) || pConfig->FindSubConfig("chan", subConf, false)) { CIRCNetwork *pNetwork = FindNetwork("user"); if (!pNetwork) { pNetwork = AddNetwork("user"); } if (pNetwork) { CUtils::PrintMessage("NOTICE: Found deprecated config, upgrading to a network"); if (!pNetwork->ParseConfig(pConfig, sError, true)) { return false; } } } pConfig->FindStringVector("loadmodule", vsList); for (vit = vsList.begin(); vit != vsList.end(); ++vit) { sValue = *vit; CString sModName = sValue.Token(0); // XXX Legacy crap, added in ZNC 0.089 if (sModName == "discon_kick") { CUtils::PrintMessage("NOTICE: [discon_kick] was renamed, loading [disconkick] instead"); sModName = "disconkick"; } // XXX Legacy crap, added in ZNC 0.099 if (sModName == "fixfreenode") { CUtils::PrintMessage("NOTICE: [fixfreenode] doesn't do anything useful anymore, ignoring it"); continue; } CUtils::PrintAction("Loading Module [" + sModName + "]"); CString sModRet; CString sArgs = sValue.Token(1, true); bool bModRet; CModInfo ModInfo; if (!CZNC::Get().GetModules().GetModInfo(ModInfo, sModName, sModRet)) { sError = "Unable to find modinfo [" + sModName + "] [" + sModRet + "]"; return false; } if (!ModInfo.SupportsType(CModInfo::UserModule) && ModInfo.SupportsType(CModInfo::NetworkModule)) { CUtils::PrintMessage("NOTICE: Module [" + sModName + "] is a network module, loading module for all networks in user."); // Do they have old NV? CFile fNVFile = CFile(GetUserPath() + "/moddata/" + sModName + "/.registry"); for (vector<CIRCNetwork*>::iterator it = m_vIRCNetworks.begin(); it != m_vIRCNetworks.end(); ++it) { if (fNVFile.Exists()) { CString sNetworkModPath = (*it)->GetNetworkPath() + "/moddata/" + sModName; if (!CFile::Exists(sNetworkModPath)) { CDir::MakeDir(sNetworkModPath); } fNVFile.Copy(sNetworkModPath + "/.registry"); } bModRet = (*it)->GetModules().LoadModule(sModName, sArgs, CModInfo::NetworkModule, this, *it, sModRet); if (!bModRet) { break; } } } else { bModRet = GetModules().LoadModule(sModName, sArgs, CModInfo::UserModule, this, NULL, sModRet); } CUtils::PrintStatus(bModRet, sModRet); if (!bModRet) { sError = sModRet; return false; } continue; } return true; }
CConfig CUser::ToConfig() { CConfig config; CConfig passConfig; CString sHash; switch (m_eHashType) { case HASH_NONE: sHash = "Plain"; break; case HASH_MD5: sHash = "MD5"; break; case HASH_SHA256: sHash = "SHA256"; break; } passConfig.AddKeyValuePair("Salt", m_sPassSalt); passConfig.AddKeyValuePair("Method", sHash); passConfig.AddKeyValuePair("Hash", GetPass()); config.AddSubConfig("Pass", "password", passConfig); config.AddKeyValuePair("Nick", GetNick()); config.AddKeyValuePair("AltNick", GetAltNick()); config.AddKeyValuePair("Ident", GetIdent()); config.AddKeyValuePair("RealName", GetRealName()); config.AddKeyValuePair("BindHost", GetBindHost()); config.AddKeyValuePair("DCCBindHost", GetDCCBindHost()); config.AddKeyValuePair("QuitMsg", GetQuitMsg()); if (CZNC::Get().GetStatusPrefix() != GetStatusPrefix()) config.AddKeyValuePair("StatusPrefix", GetStatusPrefix()); config.AddKeyValuePair("Skin", GetSkinName()); config.AddKeyValuePair("Language", GetLanguage()); config.AddKeyValuePair("ChanModes", GetDefaultChanModes()); config.AddKeyValuePair("Buffer", CString(GetBufferCount())); config.AddKeyValuePair("KeepBuffer", CString(KeepBuffer())); config.AddKeyValuePair("MultiClients", CString(MultiClients())); config.AddKeyValuePair("DenyLoadMod", CString(DenyLoadMod())); config.AddKeyValuePair("Admin", CString(IsAdmin())); config.AddKeyValuePair("DenySetBindHost", CString(DenySetBindHost())); config.AddKeyValuePair("TimestampFormat", GetTimestampFormat()); config.AddKeyValuePair("AppendTimestamp", CString(GetTimestampAppend())); config.AddKeyValuePair("PrependTimestamp", CString(GetTimestampPrepend())); config.AddKeyValuePair("TimezoneOffset", CString(m_fTimezoneOffset)); config.AddKeyValuePair("JoinTries", CString(m_uMaxJoinTries)); config.AddKeyValuePair("MaxJoins", CString(m_uMaxJoins)); config.AddKeyValuePair("IRCConnectEnabled", CString(GetIRCConnectEnabled())); // Allow Hosts if (!m_ssAllowedHosts.empty()) { for (set<CString>::iterator it = m_ssAllowedHosts.begin(); it != m_ssAllowedHosts.end(); ++it) { config.AddKeyValuePair("Allow", *it); } } // CTCP Replies if (!m_mssCTCPReplies.empty()) { for (MCString::const_iterator itb = m_mssCTCPReplies.begin(); itb != m_mssCTCPReplies.end(); ++itb) { config.AddKeyValuePair("CTCPReply", itb->first.AsUpper() + " " + itb->second); } } // Modules CModules& Mods = GetModules(); if (!Mods.empty()) { for (unsigned int a = 0; a < Mods.size(); a++) { CString sArgs = Mods[a]->GetArgs(); if (!sArgs.empty()) { sArgs = " " + sArgs; } config.AddKeyValuePair("LoadModule", Mods[a]->GetModName() + sArgs); } } // Networks for (unsigned int d = 0; d < m_vIRCNetworks.size(); d++) { CIRCNetwork *pNetwork = m_vIRCNetworks[d]; config.AddSubConfig("Network", pNetwork->GetName(), pNetwork->ToConfig()); } return config; }
bool CUser::ParseConfig(CConfig* pConfig, CString& sError) { TOption<const CString&> StringOptions[] = { {"nick", &CUser::SetNick}, {"quitmsg", &CUser::SetQuitMsg}, {"altnick", &CUser::SetAltNick}, {"ident", &CUser::SetIdent}, {"realname", &CUser::SetRealName}, {"chanmodes", &CUser::SetDefaultChanModes}, {"bindhost", &CUser::SetBindHost}, {"vhost", &CUser::SetBindHost}, {"dccbindhost", &CUser::SetDCCBindHost}, {"dccvhost", &CUser::SetDCCBindHost}, {"timestampformat", &CUser::SetTimestampFormat}, {"skin", &CUser::SetSkinName}, {"clientencoding", &CUser::SetClientEncoding}, }; TOption<unsigned int> UIntOptions[] = { {"jointries", &CUser::SetJoinTries}, {"maxnetworks", &CUser::SetMaxNetworks}, {"maxquerybuffers", &CUser::SetMaxQueryBuffers}, {"maxjoins", &CUser::SetMaxJoins}, }; TOption<bool> BoolOptions[] = { {"keepbuffer", &CUser::SetKeepBuffer}, // XXX compatibility crap from pre-0.207 {"autoclearchanbuffer", &CUser::SetAutoClearChanBuffer}, {"autoclearquerybuffer", &CUser::SetAutoClearQueryBuffer}, {"multiclients", &CUser::SetMultiClients}, {"denyloadmod", &CUser::SetDenyLoadMod}, {"admin", &CUser::SetAdmin}, {"denysetbindhost", &CUser::SetDenySetBindHost}, {"denysetvhost", &CUser::SetDenySetBindHost}, {"appendtimestamp", &CUser::SetTimestampAppend}, {"prependtimestamp", &CUser::SetTimestampPrepend}, }; for (const auto& Option : StringOptions) { CString sValue; if (pConfig->FindStringEntry(Option.name, sValue)) (this->*Option.pSetter)(sValue); } for (const auto& Option : UIntOptions) { CString sValue; if (pConfig->FindStringEntry(Option.name, sValue)) (this->*Option.pSetter)(sValue.ToUInt()); } for (const auto& Option : BoolOptions) { CString sValue; if (pConfig->FindStringEntry(Option.name, sValue)) (this->*Option.pSetter)(sValue.ToBool()); } VCString vsList; pConfig->FindStringVector("allow", vsList); for (const CString& sHost : vsList) { AddAllowedHost(sHost); } pConfig->FindStringVector("ctcpreply", vsList); for (const CString& sReply : vsList) { AddCTCPReply(sReply.Token(0), sReply.Token(1, true)); } CString sValue; CString sDCCLookupValue; pConfig->FindStringEntry("dcclookupmethod", sDCCLookupValue); if (pConfig->FindStringEntry("bouncedccs", sValue)) { if (sValue.ToBool()) { CUtils::PrintAction("Loading Module [bouncedcc]"); CString sModRet; bool bModRet = GetModules().LoadModule( "bouncedcc", "", CModInfo::UserModule, this, nullptr, sModRet); CUtils::PrintStatus(bModRet, sModRet); if (!bModRet) { sError = sModRet; return false; } if (sDCCLookupValue.Equals("Client")) { GetModules().FindModule("bouncedcc")->SetNV("UseClientIP", "1"); } } } if (pConfig->FindStringEntry("buffer", sValue)) SetBufferCount(sValue.ToUInt(), true); if (pConfig->FindStringEntry("chanbuffersize", sValue)) SetChanBufferSize(sValue.ToUInt(), true); if (pConfig->FindStringEntry("querybuffersize", sValue)) SetQueryBufferSize(sValue.ToUInt(), true); if (pConfig->FindStringEntry("awaysuffix", sValue)) { CUtils::PrintMessage( "WARNING: AwaySuffix has been deprecated, instead try -> " "LoadModule = awaynick %nick%_" + sValue); } if (pConfig->FindStringEntry("autocycle", sValue)) { if (sValue.Equals("true")) CUtils::PrintError( "WARNING: AutoCycle has been removed, instead try -> " "LoadModule = autocycle"); } if (pConfig->FindStringEntry("keepnick", sValue)) { if (sValue.Equals("true")) CUtils::PrintError( "WARNING: KeepNick has been deprecated, instead try -> " "LoadModule = keepnick"); } if (pConfig->FindStringEntry("statusprefix", sValue)) { if (!SetStatusPrefix(sValue)) { sError = "Invalid StatusPrefix [" + sValue + "] Must be 1-5 chars, no spaces."; CUtils::PrintError(sError); return false; } } if (pConfig->FindStringEntry("timezone", sValue)) { SetTimezone(sValue); } if (pConfig->FindStringEntry("timezoneoffset", sValue)) { if (fabs(sValue.ToDouble()) > 0.1) { CUtils::PrintError( "WARNING: TimezoneOffset has been deprecated, now you can set " "your timezone by name"); } } if (pConfig->FindStringEntry("timestamp", sValue)) { if (!sValue.Trim_n().Equals("true")) { if (sValue.Trim_n().Equals("append")) { SetTimestampAppend(true); SetTimestampPrepend(false); } else if (sValue.Trim_n().Equals("prepend")) { SetTimestampAppend(false); SetTimestampPrepend(true); } else if (sValue.Trim_n().Equals("false")) { SetTimestampAppend(false); SetTimestampPrepend(false); } else { SetTimestampFormat(sValue); } } } pConfig->FindStringEntry("pass", sValue); // There are different formats for this available: // Pass = <plain text> // Pass = <md5 hash> - // Pass = plain#<plain text> // Pass = <hash name>#<hash> // Pass = <hash name>#<salted hash>#<salt># // 'Salted hash' means hash of 'password' + 'salt' // Possible hashes are md5 and sha256 if (sValue.TrimSuffix("-")) { SetPass(sValue.Trim_n(), CUser::HASH_MD5); } else { CString sMethod = sValue.Token(0, false, "#"); CString sPass = sValue.Token(1, true, "#"); if (sMethod == "md5" || sMethod == "sha256") { CUser::eHashType type = CUser::HASH_MD5; if (sMethod == "sha256") type = CUser::HASH_SHA256; CString sSalt = sPass.Token(1, false, "#"); sPass = sPass.Token(0, false, "#"); SetPass(sPass, type, sSalt); } else if (sMethod == "plain") { SetPass(sPass, CUser::HASH_NONE); } else { SetPass(sValue, CUser::HASH_NONE); } } CConfig::SubConfig subConf; CConfig::SubConfig::const_iterator subIt; pConfig->FindSubConfig("pass", subConf); if (!sValue.empty() && !subConf.empty()) { sError = "Password defined more than once"; CUtils::PrintError(sError); return false; } subIt = subConf.begin(); if (subIt != subConf.end()) { CConfig* pSubConf = subIt->second.m_pSubConfig; CString sHash; CString sMethod; CString sSalt; CUser::eHashType method; pSubConf->FindStringEntry("hash", sHash); pSubConf->FindStringEntry("method", sMethod); pSubConf->FindStringEntry("salt", sSalt); if (sMethod.empty() || sMethod.Equals("plain")) method = CUser::HASH_NONE; else if (sMethod.Equals("md5")) method = CUser::HASH_MD5; else if (sMethod.Equals("sha256")) method = CUser::HASH_SHA256; else { sError = "Invalid hash method"; CUtils::PrintError(sError); return false; } SetPass(sHash, method, sSalt); if (!pSubConf->empty()) { sError = "Unhandled lines in config!"; CUtils::PrintError(sError); CZNC::DumpConfig(pSubConf); return false; } ++subIt; } if (subIt != subConf.end()) { sError = "Password defined more than once"; CUtils::PrintError(sError); return false; } pConfig->FindSubConfig("network", subConf); for (subIt = subConf.begin(); subIt != subConf.end(); ++subIt) { const CString& sNetworkName = subIt->first; CUtils::PrintMessage("Loading network [" + sNetworkName + "]"); CIRCNetwork* pNetwork = FindNetwork(sNetworkName); if (!pNetwork) { pNetwork = new CIRCNetwork(this, sNetworkName); } if (!pNetwork->ParseConfig(subIt->second.m_pSubConfig, sError)) { return false; } } if (pConfig->FindStringVector("server", vsList, false) || pConfig->FindStringVector("chan", vsList, false) || pConfig->FindSubConfig("chan", subConf, false)) { CIRCNetwork* pNetwork = FindNetwork("default"); if (!pNetwork) { CString sErrorDummy; pNetwork = AddNetwork("default", sErrorDummy); } if (pNetwork) { CUtils::PrintMessage( "NOTICE: Found deprecated config, upgrading to a network"); if (!pNetwork->ParseConfig(pConfig, sError, true)) { return false; } } } pConfig->FindStringVector("loadmodule", vsList); for (const CString& sMod : vsList) { CString sModName = sMod.Token(0); CString sNotice = "Loading user module [" + sModName + "]"; // XXX Legacy crap, added in ZNC 0.089 if (sModName == "discon_kick") { sNotice = "NOTICE: [discon_kick] was renamed, loading [disconkick] " "instead"; sModName = "disconkick"; } // XXX Legacy crap, added in ZNC 0.099 if (sModName == "fixfreenode") { sNotice = "NOTICE: [fixfreenode] doesn't do anything useful anymore, " "ignoring it"; CUtils::PrintMessage(sNotice); continue; } // XXX Legacy crap, added in ZNC 0.207 if (sModName == "admin") { sNotice = "NOTICE: [admin] module was renamed, loading [controlpanel] " "instead"; sModName = "controlpanel"; } // XXX Legacy crap, should have been added ZNC 0.207, but added only in // 1.1 :( if (sModName == "away") { sNotice = "NOTICE: [away] was renamed, loading [awaystore] instead"; sModName = "awaystore"; } // XXX Legacy crap, added in 1.1; fakeonline module was dropped in 1.0 // and returned in 1.1 if (sModName == "fakeonline") { sNotice = "NOTICE: [fakeonline] was renamed, loading [modules_online] " "instead"; sModName = "modules_online"; } // XXX Legacy crap, added in 1.3 if (sModName == "charset") { CUtils::PrintAction( "NOTICE: Charset support was moved to core, importing old " "charset module settings"); size_t uIndex = 1; if (sMod.Token(uIndex).Equals("-force")) { uIndex++; } VCString vsClient, vsServer; sMod.Token(uIndex).Split(",", vsClient); sMod.Token(uIndex + 1).Split(",", vsServer); if (vsClient.empty() || vsServer.empty()) { CUtils::PrintStatus( false, "charset module was loaded with wrong parameters."); continue; } SetClientEncoding(vsClient[0]); for (CIRCNetwork* pNetwork : m_vIRCNetworks) { pNetwork->SetEncoding(vsServer[0]); } CUtils::PrintStatus(true, "Using [" + vsClient[0] + "] for clients, and [" + vsServer[0] + "] for servers"); continue; } // XXX Legacy crap, added in 1.7 if (sModName == "disconkick") { sNotice = "NOTICE: [disconkick] is integrated to core now, ignoring it"; CUtils::PrintMessage(sNotice); continue; } CString sModRet; CString sArgs = sMod.Token(1, true); bool bModRet = LoadModule(sModName, sArgs, sNotice, sModRet); CUtils::PrintStatus(bModRet, sModRet); if (!bModRet) { // XXX The awaynick module was retired in 1.6 (still available as // external module) if (sModName == "awaynick") { // load simple_away instead, unless it's already on the list if (std::find(vsList.begin(), vsList.end(), "simple_away") == vsList.end()) { sNotice = "Loading [simple_away] module instead"; sModName = "simple_away"; // not a fatal error if simple_away is not available LoadModule(sModName, sArgs, sNotice, sModRet); } } else { sError = sModRet; return false; } } continue; } // Move ircconnectenabled to the networks if (pConfig->FindStringEntry("ircconnectenabled", sValue)) { for (CIRCNetwork* pNetwork : m_vIRCNetworks) { pNetwork->SetIRCConnectEnabled(sValue.ToBool()); } } return true; }
bool CWebSock::AddModLoop(const CString& sLoopName, CModule& Module, CTemplate *pTemplate) { if (!pTemplate) { pTemplate = &m_Template; } CString sTitle(Module.GetWebMenuTitle()); if (!sTitle.empty() && (IsLoggedIn() || (!Module.WebRequiresLogin() && !Module.WebRequiresAdmin())) && (GetSession()->IsAdmin() || !Module.WebRequiresAdmin())) { CTemplate& Row = pTemplate->AddRow(sLoopName); bool bActiveModule = false; Row["ModName"] = Module.GetModName(); Row["ModPath"] = Module.GetWebPath(); Row["Title"] = sTitle; if (m_sModName == Module.GetModName()) { CString sModuleType = GetPath().Token(1, false, "/"); if (sModuleType == "global" && Module.GetType() == CModInfo::GlobalModule) { bActiveModule = true; } else if (sModuleType == "user" && Module.GetType() == CModInfo::UserModule) { bActiveModule = true; } else if (sModuleType == "network" && Module.GetType() == CModInfo::NetworkModule) { CIRCNetwork *Network = Module.GetNetwork(); if (Network) { CString sNetworkName = GetPath().Token(2, false, "/"); if (sNetworkName == Network->GetName()) { bActiveModule = true; } } else { bActiveModule = true; } } } if (bActiveModule) { Row["Active"] = "true"; } if (Module.GetUser()) { Row["Username"] = Module.GetUser()->GetUserName(); } VWebSubPages& vSubPages = Module.GetSubPages(); for (unsigned int a = 0; a < vSubPages.size(); a++) { TWebSubPage& SubPage = vSubPages[a]; // bActive is whether or not the current url matches this subpage (params will be checked below) bool bActive = (m_sModName == Module.GetModName() && m_sPage == SubPage->GetName() && bActiveModule); if (SubPage->RequiresAdmin() && !GetSession()->IsAdmin()) { continue; // Don't add admin-only subpages to requests from non-admin users } CTemplate& SubRow = Row.AddRow("SubPageLoop"); SubRow["ModName"] = Module.GetModName(); SubRow["ModPath"] = Module.GetWebPath(); SubRow["PageName"] = SubPage->GetName(); SubRow["Title"] = SubPage->GetTitle().empty() ? SubPage->GetName() : SubPage->GetTitle(); CString& sParams = SubRow["Params"]; const VPair& vParams = SubPage->GetParams(); for (size_t b = 0; b < vParams.size(); b++) { pair<CString, CString> ssNV = vParams[b]; if (!sParams.empty()) { sParams += "&"; } if (!ssNV.first.empty()) { if (!ssNV.second.empty()) { sParams += ssNV.first.Escape_n(CString::EURL); sParams += "="; sParams += ssNV.second.Escape_n(CString::EURL); } if (bActive && GetParam(ssNV.first, false) != ssNV.second) { bActive = false; } } } if (bActive) { SubRow["Active"] = "true"; } } return true; } return false; }
void CIRCNetwork::Clone(const CIRCNetwork& Network, bool bCloneName) { if (bCloneName) { m_sName = Network.GetName(); } m_fFloodRate = Network.GetFloodRate(); m_uFloodBurst = Network.GetFloodBurst(); m_uJoinDelay = Network.GetJoinDelay(); SetNick(Network.GetNick()); SetAltNick(Network.GetAltNick()); SetIdent(Network.GetIdent()); SetRealName(Network.GetRealName()); SetBindHost(Network.GetBindHost()); SetEncoding(Network.GetEncoding()); SetQuitMsg(Network.GetQuitMsg()); m_ssTrustedFingerprints = Network.m_ssTrustedFingerprints; // Servers const vector<CServer*>& vServers = Network.GetServers(); CString sServer; CServer* pCurServ = GetCurrentServer(); if (pCurServ) { sServer = pCurServ->GetName(); } DelServers(); for (CServer* pServer : vServers) { AddServer(pServer->GetName(), pServer->GetPort(), pServer->GetPass(), pServer->IsSSL()); } m_uServerIdx = 0; for (size_t a = 0; a < m_vServers.size(); a++) { if (sServer.Equals(m_vServers[a]->GetName())) { m_uServerIdx = a + 1; break; } } if (m_uServerIdx == 0) { m_uServerIdx = m_vServers.size(); CIRCSock* pSock = GetIRCSock(); if (pSock) { PutStatus("Jumping servers because this server is no longer in the list"); pSock->Quit(); } } // !Servers // Chans const vector<CChan*>& vChans = Network.GetChans(); for (CChan* pNewChan : vChans) { CChan* pChan = FindChan(pNewChan->GetName()); if (pChan) { pChan->SetInConfig(pNewChan->InConfig()); } else { AddChan(pNewChan->GetName(), pNewChan->InConfig()); } } for (CChan* pChan : m_vChans) { CChan* pNewChan = Network.FindChan(pChan->GetName()); if (!pNewChan) { pChan->SetInConfig(false); } else { pChan->Clone(*pNewChan); } } // !Chans // Modules set<CString> ssUnloadMods; CModules& vCurMods = GetModules(); const CModules& vNewMods = Network.GetModules(); for (CModule* pNewMod : vNewMods) { CString sModRet; CModule* pCurMod = vCurMods.FindModule(pNewMod->GetModName()); if (!pCurMod) { vCurMods.LoadModule(pNewMod->GetModName(), pNewMod->GetArgs(), CModInfo::NetworkModule, m_pUser, this, sModRet); } else if (pNewMod->GetArgs() != pCurMod->GetArgs()) { vCurMods.ReloadModule(pNewMod->GetModName(), pNewMod->GetArgs(), m_pUser, this, sModRet); } } for (CModule* pCurMod : vCurMods) { CModule* pNewMod = vNewMods.FindModule(pCurMod->GetModName()); if (!pNewMod) { ssUnloadMods.insert(pCurMod->GetModName()); } } for (const CString& sMod : ssUnloadMods) { vCurMods.UnloadModule(sMod); } // !Modules SetIRCConnectEnabled(Network.GetIRCConnectEnabled()); }
void CClient::UserCommand(CString& sLine) { if (!m_pUser) { return; } if (sLine.empty()) { return; } NETWORKMODULECALL(OnStatusCommand(sLine), m_pUser, m_pNetwork, this, return); const CString sCommand = sLine.Token(0); if (sCommand.Equals("HELP")) { HelpUser(); } else if (sCommand.Equals("LISTNICKS")) { if (!m_pNetwork) { PutStatus("You must be connected with a network to use this command"); return; } CString sChan = sLine.Token(1); if (sChan.empty()) { PutStatus("Usage: ListNicks <#chan>"); return; } CChan* pChan = m_pNetwork->FindChan(sChan); if (!pChan) { PutStatus("You are not on [" + sChan + "]"); return; } if (!pChan->IsOn()) { PutStatus("You are not on [" + sChan + "] [trying]"); return; } const map<CString,CNick>& msNicks = pChan->GetNicks(); CIRCSock* pIRCSock = m_pNetwork->GetIRCSock(); const CString& sPerms = (pIRCSock) ? pIRCSock->GetPerms() : ""; if (!msNicks.size()) { PutStatus("No nicks on [" + sChan + "]"); return; } CTable Table; for (unsigned int p = 0; p < sPerms.size(); p++) { CString sPerm; sPerm += sPerms[p]; Table.AddColumn(sPerm); } Table.AddColumn("Nick"); Table.AddColumn("Ident"); Table.AddColumn("Host"); for (map<CString,CNick>::const_iterator a = msNicks.begin(); a != msNicks.end(); ++a) { Table.AddRow(); for (unsigned int b = 0; b < sPerms.size(); b++) { if (a->second.HasPerm(sPerms[b])) { CString sPerm; sPerm += sPerms[b]; Table.SetCell(sPerm, sPerm); } } Table.SetCell("Nick", a->second.GetNick()); Table.SetCell("Ident", a->second.GetIdent()); Table.SetCell("Host", a->second.GetHost()); } PutStatus(Table); } else if (sCommand.Equals("DETACH")) { if (!m_pNetwork) { PutStatus("You must be connected with a network to use this command"); return; } CString sChan = sLine.Token(1); if (sChan.empty()) { PutStatus("Usage: Detach <#chan>"); return; } const vector<CChan*>& vChans = m_pNetwork->GetChans(); vector<CChan*>::const_iterator it; unsigned int uMatches = 0, uDetached = 0; for (it = vChans.begin(); it != vChans.end(); ++it) { if (!(*it)->GetName().WildCmp(sChan)) continue; uMatches++; if ((*it)->IsDetached()) continue; uDetached++; (*it)->DetachUser(); } PutStatus("There were [" + CString(uMatches) + "] channels matching [" + sChan + "]"); PutStatus("Detached [" + CString(uDetached) + "] channels"); } else if (sCommand.Equals("VERSION")) { PutStatus(CZNC::GetTag()); PutStatus(CZNC::GetCompileOptionsString()); } else if (sCommand.Equals("MOTD") || sCommand.Equals("ShowMOTD")) { if (!SendMotd()) { PutStatus("There is no MOTD set."); } } else if (m_pUser->IsAdmin() && sCommand.Equals("Rehash")) { CString sRet; if (CZNC::Get().RehashConfig(sRet)) { PutStatus("Rehashing succeeded!"); } else { PutStatus("Rehashing failed: " + sRet); } } else if (m_pUser->IsAdmin() && sCommand.Equals("SaveConfig")) { if (CZNC::Get().WriteConfig()) { PutStatus("Wrote config to [" + CZNC::Get().GetConfigFile() + "]"); } else { PutStatus("Error while trying to write config."); } } else if (sCommand.Equals("LISTCLIENTS")) { CUser* pUser = m_pUser; CString sNick = sLine.Token(1); if (!sNick.empty()) { if (!m_pUser->IsAdmin()) { PutStatus("Usage: ListClients"); return; } pUser = CZNC::Get().FindUser(sNick); if (!pUser) { PutStatus("No such user [" + sNick + "]"); return; } } vector<CClient*> vClients = pUser->GetAllClients(); if (vClients.empty()) { PutStatus("No clients are connected"); return; } CTable Table; Table.AddColumn("Host"); Table.AddColumn("Network"); for (unsigned int a = 0; a < vClients.size(); a++) { Table.AddRow(); Table.SetCell("Host", vClients[a]->GetRemoteIP()); if (vClients[a]->GetNetwork()) { Table.SetCell("Network", vClients[a]->GetNetwork()->GetName()); } } PutStatus(Table); } else if (m_pUser->IsAdmin() && sCommand.Equals("LISTUSERS")) { const map<CString, CUser*>& msUsers = CZNC::Get().GetUserMap(); CTable Table; Table.AddColumn("Username"); Table.AddColumn("Networks"); Table.AddColumn("Clients"); for (map<CString, CUser*>::const_iterator it = msUsers.begin(); it != msUsers.end(); ++it) { Table.AddRow(); Table.SetCell("Username", it->first); Table.SetCell("Networks", CString(it->second->GetNetworks().size())); Table.SetCell("Clients", CString(it->second->GetAllClients().size())); } PutStatus(Table); } else if (m_pUser->IsAdmin() && sCommand.Equals("SetMOTD")) { CString sMessage = sLine.Token(1, true); if (sMessage.empty()) { PutStatus("Usage: SetMOTD <Message>"); } else { CZNC::Get().SetMotd(sMessage); PutStatus("MOTD set to [" + sMessage + "]"); } } else if (m_pUser->IsAdmin() && sCommand.Equals("AddMOTD")) { CString sMessage = sLine.Token(1, true); if (sMessage.empty()) { PutStatus("Usage: AddMOTD <Message>"); } else { CZNC::Get().AddMotd(sMessage); PutStatus("Added [" + sMessage + "] to MOTD"); } } else if (m_pUser->IsAdmin() && sCommand.Equals("ClearMOTD")) { CZNC::Get().ClearMotd(); PutStatus("Cleared MOTD"); } else if (m_pUser->IsAdmin() && sCommand.Equals("BROADCAST")) { CZNC::Get().Broadcast(sLine.Token(1, true)); } else if (m_pUser->IsAdmin() && (sCommand.Equals("SHUTDOWN") || sCommand.Equals("RESTART"))) { bool bRestart = sCommand.Equals("RESTART"); CString sMessage = sLine.Token(1, true); bool bForce = false; if (sMessage.Token(0).Equals("FORCE")) { bForce = true; sMessage = sMessage.Token(1, true); } if (sMessage.empty()) { sMessage = (bRestart ? "ZNC is being restarted NOW!" : "ZNC is being shut down NOW!"); } if(!CZNC::Get().WriteConfig() && !bForce) { PutStatus("ERROR: Writing config file to disk failed! Aborting. Use " + sCommand.AsUpper() + " FORCE to ignore."); } else { CZNC::Get().Broadcast(sMessage); throw CException(bRestart ? CException::EX_Restart : CException::EX_Shutdown); } } else if (sCommand.Equals("JUMP") || sCommand.Equals("CONNECT")) { if (!m_pNetwork) { PutStatus("You must be connected with a network to use this command"); return; } if (!m_pNetwork->HasServers()) { PutStatus("You don't have any servers added."); return; } CString sArgs = sLine.Token(1, true); CServer *pServer = NULL; if (!sArgs.empty()) { pServer = m_pNetwork->FindServer(sArgs); if (!pServer) { PutStatus("Server [" + sArgs + "] not found"); return; } m_pNetwork->SetNextServer(pServer); // If we are already connecting to some server, // we have to abort that attempt Csock *pIRCSock = GetIRCSock(); if (pIRCSock && !pIRCSock->IsConnected()) { pIRCSock->Close(); } } if (GetIRCSock()) { GetIRCSock()->Quit(); if (pServer) PutStatus("Connecting to [" + pServer->GetName() + "]..."); else PutStatus("Jumping to the next server in the list..."); } else { if (pServer) PutStatus("Connecting to [" + pServer->GetName() + "]..."); else PutStatus("Connecting..."); } m_pNetwork->SetIRCConnectEnabled(true); return; } else if (sCommand.Equals("DISCONNECT")) { if (!m_pNetwork) { PutStatus("You must be connected with a network to use this command"); return; } if (GetIRCSock()) { CString sQuitMsg = sLine.Token(1, true); GetIRCSock()->Quit(sQuitMsg); } m_pNetwork->SetIRCConnectEnabled(false); PutStatus("Disconnected from IRC. Use 'connect' to reconnect."); return; } else if (sCommand.Equals("ENABLECHAN")) { if (!m_pNetwork) { PutStatus("You must be connected with a network to use this command"); return; } CString sChan = sLine.Token(1, true); if (sChan.empty()) { PutStatus("Usage: EnableChan <channel>"); } else { const vector<CChan*>& vChans = m_pNetwork->GetChans(); vector<CChan*>::const_iterator it; unsigned int uMatches = 0, uEnabled = 0; for (it = vChans.begin(); it != vChans.end(); ++it) { if (!(*it)->GetName().WildCmp(sChan)) continue; uMatches++; if (!(*it)->IsDisabled()) continue; uEnabled++; (*it)->Enable(); } PutStatus("There were [" + CString(uMatches) + "] channels matching [" + sChan + "]"); PutStatus("Enabled [" + CString(uEnabled) + "] channels"); } } else if (sCommand.Equals("LISTCHANS")) { if (!m_pNetwork) { PutStatus("You must be connected with a network to use this command"); return; } CUser* pUser = m_pUser; CIRCNetwork* pNetwork = m_pNetwork; const CString sNick = sLine.Token(1); const CString sNetwork = sLine.Token(2); if (!sNick.empty()) { if (!m_pUser->IsAdmin()) { PutStatus("Usage: ListChans"); return; } pUser = CZNC::Get().FindUser(sNick); if (!pUser) { PutStatus("No such user [" + sNick + "]"); return; } pNetwork = pUser->FindNetwork(sNetwork); if (!pNetwork) { PutStatus("No such network for user [" + sNetwork + "]"); return; } } const vector<CChan*>& vChans = pNetwork->GetChans(); CIRCSock* pIRCSock = pNetwork->GetIRCSock(); const CString& sPerms = (pIRCSock) ? pIRCSock->GetPerms() : ""; if (!vChans.size()) { PutStatus("There are no channels defined."); return; } CTable Table; Table.AddColumn("Name"); Table.AddColumn("Status"); Table.AddColumn("Conf"); Table.AddColumn("Buf"); Table.AddColumn("Modes"); Table.AddColumn("Users"); for (unsigned int p = 0; p < sPerms.size(); p++) { CString sPerm; sPerm += sPerms[p]; Table.AddColumn(sPerm); } unsigned int uNumDetached = 0, uNumDisabled = 0, uNumJoined = 0; for (unsigned int a = 0; a < vChans.size(); a++) { const CChan* pChan = vChans[a]; Table.AddRow(); Table.SetCell("Name", pChan->GetPermStr() + pChan->GetName()); Table.SetCell("Status", ((vChans[a]->IsOn()) ? ((vChans[a]->IsDetached()) ? "Detached" : "Joined") : ((vChans[a]->IsDisabled()) ? "Disabled" : "Trying"))); Table.SetCell("Conf", CString((pChan->InConfig()) ? "yes" : "")); Table.SetCell("Buf", CString((pChan->KeepBuffer()) ? "*" : "") + CString(pChan->GetBufferCount())); Table.SetCell("Modes", pChan->GetModeString()); Table.SetCell("Users", CString(pChan->GetNickCount())); map<char, unsigned int> mPerms = pChan->GetPermCounts(); for (unsigned int b = 0; b < sPerms.size(); b++) { char cPerm = sPerms[b]; Table.SetCell(CString(cPerm), CString(mPerms[cPerm])); } if(pChan->IsDetached()) uNumDetached++; if(pChan->IsOn()) uNumJoined++; if(pChan->IsDisabled()) uNumDisabled++; } PutStatus(Table); PutStatus("Total: " + CString(vChans.size()) + " - Joined: " + CString(uNumJoined) + " - Detached: " + CString(uNumDetached) + " - Disabled: " + CString(uNumDisabled)); } else if (sCommand.Equals("ADDNETWORK")) { #ifndef ENABLE_ADD_NETWORK if (!m_pUser->IsAdmin()) { PutStatus("Permission denied"); return; } #endif CString sNetwork = sLine.Token(1); if (sNetwork.empty()) { PutStatus("Usage: AddNetwork <name>"); return; } if (m_pUser->AddNetwork(sNetwork)) { 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"); } } else if (m_pUser->IsAdmin() && sCommand.Equals("DELNETWORK")) { CString sNetwork = sLine.Token(1); if (sNetwork.empty()) { PutStatus("Usage: DelNetwork <name>"); return; } if (m_pNetwork && m_pNetwork->GetName().Equals(sNetwork)) { SetNetwork(NULL); } if (m_pUser->DeleteNetwork(sNetwork)) { PutStatus("Network deleted"); } else { PutStatus("Failed to delete network"); PutStatus("Perhaps this network doesn't exist"); } } else if (sCommand.Equals("LISTNETWORKS")) { CUser *pUser = m_pUser; if (m_pUser->IsAdmin() && !sLine.Token(1).empty()) { pUser = CZNC::Get().FindUser(sLine.Token(1)); if (!pUser) { PutStatus("User not found " + sLine.Token(1)); return; } } const vector<CIRCNetwork*>& vNetworks = pUser->GetNetworks(); CTable Table; Table.AddColumn("Network"); Table.AddColumn("OnIRC"); Table.AddColumn("IRC Server"); Table.AddColumn("IRC User"); Table.AddColumn("Channels"); for (unsigned int a = 0; a < vNetworks.size(); a++) { CIRCNetwork* pNetwork = vNetworks[a]; Table.AddRow(); Table.SetCell("Network", pNetwork->GetName()); if (pNetwork->IsIRCConnected()) { Table.SetCell("OnIRC", "Yes"); Table.SetCell("IRC Server", pNetwork->GetIRCServer()); Table.SetCell("IRC User", pNetwork->GetIRCNick().GetNickMask()); Table.SetCell("Channels", CString(pNetwork->GetChans().size())); } else { Table.SetCell("OnIRC", "No"); } } if (PutStatus(Table) == 0) { PutStatus("No networks"); } } else if (sCommand.Equals("JUMPNETWORK")) { CString sNetwork = sLine.Token(1); if (sNetwork.empty()) { PutStatus("No network supplied."); return; } if (m_pNetwork && (m_pNetwork->GetName() == sNetwork)) { PutStatus("You are already connected with this network."); return; } CIRCNetwork *pNetwork = m_pUser->FindNetwork(sNetwork); if (pNetwork) { PutStatus("Switched to " + sNetwork); SetNetwork(pNetwork); } else { PutStatus("You don't have a network named " + sNetwork); } } else if (sCommand.Equals("MODE")) { CString sNetwork = sLine.Token(1); if (sNetwork.empty()) { PutStatus("Syntax: MODE <support/default>"); return; } if (m_pNetwork && (m_pNetwork->GetName() == sNetwork)) { PutStatus("You are already in this mode."); return; } CIRCNetwork *pNetwork = m_pUser->FindNetwork(sNetwork); if (pNetwork) { PutStatus("You are now in " + sNetwork + " mode."); SetNetwork(pNetwork); } else { PutStatus("ERROR! Contact GeekBouncer admins immediately"); } } else if (m_pUser->IsAdmin() && sCommand.Equals("ADDSERVER")) { CString sServer = sLine.Token(1); if (!m_pNetwork) { PutStatus("You must be connected with a network to use this command"); return; } if (sServer.empty()) { PutStatus("Usage: AddServer <host> [[+]port] [pass]"); return; } if (m_pNetwork->AddServer(sLine.Token(1, true))) { PutStatus("Server added"); } else { PutStatus("Unable to add that server"); PutStatus("Perhaps the server is already added or openssl is disabled?"); } } else if (m_pUser->IsAdmin() && sCommand.Equals("REMSERVER") || sCommand.Equals("DELSERVER")) { if (!m_pNetwork) { PutStatus("You must be connected with a network to use this command"); return; } CString sServer = sLine.Token(1); unsigned short uPort = sLine.Token(2).ToUShort(); CString sPass = sLine.Token(3); if (sServer.empty()) { PutStatus("Usage: RemServer <host> [port] [pass]"); return; } if (!m_pNetwork->HasServers()) { PutStatus("You don't have any servers added."); return; } if (m_pNetwork->DelServer(sServer, uPort, sPass)) { PutStatus("Server removed"); } else { PutStatus("No such server"); } } else if (sCommand.Equals("LISTSERVERS")) { if (!m_pNetwork) { PutStatus("You must be connected with a network to use this command"); return; } if (m_pNetwork->HasServers()) { const vector<CServer*>& vServers = m_pNetwork->GetServers(); CServer* pCurServ = m_pNetwork->GetCurrentServer(); CTable Table; Table.AddColumn("Host"); Table.AddColumn("Port"); Table.AddColumn("SSL"); Table.AddColumn("Pass"); for (unsigned int a = 0; a < vServers.size(); a++) { CServer* pServer = vServers[a]; Table.AddRow(); Table.SetCell("Host", pServer->GetName() + (pServer == pCurServ ? "*" : "")); Table.SetCell("Port", CString(pServer->GetPort())); Table.SetCell("SSL", (pServer->IsSSL()) ? "SSL" : ""); Table.SetCell("Pass", pServer->GetPass()); } PutStatus(Table); } else { PutStatus("You don't have any servers added."); } } else if (sCommand.Equals("TOPICS")) { if (!m_pNetwork) { PutStatus("You must be connected with a network to use this command"); return; } const vector<CChan*>& vChans = m_pNetwork->GetChans(); CTable Table; Table.AddColumn("Name"); Table.AddColumn("Set By"); Table.AddColumn("Topic"); for (unsigned int a = 0; a < vChans.size(); a++) { CChan* pChan = vChans[a]; Table.AddRow(); Table.SetCell("Name", pChan->GetName()); Table.SetCell("Set By", pChan->GetTopicOwner()); Table.SetCell("Topic", pChan->GetTopic()); } PutStatus(Table); } else if (sCommand.Equals("LISTMODS") || sCommand.Equals("LISTMODULES")) { if (m_pUser->IsAdmin()) { CModules& GModules = CZNC::Get().GetModules(); if (!GModules.size()) { PutStatus("No global modules loaded."); } else { PutStatus("Global modules:"); CTable GTable; GTable.AddColumn("Name"); GTable.AddColumn("Arguments"); for (unsigned int b = 0; b < GModules.size(); b++) { GTable.AddRow(); GTable.SetCell("Name", GModules[b]->GetModName()); GTable.SetCell("Arguments", GModules[b]->GetArgs()); } PutStatus(GTable); } } CModules& Modules = m_pUser->GetModules(); if (!Modules.size()) { PutStatus("Your user has no modules loaded."); } else { PutStatus("User modules:"); CTable Table; Table.AddColumn("Name"); Table.AddColumn("Arguments"); for (unsigned int b = 0; b < Modules.size(); b++) { Table.AddRow(); Table.SetCell("Name", Modules[b]->GetModName()); Table.SetCell("Arguments", Modules[b]->GetArgs()); } PutStatus(Table); } if (m_pNetwork) { CModules& NetworkModules = m_pNetwork->GetModules(); if (NetworkModules.empty()) { PutStatus("This network has no modules loaded."); } else { PutStatus("Network modules:"); CTable Table; Table.AddColumn("Name"); Table.AddColumn("Arguments"); for (unsigned int b = 0; b < NetworkModules.size(); b++) { Table.AddRow(); Table.SetCell("Name", NetworkModules[b]->GetModName()); Table.SetCell("Arguments", NetworkModules[b]->GetArgs()); } PutStatus(Table); } } return; } else if (sCommand.Equals("LISTAVAILMODS") || sCommand.Equals("LISTAVAILABLEMODULES")) { if (m_pUser->DenyLoadMod()) { PutStatus("Access Denied."); return; } if (m_pUser->IsAdmin()) { set<CModInfo> ssGlobalMods; CZNC::Get().GetModules().GetAvailableMods(ssGlobalMods, CModInfo::GlobalModule); if (ssGlobalMods.empty()) { PutStatus("No global modules available."); } else { PutStatus("Global modules:"); CTable GTable; GTable.AddColumn("Name"); GTable.AddColumn("Description"); set<CModInfo>::iterator it; for (it = ssGlobalMods.begin(); it != ssGlobalMods.end(); ++it) { const CModInfo& Info = *it; GTable.AddRow(); GTable.SetCell("Name", (CZNC::Get().GetModules().FindModule(Info.GetName()) ? "*" : " ") + Info.GetName()); GTable.SetCell("Description", Info.GetDescription().Ellipsize(128)); } PutStatus(GTable); } } set<CModInfo> ssUserMods; CZNC::Get().GetModules().GetAvailableMods(ssUserMods); if (!ssUserMods.size()) { PutStatus("No user modules available."); } else { PutStatus("User modules:"); CTable Table; Table.AddColumn("Name"); Table.AddColumn("Description"); set<CModInfo>::iterator it; for (it = ssUserMods.begin(); it != ssUserMods.end(); ++it) { const CModInfo& Info = *it; Table.AddRow(); Table.SetCell("Name", (m_pUser->GetModules().FindModule(Info.GetName()) ? "*" : " ") + Info.GetName()); Table.SetCell("Description", Info.GetDescription().Ellipsize(128)); } PutStatus(Table); } set<CModInfo> ssNetworkMods; CZNC::Get().GetModules().GetAvailableMods(ssNetworkMods, CModInfo::NetworkModule); if (!ssNetworkMods.size()) { PutStatus("No network modules available."); } else { PutStatus("Network modules:"); CTable Table; Table.AddColumn("Name"); Table.AddColumn("Description"); set<CModInfo>::const_iterator it; for (it = ssNetworkMods.begin(); it != ssNetworkMods.end(); ++it) { const CModInfo& Info = *it; Table.AddRow(); Table.SetCell("Name", ((m_pNetwork && m_pNetwork->GetModules().FindModule(Info.GetName())) ? "*" : " ") + Info.GetName()); Table.SetCell("Description", Info.GetDescription().Ellipsize(128)); } PutStatus(Table); } return; } else if (sCommand.Equals("LOADMOD") || sCommand.Equals("LOADMODULE")) { CModInfo::EModuleType eType; CString sType = sLine.Token(1); CString sMod = sLine.Token(2); CString sArgs = sLine.Token(3, true); if (sType.Equals("global")) { eType = CModInfo::GlobalModule; } else if (sType.Equals("user")) { eType = CModInfo::UserModule; } else if (sType.Equals("network")) { eType = CModInfo::NetworkModule; } else { sMod = sType; sArgs = sLine.Token(2, true); sType = "default"; // Will be set correctly later eType = CModInfo::UserModule; } if (m_pUser->DenyLoadMod()) { PutStatus("Unable to load [" + sMod + "]: Access Denied."); return; } if (sMod.empty()) { PutStatus("Usage: LoadMod [type] <module> [args]"); return; } CModInfo ModInfo; CString sRetMsg; if (!CZNC::Get().GetModules().GetModInfo(ModInfo, sMod, sRetMsg)) { PutStatus("Unable to find modinfo [" + sMod + "] [" + sRetMsg + "]"); return; } if (sType.Equals("default")) { eType = ModInfo.GetDefaultType(); } if (eType == CModInfo::GlobalModule && !m_pUser->IsAdmin()) { PutStatus("Unable to load global module [" + sMod + "]: Access Denied."); return; } if (eType == CModInfo::NetworkModule && !m_pNetwork) { PutStatus("Unable to load network module [" + sMod + "] Not connected with a network."); return; } CString sModRet; bool b = false; switch (eType) { case CModInfo::GlobalModule: b = CZNC::Get().GetModules().LoadModule(sMod, sArgs, eType, NULL, NULL, sModRet); break; case CModInfo::UserModule: b = m_pUser->GetModules().LoadModule(sMod, sArgs, eType, m_pUser, NULL, sModRet); break; case CModInfo::NetworkModule: b = m_pNetwork->GetModules().LoadModule(sMod, sArgs, eType, m_pUser, m_pNetwork, sModRet); break; default: sModRet = "Unable to load module [" + sMod + "]: Unknown module type"; } if (b) sModRet = "Loaded module [" + sMod + "] " + sModRet; PutStatus(sModRet); return; } else if (sCommand.Equals("UNLOADMOD") || sCommand.Equals("UNLOADMODULE")) { CModInfo::EModuleType eType = CModInfo::UserModule; CString sType = sLine.Token(1); CString sMod = sLine.Token(2); if (sType.Equals("global")) { eType = CModInfo::GlobalModule; } else if (sType.Equals("user")) { eType = CModInfo::UserModule; } else if (sType.Equals("network")) { eType = CModInfo::NetworkModule; } else { sMod = sType; sType = "default"; } if (m_pUser->DenyLoadMod()) { PutStatus("Unable to unload [" + sMod + "] Access Denied."); return; } if (sMod.empty()) { PutStatus("Usage: UnloadMod [type] <module>"); return; } if (sType.Equals("default")) { CModInfo ModInfo; CString sRetMsg; if (!CZNC::Get().GetModules().GetModInfo(ModInfo, sMod, sRetMsg)) { PutStatus("Unable to find modinfo [" + sMod + "] [" + sRetMsg + "]"); return; } eType = ModInfo.GetDefaultType(); } if (eType == CModInfo::GlobalModule && !m_pUser->IsAdmin()) { PutStatus("Unable to unload global module [" + sMod + "]: Access Denied."); return; } if (eType == CModInfo::NetworkModule && !m_pNetwork) { PutStatus("Unable to unload network module [" + sMod + "] Not connected with a network."); return; } CString sModRet; switch (eType) { case CModInfo::GlobalModule: CZNC::Get().GetModules().UnloadModule(sMod, sModRet); break; case CModInfo::UserModule: m_pUser->GetModules().UnloadModule(sMod, sModRet); break; case CModInfo::NetworkModule: m_pNetwork->GetModules().UnloadModule(sMod, sModRet); break; default: sModRet = "Unable to unload module [" + sMod + "]: Unknown module type"; } PutStatus(sModRet); return; } else if (sCommand.Equals("RELOADMOD") || sCommand.Equals("RELOADMODULE")) { CModInfo::EModuleType eType; CString sType = sLine.Token(1); CString sMod = sLine.Token(2); CString sArgs = sLine.Token(3, true); if (m_pUser->DenyLoadMod()) { PutStatus("Unable to reload modules. Access Denied."); return; } if (sType.Equals("global")) { eType = CModInfo::GlobalModule; } else if (sType.Equals("user")) { eType = CModInfo::UserModule; } else if (sType.Equals("network")) { eType = CModInfo::NetworkModule; } else { sMod = sType; sArgs = sLine.Token(2, true); sType = "default"; // Will be set correctly later eType = CModInfo::UserModule; } if (sMod.empty()) { PutStatus("Usage: ReloadMod [type] <module> [args]"); return; } if (sType.Equals("default")) { CModInfo ModInfo; CString sRetMsg; if (!CZNC::Get().GetModules().GetModInfo(ModInfo, sMod, sRetMsg)) { PutStatus("Unable to find modinfo for [" + sMod + "] [" + sRetMsg + "]"); return; } eType = ModInfo.GetDefaultType(); } if (eType == CModInfo::GlobalModule && !m_pUser->IsAdmin()) { PutStatus("Unable to reload global module [" + sMod + "]: Access Denied."); return; } if (eType == CModInfo::NetworkModule && !m_pNetwork) { PutStatus("Unable to load network module [" + sMod + "] Not connected with a network."); return; } CString sModRet; switch (eType) { case CModInfo::GlobalModule: CZNC::Get().GetModules().ReloadModule(sMod, sArgs, NULL, NULL, sModRet); break; case CModInfo::UserModule: m_pUser->GetModules().ReloadModule(sMod, sArgs, m_pUser, NULL, sModRet); break; case CModInfo::NetworkModule: m_pNetwork->GetModules().ReloadModule(sMod, sArgs, m_pUser, m_pNetwork, sModRet); break; default: sModRet = "Unable to reload module [" + sMod + "]: Unknown module type"; } PutStatus(sModRet); return; } else if ((sCommand.Equals("UPDATEMOD") || sCommand.Equals("UPDATEMODULE")) && m_pUser->IsAdmin() ) { CString sMod = sLine.Token(1); if (sMod.empty()) { PutStatus("Usage: UpdateMod <module>"); return; } PutStatus("Reloading [" + sMod + "] everywhere"); if (CZNC::Get().UpdateModule(sMod)) { PutStatus("Done"); } else { PutStatus("Done, but there were errors, [" + sMod + "] could not be loaded everywhere."); } } else if ((sCommand.Equals("ADDBINDHOST") || sCommand.Equals("ADDVHOST")) && m_pUser->IsAdmin()) { CString sHost = sLine.Token(1); if (sHost.empty()) { PutStatus("Usage: AddBindHost <host>"); return; } if (CZNC::Get().AddBindHost(sHost)) { PutStatus("Done"); } else { PutStatus("The host [" + sHost + "] is already in the list"); } } else if ((sCommand.Equals("REMBINDHOST") || sCommand.Equals("REMVHOST") || sCommand.Equals("DELVHOST")) && m_pUser->IsAdmin()) { CString sHost = sLine.Token(1); if (sHost.empty()) { PutStatus("Usage: RemBindHost <host>"); return; } if (CZNC::Get().RemBindHost(sHost)) { PutStatus("Done"); } else { PutStatus("The host [" + sHost + "] is not in the list"); } } else if ((sCommand.Equals("LISTBINDHOSTS") || sCommand.Equals("LISTVHOSTS")) && (m_pUser->IsAdmin() || !m_pUser->DenySetBindHost())) { const VCString& vsHosts = CZNC::Get().GetBindHosts(); if (vsHosts.empty()) { PutStatus("No bind hosts configured"); return; } CTable Table; Table.AddColumn("Host"); VCString::const_iterator it; for (it = vsHosts.begin(); it != vsHosts.end(); ++it) { Table.AddRow(); Table.SetCell("Host", *it); } PutStatus(Table); } else if ((sCommand.Equals("SETBINDHOST") || sCommand.Equals("SETVHOST")) && (m_pUser->IsAdmin() || !m_pUser->DenySetBindHost())) { CString sHost = sLine.Token(1); if (sHost.empty()) { PutStatus("Usage: SetBindHost <host>"); return; } if (sHost.Equals(m_pUser->GetBindHost())) { PutStatus("You already have this bind host!"); return; } const VCString& vsHosts = CZNC::Get().GetBindHosts(); if (!m_pUser->IsAdmin() && !vsHosts.empty()) { VCString::const_iterator it; bool bFound = false; for (it = vsHosts.begin(); it != vsHosts.end(); ++it) { if (sHost.Equals(*it)) { bFound = true; break; } } if (!bFound) { PutStatus("You may not use this bind host. See [ListBindHosts] for a list"); return; } } m_pUser->SetBindHost(sHost); PutStatus("Set bind host to [" + m_pUser->GetBindHost() + "]"); } else if ((sCommand.Equals("CLEARBINDHOST") || sCommand.Equals("CLEARVHOST")) && (m_pUser->IsAdmin() || !m_pUser->DenySetBindHost())) { m_pUser->SetBindHost(""); PutStatus("Bind Host Cleared"); } else if (sCommand.Equals("PLAYBUFFER")) { if (!m_pNetwork) { PutStatus("You must be connected with a network to use this command"); return; } CString sChan = sLine.Token(1); if (sChan.empty()) { PutStatus("Usage: PlayBuffer <#chan>"); return; } CChan* pChan = m_pNetwork->FindChan(sChan); if (!pChan) { PutStatus("You are not on [" + sChan + "]"); return; } if (!pChan->IsOn()) { PutStatus("You are not on [" + sChan + "] [trying]"); return; } if (pChan->GetBuffer().IsEmpty()) { PutStatus("The buffer for [" + sChan + "] is empty"); return; } pChan->SendBuffer(this); } else if (sCommand.Equals("CLEARBUFFER")) { if (!m_pNetwork) { PutStatus("You must be connected with a network to use this command"); return; } CString sChan = sLine.Token(1); if (sChan.empty()) { PutStatus("Usage: ClearBuffer <#chan>"); return; } CChan* pChan = m_pNetwork->FindChan(sChan); if (!pChan) { PutStatus("You are not on [" + sChan + "]"); return; } const vector<CChan*>& vChans = m_pNetwork->GetChans(); vector<CChan*>::const_iterator it; unsigned int uMatches = 0; for (it = vChans.begin(); it != vChans.end(); ++it) { if (!(*it)->GetName().WildCmp(sChan)) continue; uMatches++; (*it)->ClearBuffer(); } PutStatus("The buffer for [" + CString(uMatches) + "] channels matching [" + sChan + "] has been cleared"); } else if (sCommand.Equals("CLEARALLCHANNELBUFFERS")) { if (!m_pNetwork) { PutStatus("You must be connected with a network to use this command"); return; } vector<CChan*>::const_iterator it; const vector<CChan*>& vChans = m_pNetwork->GetChans(); for (it = vChans.begin(); it != vChans.end(); ++it) { (*it)->ClearBuffer(); } PutStatus("All channel buffers have been cleared"); } else if (sCommand.Equals("SETBUFFER")) { if (!m_pNetwork) { PutStatus("You must be connected with a network to use this command"); return; } CString sChan = sLine.Token(1); if (sChan.empty()) { PutStatus("Usage: SetBuffer <#chan> [linecount]"); return; } unsigned int uLineCount = sLine.Token(2).ToUInt(); const vector<CChan*>& vChans = m_pNetwork->GetChans(); vector<CChan*>::const_iterator it; unsigned int uMatches = 0, uFail = 0; for (it = vChans.begin(); it != vChans.end(); ++it) { if (!(*it)->GetName().WildCmp(sChan)) continue; uMatches++; if (!(*it)->SetBufferCount(uLineCount)) uFail++; } PutStatus("BufferCount for [" + CString(uMatches - uFail) + "] channels was set to [" + CString(uLineCount) + "]"); if (uFail > 0) { PutStatus("Setting BufferCount failed for [" + CString(uFail) + "] channels, " "max buffer count is " + CString(CZNC::Get().GetMaxBufferSize())); } } else if (m_pUser->IsAdmin() && sCommand.Equals("TRAFFIC")) { CZNC::TrafficStatsPair Users, ZNC, Total; CZNC::TrafficStatsMap traffic = CZNC::Get().GetTrafficStats(Users, ZNC, Total); CZNC::TrafficStatsMap::const_iterator it; CTable Table; Table.AddColumn("Username"); Table.AddColumn("In"); Table.AddColumn("Out"); Table.AddColumn("Total"); for (it = traffic.begin(); it != traffic.end(); ++it) { Table.AddRow(); Table.SetCell("Username", it->first); Table.SetCell("In", CString::ToByteStr(it->second.first)); Table.SetCell("Out", CString::ToByteStr(it->second.second)); Table.SetCell("Total", CString::ToByteStr(it->second.first + it->second.second)); } Table.AddRow(); Table.SetCell("Username", "<Users>"); Table.SetCell("In", CString::ToByteStr(Users.first)); Table.SetCell("Out", CString::ToByteStr(Users.second)); Table.SetCell("Total", CString::ToByteStr(Users.first + Users.second)); Table.AddRow(); Table.SetCell("Username", "<ZNC>"); Table.SetCell("In", CString::ToByteStr(ZNC.first)); Table.SetCell("Out", CString::ToByteStr(ZNC.second)); Table.SetCell("Total", CString::ToByteStr(ZNC.first + ZNC.second)); Table.AddRow(); Table.SetCell("Username", "<Total>"); Table.SetCell("In", CString::ToByteStr(Total.first)); Table.SetCell("Out", CString::ToByteStr(Total.second)); Table.SetCell("Total", CString::ToByteStr(Total.first + Total.second)); PutStatus(Table); } else if (sCommand.Equals("UPTIME")) { PutStatus("Running for " + CZNC::Get().GetUptime()); } else if (m_pUser->IsAdmin() && (sCommand.Equals("LISTPORTS") || sCommand.Equals("ADDPORT") || sCommand.Equals("DELPORT"))) { UserPortCommand(sLine); } else { PutStatus("Unknown command [" + sCommand + "] try 'Help'"); } }
virtual bool OnWebRequest(CWebSock& WebSock, const CString& sPageName, CTemplate& Tmpl) { CSmartPtr<CWebSession> spSession = WebSock.GetSession(); if (sPageName == "settings") { // Admin Check if (!spSession->IsAdmin()) { return false; } return SettingsPage(WebSock, Tmpl); } else if (sPageName == "adduser") { // Admin Check if (!spSession->IsAdmin()) { return false; } return UserPage(WebSock, Tmpl); } else if (sPageName == "addnetwork") { CUser* pUser = SafeGetUserFromParam(WebSock); // Admin||Self Check if (!spSession->IsAdmin() && (!spSession->GetUser() || spSession->GetUser() != pUser)) { return false; } if (pUser) { return NetworkPage(WebSock, Tmpl, pUser); } WebSock.PrintErrorPage("No such username"); return true; } 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 if (!spSession->IsAdmin() && (!spSession->GetUser() || spSession->GetUser() != pUser)) { return false; } 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; } 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()) { return false; } if (!WebSock.IsPost()) { // Show the "Are you sure?" page: CString sUser = WebSock.GetParam("user", false); CUser* pUser = CZNC::Get().FindUser(sUser); if (!pUser) { WebSock.PrintErrorPage("No such username"); return true; } Tmpl.SetFile("del_user.tmpl"); Tmpl["Username"] = sUser; return true; } // The "Are you sure?" page has been submitted with "Yes", // so we actually delete the user now: CString sUser = WebSock.GetParam("user"); CUser* pUser = CZNC::Get().FindUser(sUser); if (pUser && pUser == spSession->GetUser()) { WebSock.PrintErrorPage("Please don't delete yourself, suicide is not the answer!"); return true; } else if (CZNC::Get().DeleteUser(sUser)) { WebSock.Redirect("listusers"); return true; } WebSock.PrintErrorPage("No such username"); return true; } else if (sPageName == "edituser") { CString sUserName = SafeGetUserNameParam(WebSock); CUser* pUser = CZNC::Get().FindUser(sUserName); if(!pUser) { if(sUserName.empty()) { pUser = spSession->GetUser(); } // else: the "no such user" message will be printed. } // Admin||Self Check if (!spSession->IsAdmin() && (!spSession->GetUser() || spSession->GetUser() != pUser)) { return false; } if (pUser) { return UserPage(WebSock, Tmpl, pUser); } WebSock.PrintErrorPage("No such username"); return true; } else if (sPageName == "listusers" && spSession->IsAdmin()) { return ListUsersPage(WebSock, Tmpl); } else if (sPageName == "traffic" && spSession->IsAdmin()) { return TrafficPage(WebSock, Tmpl); } else if (sPageName == "index") { return true; } return false; }
void AddNetwork(CIRCNetwork& network) { CUser *user = network.GetUser(); const CString& sUsername = user->GetUserName(); m_msvsNetworks[sUsername].push_back(network.GetName()); }
virtual EModRet OnDeleteNetwork(CIRCNetwork& Network) { DelNV("Enabled_" + Network.GetUser()->GetUserName() + "/" + Network.GetName()); return CONTINUE; }