bool OnLoad(const CString& sArgs, CString& sMessage) override { if (!sArgs.empty()) { SetUsername(sArgs.Token(0)); SetPassword(sArgs.Token(1)); } else { m_sUsername = GetNV("Username"); m_sPassword = GetNV("Password"); } CString sTmp; m_bUseCloakedHost = (sTmp = GetNV("UseCloakedHost")).empty() ? true : sTmp.ToBool(); m_bUseChallenge = (sTmp = GetNV("UseChallenge")).empty() ? true : sTmp.ToBool(); m_bRequestPerms = GetNV("RequestPerms").ToBool(); m_bJoinOnInvite = (sTmp = GetNV("JoinOnInvite")).empty() ? true : sTmp.ToBool(); m_bJoinAfterCloaked = (sTmp = GetNV("JoinAfterCloaked")).empty() ? true : sTmp.ToBool(); // Make sure NVs are stored in config. Note: SetUseCloakedHost() is // called further down. SetUseChallenge(m_bUseChallenge); SetRequestPerms(m_bRequestPerms); SetJoinOnInvite(m_bJoinOnInvite); SetJoinAfterCloaked(m_bJoinAfterCloaked); OnIRCDisconnected(); // reset module's state if (IsIRCConnected()) { // check for usermode +x if we are already connected set<unsigned char> scUserModes = GetNetwork()->GetIRCSock()->GetUserModes(); if (scUserModes.find('x') != scUserModes.end()) m_bCloaked = true; // This will only happen once, and only if the user loads the module // after connecting to IRC. // Also don't notify the user in case he already had mode +x set. if (GetNV("UseCloakedHost").empty()) { if (!m_bCloaked) PutModule( "Notice: Your host will be cloaked the next time you " "reconnect to IRC. " "If you want to cloak your host now, /msg *q Cloak. " "You can set your preference " "with /msg *q Set UseCloakedHost true/false."); m_bUseCloakedHost = true; SetUseCloakedHost(m_bUseCloakedHost); m_bJoinAfterCloaked = true; SetJoinAfterCloaked(m_bJoinAfterCloaked); } else if (m_bUseChallenge) { Cloak(); } WhoAmI(); } else { SetUseCloakedHost(m_bUseCloakedHost); } return true; }
CChan::CChan(const CString& sName, CIRCNetwork* pNetwork, bool bInConfig, CConfig *pConfig) { m_sName = sName.Token(0); m_sKey = sName.Token(1); m_pNetwork = pNetwork; if (!m_pNetwork->IsChan(m_sName)) { m_sName = "#" + m_sName; } m_bInConfig = bInConfig; m_Nick.SetNetwork(m_pNetwork); m_bDetached = false; m_uBufferCount = m_pNetwork->GetUser()->GetBufferCount(); m_bKeepBuffer = m_pNetwork->GetUser()->KeepBuffer(); m_bDisabled = false; Reset(); if (pConfig) { CString sValue; if (pConfig->FindStringEntry("buffer", sValue)) SetBufferCount(sValue.ToUInt(), true); if (pConfig->FindStringEntry("keepbuffer", sValue)) SetKeepBuffer(sValue.ToBool()); if (pConfig->FindStringEntry("detached", sValue)) SetDetached(sValue.ToBool()); if (pConfig->FindStringEntry("autocycle", sValue)) if (sValue.Equals("true")) CUtils::PrintError("WARNING: AutoCycle has been removed, instead try -> LoadModule = autocycle " + sName); if (pConfig->FindStringEntry("key", sValue)) SetKey(sValue); if (pConfig->FindStringEntry("modes", sValue)) SetDefaultModes(sValue); } }
virtual bool OnLoad(const CString& sArgs, CString& sMessage) { if (!sArgs.empty()) { SetUsername(sArgs.Token(0)); SetPassword(sArgs.Token(1)); } else { m_sUsername = GetNV("Username"); m_sPassword = GetNV("Password"); } CString sTmp; m_bUseCloakedHost = (sTmp = GetNV("UseCloakedHost")).empty() ? true : sTmp.ToBool(); m_bUseChallenge = (sTmp = GetNV("UseChallenge")).empty() ? true : sTmp.ToBool(); m_bRequestPerms = GetNV("RequestPerms").ToBool(); OnIRCDisconnected(); // reset module's state if (IsIRCConnected()) { // check for usermode +x if we are already connected set<unsigned char> scUserModes = GetUser()->GetIRCSock()->GetUserModes(); if (scUserModes.find('x') != scUserModes.end()) m_bCloaked = true; OnIRCConnected(); } return true; }
CChan::CChan(const CString& sName, CIRCNetwork* pNetwork, bool bInConfig, CConfig* pConfig) : m_bDetached(false), m_bIsOn(false), m_bAutoClearChanBuffer(pNetwork->GetUser()->AutoClearChanBuffer()), m_bInConfig(bInConfig), m_bDisabled(false), m_bHasBufferCountSet(false), m_bHasAutoClearChanBufferSet(false), m_sName(sName.Token(0)), m_sKey(sName.Token(1)), m_sTopic(""), m_sTopicOwner(""), m_ulTopicDate(0), m_ulCreationDate(0), m_pNetwork(pNetwork), m_Nick(), m_uJoinTries(0), m_sDefaultModes(""), m_msNicks(), m_Buffer(), m_bModeKnown(false), m_mcsModes() { if (!m_pNetwork->IsChan(m_sName)) { m_sName = "#" + m_sName; } m_Nick.SetNetwork(m_pNetwork); m_Buffer.SetLineCount(m_pNetwork->GetUser()->GetChanBufferSize(), true); if (pConfig) { CString sValue; if (pConfig->FindStringEntry("buffer", sValue)) SetBufferCount(sValue.ToUInt(), true); if (pConfig->FindStringEntry("autoclearchanbuffer", sValue)) SetAutoClearChanBuffer(sValue.ToBool()); if (pConfig->FindStringEntry("keepbuffer", sValue)) // XXX Compatibility crap, added in 0.207 SetAutoClearChanBuffer(!sValue.ToBool()); if (pConfig->FindStringEntry("detached", sValue)) SetDetached(sValue.ToBool()); if (pConfig->FindStringEntry("disabled", sValue)) if (sValue.ToBool()) Disable(); if (pConfig->FindStringEntry("autocycle", sValue)) if (sValue.Equals("true")) CUtils::PrintError( "WARNING: AutoCycle has been removed, instead try -> " "LoadModule = autocycle " + sName); if (pConfig->FindStringEntry("key", sValue)) SetKey(sValue); if (pConfig->FindStringEntry("modes", sValue)) SetDefaultModes(sValue); } }
void SetChan(const CString& sLine) { const CString var = sLine.Token(1).AsLower(); CString username = sLine.Token(2); CString chan = sLine.Token(3); CString value = sLine.Token(4, true); if (value.empty()) { PutModule("Usage: setchan <variable> <username> <chan> <value>"); return; } CUser* user = GetUser(username); if (!user) return; CChan* pChan = user->FindChan(chan); if (!pChan) { PutModule("Error: Channel not found: " + chan); return; } if (var == "defmodes") { pChan->SetDefaultModes(value); PutModule("DefModes = " + value); } else if (var == "buffer") { unsigned int i = value.ToUInt(); pChan->SetBufferCount(i); PutModule("Buffer = " + CString(i)); } else if (var == "inconfig") { bool b = value.ToBool(); pChan->SetInConfig(b); PutModule("InConfig = " + CString(b)); } else if (var == "keepbuffer") { bool b = value.ToBool(); pChan->SetKeepBuffer(b); PutModule("KeepBuffer = " + CString(b)); } else if (var == "detached") { bool b = value.ToBool(); if (pChan->IsDetached() != b) { if (b) pChan->DetachUser(); else pChan->AttachUser(); } PutModule("Detached = " + CString(b)); } else PutModule("Error: Unknown variable"); }
CChan::CChan(const CString& sName, CIRCNetwork* pNetwork, bool bInConfig, CConfig *pConfig) { m_sName = sName.Token(0); m_sKey = sName.Token(1); m_pNetwork = pNetwork; if (!m_pNetwork->IsChan(m_sName)) { m_sName = "#" + m_sName; } m_bInConfig = bInConfig; m_Nick.SetNetwork(m_pNetwork); m_bDetached = false; m_bDisabled = false; m_bHasBufferCountSet = false; m_bHasAutoClearChanBufferSet = false; m_Buffer.SetLineCount(m_pNetwork->GetUser()->GetBufferCount(), true); m_bAutoClearChanBuffer = m_pNetwork->GetUser()->AutoClearChanBuffer(); Reset(); if (pConfig) { CString sValue; if (pConfig->FindStringEntry("buffer", sValue)) SetBufferCount(sValue.ToUInt(), true); if (pConfig->FindStringEntry("autoclearchanbuffer", sValue)) SetAutoClearChanBuffer(sValue.ToBool()); if (pConfig->FindStringEntry("keepbuffer", sValue)) SetAutoClearChanBuffer(!sValue.ToBool()); // XXX Compatibility crap, added in 0.207 if (pConfig->FindStringEntry("detached", sValue)) SetDetached(sValue.ToBool()); if (pConfig->FindStringEntry("disabled", sValue)) if (sValue.ToBool()) Disable(); if (pConfig->FindStringEntry("autocycle", sValue)) if (sValue.Equals("true")) CUtils::PrintError("WARNING: AutoCycle has been removed, instead try -> LoadModule = autocycle " + sName); if (pConfig->FindStringEntry("key", sValue)) SetKey(sValue); if (pConfig->FindStringEntry("modes", sValue)) SetDefaultModes(sValue); } }
void SilentCommand(const CString& sLine) { const CString sArg = sLine.Token(1, true); if (!sArg.empty()) { SetNV("silent", CString(sArg.ToBool())); } if (GetNV("silent").ToBool()) { PutModule(t_s("Module messages are disabled")); } else { PutModule(t_s("Module messages are enabled")); } }
void SetAwayCommand(const CString &sLine) { const vector<CClient*> vClients = m_pUser->GetAllClients(); CString sHostname = sLine.Token(1); // Valid value of true or false for setting away/unaway bool sToggleFlag = true; CString sToggleValue = "away"; VCString sReturn; // If the hostname argument isn't passed and only arg is true/false, treat that as sToggleFlag if (sHostname.AsLower() == "true" || sHostname.AsLower() == "false" ) { sToggleFlag = sHostname.ToBool(); sHostname = ""; } unsigned int count = 0; for (vector<CClient*>::const_iterator it = vClients.begin(); it != vClients.end(); ++it) { CClient *pClient = *it; //Set all hosts to away if we encounter an empty hostname //Otherwise, set the flag to the provided second argument value if (pClient->GetRemoteIP().Equals(sHostname)) { if (sLine.Token(2).empty()) { sToggleFlag = !pClient->IsAway(); } else { sToggleFlag = sLine.Token(2).ToBool(); } } if (sHostname.empty() || pClient->GetRemoteIP().Equals(sHostname)) { pClient->SetAway(sToggleFlag); ++count; } } if (!sToggleFlag) { sToggleValue = "unaway"; } if (count == 1) { PutModule(CString(count) + " client has been set " + sToggleValue); } else { PutModule(CString(count) + " clients have been set " + sToggleValue); } }
bool CIRCNetwork::ParseConfig(CConfig *pConfig, CString& sError, bool bUpgrade) { VCString vsList; if (!bUpgrade) { TOption<const CString&> StringOptions[] = { { "nick", &CIRCNetwork::SetNick }, { "altnick", &CIRCNetwork::SetAltNick }, { "ident", &CIRCNetwork::SetIdent }, { "realname", &CIRCNetwork::SetRealName }, { "bindhost", &CIRCNetwork::SetBindHost }, { "encoding", &CIRCNetwork::SetEncoding }, { "quitmsg", &CIRCNetwork::SetQuitMsg }, }; TOption<bool> BoolOptions[] = { { "ircconnectenabled", &CIRCNetwork::SetIRCConnectEnabled }, }; TOption<double> DoubleOptions[] = { { "floodrate", &CIRCNetwork::SetFloodRate }, }; TOption<short unsigned int> SUIntOptions[] = { { "floodburst", &CIRCNetwork::SetFloodBurst }, { "joindelay", &CIRCNetwork::SetJoinDelay }, }; for (const auto& Option : StringOptions) { CString sValue; if (pConfig->FindStringEntry(Option.name, sValue)) (this->*Option.pSetter)(sValue); } for (const auto& Option : BoolOptions) { CString sValue; if (pConfig->FindStringEntry(Option.name, sValue)) (this->*Option.pSetter)(sValue.ToBool()); } for (const auto& Option : DoubleOptions) { double fValue; if (pConfig->FindDoubleEntry(Option.name, fValue)) (this->*Option.pSetter)(fValue); } for (const auto& Option : SUIntOptions) { unsigned short value; if (pConfig->FindUShortEntry(Option.name, value)) (this->*Option.pSetter)(value); } pConfig->FindStringVector("loadmodule", vsList); for (const CString& sValue : vsList) { CString sModName = sValue.Token(0); CString sNotice = "Loading network module [" + sModName + "]"; // XXX Legacy crap, added in ZNC 0.203, modified in 0.207 // Note that 0.203 == 0.207 if (sModName == "away") { sNotice = "NOTICE: [away] was renamed, loading [awaystore] instead"; sModName = "awaystore"; } // XXX Legacy crap, added in ZNC 0.207 if (sModName == "autoaway") { sNotice = "NOTICE: [autoaway] 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"; } CString sModRet; CString sArgs = sValue.Token(1, true); bool bModRet = LoadModule(sModName, sArgs, sNotice, 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 network module [simple_away] instead"; sModName = "simple_away"; // not a fatal error if simple_away is not available LoadModule(sModName, sArgs, sNotice, sModRet); } } else { sError = sModRet; return false; } } } } pConfig->FindStringVector("server", vsList); for (const CString& sServer : vsList) { CUtils::PrintAction("Adding server [" + sServer + "]"); CUtils::PrintStatus(AddServer(sServer)); } pConfig->FindStringVector("trustedserverfingerprint", vsList); for (const CString& sFP : vsList) { AddTrustedFingerprint(sFP); } pConfig->FindStringVector("chan", vsList); for (const CString& sChan : vsList) { AddChan(sChan, true); } CConfig::SubConfig subConf; CConfig::SubConfig::const_iterator subIt; pConfig->FindSubConfig("chan", subConf); for (subIt = subConf.begin(); subIt != subConf.end(); ++subIt) { const CString& sChanName = subIt->first; CConfig* pSubConf = subIt->second.m_pSubConfig; CChan* pChan = new CChan(sChanName, this, true, pSubConf); if (!pSubConf->empty()) { sError = "Unhandled lines in config for User [" + m_pUser->GetUserName() + "], Network [" + GetName() + "], Channel [" + sChanName + "]!"; CUtils::PrintError(sError); CZNC::DumpConfig(pSubConf); return false; } // Save the channel name, because AddChan // deletes the CChannel*, if adding fails sError = pChan->GetName(); if (!AddChan(pChan)) { sError = "Channel [" + sError + "] defined more than once"; CUtils::PrintError(sError); return false; } sError.clear(); } return true; }
bool CIRCNetwork::ParseConfig(CConfig *pConfig, CString& sError, bool bUpgrade) { VCString vsList; VCString::const_iterator vit; if (!bUpgrade) { TOption<const CString&> StringOptions[] = { { "nick", &CIRCNetwork::SetNick }, { "altnick", &CIRCNetwork::SetAltNick }, { "ident", &CIRCNetwork::SetIdent }, { "realname", &CIRCNetwork::SetRealName } }; size_t numStringOptions = sizeof(StringOptions) / sizeof(StringOptions[0]); TOption<bool> BoolOptions[] = { { "ircconnectenabled", &CIRCNetwork::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 < numBoolOptions; i++) { CString sValue; if (pConfig->FindStringEntry(BoolOptions[i].name, sValue)) (this->*BoolOptions[i].pSetter)(sValue.ToBool()); } pConfig->FindStringVector("loadmodule", vsList); for (vit = vsList.begin(); vit != vsList.end(); ++vit) { CString sValue = *vit; CString sModName = sValue.Token(0); // XXX Legacy crap, added in ZNC 0.203 if (sModName == "away") { CUtils::PrintMessage("NOTICE: [away] was renamed, " "loading [autoaway] instead"); sModName = "autoaway"; } CUtils::PrintAction("Loading Module [" + sModName + "]"); CString sModRet; CString sArgs = sValue.Token(1, true); bool bModRet = GetModules().LoadModule(sModName, sArgs, CModInfo::NetworkModule, GetUser(), this, sModRet); CUtils::PrintStatus(bModRet, sModRet); if (!bModRet) { sError = sModRet; return false; } } } pConfig->FindStringVector("server", vsList); for (vit = vsList.begin(); vit != vsList.end(); ++vit) { CUtils::PrintAction("Adding Server [" + *vit + "]"); CUtils::PrintStatus(AddServer(*vit)); } pConfig->FindStringVector("chan", vsList); for (vit = vsList.begin(); vit != vsList.end(); ++vit) { AddChan(*vit, true); } CConfig::SubConfig subConf; CConfig::SubConfig::const_iterator subIt; pConfig->FindSubConfig("chan", subConf); for (subIt = subConf.begin(); subIt != subConf.end(); ++subIt) { const CString& sChanName = subIt->first; CConfig* pSubConf = subIt->second.m_pSubConfig; CChan* pChan = new CChan(sChanName, this, true, pSubConf); if (!pSubConf->empty()) { sError = "Unhandled lines in config for User [" + m_pUser->GetUserName() + "], Network [" + GetName() + "], Channel [" + sChanName + "]!"; CUtils::PrintError(sError); CZNC::DumpConfig(pSubConf); return false; } // Save the channel name, because AddChan // deletes the CChannel*, if adding fails sError = pChan->GetName(); if (!AddChan(pChan)) { sError = "Channel [" + sError + "] defined more than once"; CUtils::PrintError(sError); return false; } sError.clear(); } return true; }
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; }
void OnModCommand(const CString& sLine) override { CString sCommand = sLine.Token(0).AsLower(); if (sCommand == "help") { PutModule("The following commands are available:"); CTable Table; Table.AddColumn("Command"); Table.AddColumn("Description"); Table.AddRow(); Table.SetCell("Command", "Auth [<username> <password>]"); Table.SetCell("Description", "Tries to authenticate you with Q. Both parameters " "are optional."); Table.AddRow(); Table.SetCell("Command", "Cloak"); Table.SetCell( "Description", "Tries to set usermode +x to hide your real hostname."); Table.AddRow(); Table.SetCell("Command", "Status"); Table.SetCell("Description", "Prints the current status of the module."); Table.AddRow(); Table.SetCell("Command", "Update"); Table.SetCell("Description", "Re-requests the current user information from Q."); Table.AddRow(); Table.SetCell("Command", "Set <setting> <value>"); Table.SetCell("Description", "Changes the value of the given setting. See the " "list of settings below."); Table.AddRow(); Table.SetCell("Command", "Get"); Table.SetCell("Description", "Prints out the current configuration. See the list " "of settings below."); PutModule(Table); PutModule("The following settings are available:"); CTable Table2; Table2.AddColumn("Setting"); Table2.AddColumn("Type"); Table2.AddColumn("Description"); Table2.AddRow(); Table2.SetCell("Setting", "Username"); Table2.SetCell("Type", "String"); Table2.SetCell("Description", "Your Q username."); Table2.AddRow(); Table2.SetCell("Setting", "Password"); Table2.SetCell("Type", "String"); Table2.SetCell("Description", "Your Q password."); Table2.AddRow(); Table2.SetCell("Setting", "UseCloakedHost"); Table2.SetCell("Type", "Boolean"); Table2.SetCell("Description", "Whether to cloak your hostname (+x) automatically " "on connect."); Table2.AddRow(); Table2.SetCell("Setting", "UseChallenge"); Table2.SetCell("Type", "Boolean"); Table2.SetCell("Description", "Whether to use the CHALLENGEAUTH mechanism to " "avoid sending passwords in cleartext."); Table2.AddRow(); Table2.SetCell("Setting", "RequestPerms"); Table2.SetCell("Type", "Boolean"); Table2.SetCell( "Description", "Whether to request voice/op from Q on join/devoice/deop."); Table2.AddRow(); Table2.SetCell("Setting", "JoinOnInvite"); Table2.SetCell("Type", "Boolean"); Table2.SetCell("Description", "Whether to join channels when Q invites you."); Table2.AddRow(); Table2.SetCell("Setting", "JoinAfterCloaked"); Table2.SetCell("Type", "Boolean"); Table2.SetCell("Description", "Whether to delay joining channels until after you " "are cloaked."); PutModule(Table2); PutModule( "This module takes 2 optional parameters: <username> " "<password>"); PutModule("Module settings are stored between restarts."); } else if (sCommand == "set") { CString sSetting = sLine.Token(1).AsLower(); CString sValue = sLine.Token(2); if (sSetting.empty() || sValue.empty()) { PutModule("Syntax: Set <setting> <value>"); } else if (sSetting == "username") { SetUsername(sValue); PutModule("Username set"); } else if (sSetting == "password") { SetPassword(sValue); PutModule("Password set"); } else if (sSetting == "usecloakedhost") { SetUseCloakedHost(sValue.ToBool()); PutModule("UseCloakedHost set"); } else if (sSetting == "usechallenge") { SetUseChallenge(sValue.ToBool()); PutModule("UseChallenge set"); } else if (sSetting == "requestperms") { SetRequestPerms(sValue.ToBool()); PutModule("RequestPerms set"); } else if (sSetting == "joinoninvite") { SetJoinOnInvite(sValue.ToBool()); PutModule("JoinOnInvite set"); } else if (sSetting == "joinaftercloaked") { SetJoinAfterCloaked(sValue.ToBool()); PutModule("JoinAfterCloaked set"); } else PutModule("Unknown setting: " + sSetting); } else if (sCommand == "get" || sCommand == "list") { CTable Table; Table.AddColumn("Setting"); Table.AddColumn("Value"); Table.AddRow(); Table.SetCell("Setting", "Username"); Table.SetCell("Value", m_sUsername); Table.AddRow(); Table.SetCell("Setting", "Password"); Table.SetCell("Value", "*****"); // m_sPassword Table.AddRow(); Table.SetCell("Setting", "UseCloakedHost"); Table.SetCell("Value", CString(m_bUseCloakedHost)); Table.AddRow(); Table.SetCell("Setting", "UseChallenge"); Table.SetCell("Value", CString(m_bUseChallenge)); Table.AddRow(); Table.SetCell("Setting", "RequestPerms"); Table.SetCell("Value", CString(m_bRequestPerms)); Table.AddRow(); Table.SetCell("Setting", "JoinOnInvite"); Table.SetCell("Value", CString(m_bJoinOnInvite)); Table.AddRow(); Table.SetCell("Setting", "JoinAfterCloaked"); Table.SetCell("Value", CString(m_bJoinAfterCloaked)); PutModule(Table); } else if (sCommand == "status") { PutModule("Connected: " + CString(IsIRCConnected() ? "yes" : "no")); PutModule("Cloaked: " + CString(m_bCloaked ? "yes" : "no")); PutModule("Authed: " + CString(m_bAuthed ? "yes" : "no")); } else { // The following commands require an IRC connection. if (!IsIRCConnected()) { PutModule("Error: You are not connected to IRC."); return; } if (sCommand == "cloak") { if (!m_bCloaked) Cloak(); else PutModule("Error: You are already cloaked!"); } else if (sCommand == "auth") { if (!m_bAuthed) Auth(sLine.Token(1), sLine.Token(2)); else PutModule("Error: You are already authed!"); } else if (sCommand == "update") { WhoAmI(); PutModule("Update requested."); } else { PutModule("Unknown command. Try 'help'."); } } }
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 }, }; 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 }, { "bouncedccs", &CUser::SetBounceDCCs }, { "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)); } pConfig->FindStringVector("server", vsList); for (vit = vsList.begin(); vit != vsList.end(); ++vit) { CUtils::PrintAction("Adding Server [" + *vit + "]"); CUtils::PrintStatus(AddServer(*vit)); } pConfig->FindStringVector("chan", vsList); for (vit = vsList.begin(); vit != vsList.end(); ++vit) { AddChan(*vit, true); } CString sValue; 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); } } } if (pConfig->FindStringEntry("dcclookupmethod", sValue)) SetUseClientIP(sValue.Equals("Client")); 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("chan", subConf); for (subIt = subConf.begin(); subIt != subConf.end(); ++subIt) { const CString& sChanName = subIt->first; CConfig* pSubConf = subIt->second.m_pSubConfig; CChan* pChan = new CChan(sChanName, this, true, pSubConf); if (!pSubConf->empty()) { sError = "Unhandled lines in config for User [" + GetUserName() + "], Channel [" + sChanName + "]!"; CUtils::PrintError(sError); CZNC::DumpConfig(pSubConf); return false; } // Save the channel name, because AddChan // deletes the CChannel*, if adding fails sError = pChan->GetName(); if (!AddChan(pChan)) { sError = "Channel [" + sError + "] defined more than once"; CUtils::PrintError(sError); return false; } sError.clear(); } 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"; } CUtils::PrintAction("Loading Module [" + sModName + "]"); CString sModRet; CString sArgs = sValue.Token(1, true); bool bModRet = GetModules().LoadModule(sModName, sArgs, this, sModRet); CUtils::PrintStatus(bModRet, sModRet); if (!bModRet) { sError = sModRet; return false; } continue; } return true; }
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 OnLoad(const CString& sArgs, CString& sMessage) override { if (!sArgs.empty() && sArgs != "<hidden>") { SetNV("Password", sArgs); SetArgs("<hidden>"); } if (GetNV("IdentifyCmd").empty()) { SetNV("IdentifyCmd", "NICKSERV IDENTIFY {password}"); } CString sTmp; m_bJoinAfterIdentified = (sTmp = GetNV("JoinAfterIdentified")).empty() ? false : sTmp.ToBool(); return true; }
void Set(const CString& sLine) { const CString var = sLine.Token(1).AsLower(); CString username = sLine.Token(2); CString value = sLine.Token(3, true); if (value.empty()) { PutModule("Usage: set <variable> <username> <value>"); return; } CUser* user = GetUser(username); if (!user) return; if (var == "nick") { user->SetNick(value); PutModule("Nick = " + value); } else if (var == "altnick") { user->SetAltNick(value); PutModule("AltNick = " + value); } else if (var == "ident") { user->SetIdent(value); PutModule("Ident = " + value); } else if (var == "realname") { user->SetRealName(value); PutModule("RealName = " + value); } else if (var == "vhost") { user->SetVHost(value); PutModule("VHost = " + value); } else if (var == "multiclients") { bool b = value.ToBool(); user->SetMultiClients(b); PutModule("MultiClients = " + CString(b)); } else if (var == "bouncedccs") { bool b = value.ToBool(); user->SetBounceDCCs(b); PutModule("BounceDCCs = " + CString(b)); } else if (var == "useclientip") { bool b = value.ToBool(); user->SetUseClientIP(b); PutModule("UseClientIP = " + CString(b)); } else if (var == "denyloadmod") { bool b = value.ToBool(); user->SetDenyLoadMod(b); PutModule("DenyLoadMod = " + CString(b)); } else if (var == "defaultchanmodes") { user->SetDefaultChanModes(value); PutModule("DefaultChanModes = " + value); } else if (var == "quitmsg") { user->SetQuitMsg(value); PutModule("QuitMsg = " + value); } else if (var == "buffercount") { unsigned int i = value.ToUInt(); user->SetBufferCount(i); PutModule("BufferCount = " + value); } else if (var == "keepbuffer") { bool b = value.ToBool(); user->SetKeepBuffer(b); PutModule("KeepBuffer = " + CString(b)); } else if (var == "password") { const CString sSalt = CUtils::GetSalt(); const CString sHash = CUser::SaltedHash(value, sSalt); user->SetPass(sHash, CUser::HASH_DEFAULT, sSalt); PutModule("Password has been changed!!"); } else PutModule("Error: Unknown variable"); }