virtual bool OnLoad(const CString& sArgs, CString& sMessage) { // Load the chans from the command line unsigned int a = 0; VCString vsChans; sArgs.Split(" ", vsChans, false); for (VCString::const_iterator it = vsChans.begin(); it != vsChans.end(); ++it) { CString sName = "Args"; sName += CString(a); AddUser(sName, "*", *it); } // Load the saved users for (MCString::iterator it = BeginNV(); it != EndNV(); it++) { const CString& sLine = it->second; CAutoVoiceUser* pUser = new CAutoVoiceUser; if (!pUser->FromString(sLine) || FindUser(pUser->GetUsername().AsLower())) { delete pUser; } else { m_msUsers[pUser->GetUsername().AsLower()] = pUser; } } return true; }
void BootStrap(T *pTarget, const CString& sContent) { if (!pTarget->GetBuffer().IsEmpty()) return; // in this case the module was probably reloaded VCString vsLines; VCString::iterator it; sContent.Split("\n", vsLines); for (it = vsLines.begin(); it != vsLines.end(); ++it) { CString sLine(*it); sLine.Trim(); if (sLine[0] == '@' && it+1 != vsLines.end()) { CString sTimestamp = sLine.Token(0); sTimestamp.TrimLeft("@"); timeval ts; ts.tv_sec = sTimestamp.Token(0, false, ",").ToLongLong(); ts.tv_usec = sTimestamp.Token(1, false, ",").ToLong(); CString sFormat = sLine.Token(1, true); CString sText(*++it); sText.Trim(); pTarget->AddBuffer(sFormat, sText, &ts); } else { // Old format, escape the line and use as is. pTarget->AddBuffer(_NAMEDFMT(sLine)); } } }
bool BootStrap(CChan *pChan) { CString sFile; if (DecryptChannel(pChan->GetName(), sFile)) { if (!pChan->GetBuffer().empty()) return(true); // reloaded a module probably in this case, so just verify we can decrypt the file VCString vsLines; VCString::iterator it; sFile.Split("\n", vsLines); for (it = vsLines.begin(); it != vsLines.end(); ++it) { CString sLine(*it); sLine.Trim(); pChan->AddBuffer(sLine); } } else { m_sPassword = ""; CUtils::PrintError("[" + GetModName() + ".so] Failed to Decrypt [" + pChan->GetName() + "]"); return(false); } return(true); }
void ProcessMail() { EmailST tmp; tmp.sUidl = (char *)CMD5(m_sMailBuffer.Left(255)); VCString vsLines; VCString::iterator it; m_sMailBuffer.Split("\n", vsLines); for (it = vsLines.begin(); it != vsLines.end(); it++) { CString sLine(*it); sLine.Trim(); if (sLine.empty()) break; // out of the headers if (sLine.Equals("From: ", false, 6)) tmp.sFrom = sLine.substr(6, CString::npos); else if (sLine.Equals("Subject: ", false, 9)) tmp.sSubject = sLine.substr(9, CString::npos); if ((!tmp.sFrom.empty()) && (!tmp.sSubject.empty())) break; } tmp.iSize = m_sMailBuffer.length(); m_vEmails.push_back(tmp); }
virtual bool OnLoad(const CString& sArgs, CString& sMessage) { VCString vsChans; VCString::const_iterator it; sArgs.Split(" ", vsChans, false); for (it = vsChans.begin(); it != vsChans.end(); ++it) { if (it->StrCmp("saslauthd") || it->StrCmp("auxprop")) { method += *it + " "; } else { CUtils::PrintError("Ignoring invalid SASL pwcheck method: " + *it); sMessage = "Ignored invalid SASL pwcheck method"; } } method.TrimRight(); if (method.empty()) { sMessage = "Need a pwcheck method as argument (saslauthd, auxprop)"; return false; } if (sasl_server_init(NULL, NULL) != SASL_OK) { sMessage = "SASL Could Not Be Initialized - Halting Startup"; return false; } return true; }
void OnModCommand(const CString& sCmdLine) override { CString sCommand = sCmdLine.Token(0); CString sArgs = sCmdLine.Token(1, true); if (sCommand.Equals("dumpbuff")) { // for testing purposes - hidden from help CString sFile; CString sName; if (DecryptBuffer(GetPath(sArgs), sFile, sName)) { VCString vsLines; VCString::iterator it; sFile.Split("\n", vsLines); for (it = vsLines.begin(); it != vsLines.end(); ++it) { CString sLine(*it); sLine.Trim(); PutModule("[" + sLine + "]"); } } PutModule("//!-- EOF " + sArgs); } else { HandleCommand(sCmdLine); } }
virtual bool OnLoad(const CString& sArgs, CString& sMessage) { VCString vsChans; sArgs.Split(" ", vsChans, false); for (VCString::const_iterator it = vsChans.begin(); it != vsChans.end(); ++it) { CString sAdd = *it; bool bNegated = sAdd.TrimPrefix("!"); CString sChan = sAdd.Token(0); CString sHost = sAdd.Token(1, true); if (!Add(bNegated, sChan, sHost)) { PutModule("Unable to add [" + *it + "]"); } } // Load our saved settings, ignore errors MCString::iterator it; for (it = BeginNV(); it != EndNV(); ++it) { CString sAdd = it->first; bool bNegated = sAdd.TrimPrefix("!"); CString sChan = sAdd.Token(0); CString sHost = sAdd.Token(1, true); Add(bNegated, sChan, sHost); } return true; }
virtual bool OnLoad(const CString& sArgs, CString& sMessage) { VCString vsArgs; VCString::const_iterator it; sArgs.Split(" ", vsArgs, false); for (it = vsArgs.begin(); it != vsArgs.end(); ++it) { if (it->Equals("saslauthd") || it->Equals("auxprop")) { m_sMethod += *it + " "; } else { CUtils::PrintError("Ignoring invalid SASL pwcheck method: " + *it); sMessage = "Ignored invalid SASL pwcheck method"; } } m_sMethod.TrimRight(); if (m_sMethod.empty()) { sMessage = "Need a pwcheck method as argument (saslauthd, auxprop)"; return false; } if (sasl_server_init(NULL, NULL) != SASL_OK) { sMessage = "SASL Could Not Be Initialized - Halting Startup"; return false; } m_cbs[0].id = SASL_CB_GETOPT; m_cbs[0].proc = reinterpret_cast<int(*)()>(CSASLAuthMod::getopt); m_cbs[0].context = this; m_cbs[1].id = SASL_CB_LIST_END; m_cbs[1].proc = NULL; m_cbs[1].context = NULL; return true; }
virtual bool OnBoot() { const vector<CListener*>& vListeners = CZNC::Get().GetListeners(); vector<CListener*>::const_iterator it; // We need the SSL_VERIFY_PEER flag on all listeners, or else // the client doesn't send a ssl cert for (it = vListeners.begin(); it != vListeners.end(); ++it) (*it)->GetRealListener()->SetRequireClientCertFlags(SSL_VERIFY_PEER); MCString::iterator it1; for (it1 = BeginNV(); it1 != EndNV(); ++it1) { VCString vsKeys; VCString::iterator it2; if (CZNC::Get().FindUser(it1->first) == NULL) { DEBUG("Unknown user in saved data [" + it1->first + "]"); continue; } it1->second.Split(" ", vsKeys, false); for (it2 = vsKeys.begin(); it2 != vsKeys.end(); ++it2) { m_PubKeys[it1->first].insert(*it2); } } return true; }
CString CLogMod::JoinRules(const CString& sSeparator) const { VCString vsRules; for (const CLogRule& Rule : m_vRules) { vsRules.push_back(Rule.ToString()); } return sSeparator.Join(vsRules.begin(), vsRules.end()); }
bool CDir::MakeDir(const CString& sPath, mode_t iMode) { #ifdef _WIN32 if (sPath.empty()) return false; CString sFixedPath = sPath; sFixedPath.Replace("/", "\\"); int iResult = SHCreateDirectoryEx(0, sFixedPath.c_str(), NULL); return (iResult == ERROR_SUCCESS || iResult == ERROR_FILE_EXISTS || iResult == ERROR_ALREADY_EXISTS); #else CString sDir; VCString dirs; VCString::iterator it; // Just in case someone tries this... if (sPath.empty()) return false; // If this is an absolute path, we need to handle this now! if (sPath.Left(1) == "/") sDir = "/"; // For every single subpath, do... sPath.Split("/", dirs, false); for (it = dirs.begin(); it != dirs.end(); ++it) { // Add this to the path we already created sDir += *it; int i = mkdir(sDir.c_str(), iMode); if (i != 0) { // All errors except EEXIST are fatal if (errno != EEXIST) return false; // If it's EEXIST we have to make sure it's a dir if (!CFile::IsDir(sDir)) return false; } sDir += "/"; } // All went well return true; #endif }
int CChan::AddNicks(const CString& sNicks) { int iRet = 0; VCString vsNicks; VCString::iterator it; sNicks.Split(" ", vsNicks, false); for (it = vsNicks.begin(); it != vsNicks.end(); ++it) { if (AddNick(*it)) { iRet++; } } return iRet; }
CString CChan::GetOptions() const { VCString vsRet; if (IsDetached()) { vsRet.push_back("Detached"); } if (AutoClearChanBuffer()) { if (HasAutoClearChanBufferSet()) { vsRet.push_back("AutoClearChanBuffer"); } else { vsRet.push_back("AutoClearChanBuffer (default)"); } } return CString(", ").Join(vsRet.begin(), vsRet.end()); }
bool BootStrap(CChan *pChan) { CString sFile; if (DecryptChannel(pChan->GetName(), sFile)) { if (!pChan->GetBuffer().IsEmpty()) return(true); // reloaded a module probably in this case, so just verify we can decrypt the file VCString vsLines; VCString::iterator it; sFile.Split("\n", vsLines); for (it = vsLines.begin(); it != vsLines.end(); ++it) { CString sLine(*it); sLine.Trim(); if (sLine[0] == '@' && it+1 != vsLines.end()) { CString sTimestamp = sLine.Token(0); sTimestamp.TrimLeft("@"); timeval ts; ts.tv_sec = sTimestamp.Token(0, false, ",").ToLongLong(); ts.tv_usec = sTimestamp.Token(1, false, ",").ToLong(); CString sFormat = sLine.Token(1, true); CString sText(*++it); sText.Trim(); pChan->AddBuffer(sFormat, sText, &ts); } else { // Old format, escape the line and use as is. pChan->AddBuffer(_NAMEDFMT(sLine)); } } } else { m_sPassword = ""; CUtils::PrintError("[" + GetModName() + ".so] Failed to Decrypt [" + pChan->GetName() + "]"); return(false); } return(true); }
virtual bool OnLoad(const CString& sArgs, CString& sMessage) { VCString vsChans; sArgs.Split(" ", vsChans, false); for (VCString::const_iterator it = vsChans.begin(); it != vsChans.end(); ++it) { if (!Add(*it)) { PutModule("Unable to add [" + *it + "]"); } } // Load our saved settings, ignore errors MCString::iterator it; for (it = BeginNV(); it != EndNV(); ++it) { Add(it->first); } return true; }
bool CStickyChan::OnLoad(const CString& sArgs, CString& sMessage) { VCString vsChans; VCString::iterator it; sArgs.Split(",", vsChans, false); for (it = vsChans.begin(); it != vsChans.end(); ++it) { CString sChan = it->Token(0); CString sKey = it->Token(1, true); SetNV(sChan, sKey); } // Since we now have these channels added, clear the argument list SetArgs(""); AddTimer(RunTimer, "StickyChanTimer", 15); return(true); }
virtual EModRet OnUserRaw(CString& sLine) { //Handle ISON if (sLine.Token(0).Equals("ison")) { VCString vsNicks; VCString::const_iterator it; // Get the list of nicks which are being asked for sLine.Token(1, true).TrimLeft_n(":").Split(" ", vsNicks, false); CString sBNCNicks; for (it = vsNicks.begin(); it != vsNicks.end(); ++it) { if (IsOnlineModNick(*it)) { sBNCNicks += " " + *it; } } // Remove the leading space sBNCNicks.LeftChomp(); if (!m_pNetwork->GetIRCSock()) { // if we are not connected to any IRC server, send // an empty or module-nick filled response. PutUser(":irc.znc.in 303 " + m_pClient->GetNick() + " :" + sBNCNicks); } else { // We let the server handle this request and then act on // the 303 response from the IRC server. m_ISONRequests.push_back(sBNCNicks); } } //Handle WHOIS if (sLine.Token(0).Equals("whois")) { CString sNick = sLine.Token(1); if (IsOnlineModNick(sNick)) { PutUser(":znc.in 311 " + m_pNetwork->GetCurNick() + " " + sNick + " " + sNick + " znc.in * :" + sNick); PutUser(":znc.in 312 " + m_pNetwork->GetCurNick() + " " + sNick + " *.znc.in :Bouncer"); PutUser(":znc.in 318 " + m_pNetwork->GetCurNick() + " " + sNick + " :End of /WHOIS list."); return HALT; } } return CONTINUE; }
void Replay(const CString & sChan) { CString sFile; PutUser(":***[email protected] PRIVMSG " + sChan + " :Buffer Playback..."); if (DecryptChannel(sChan, sFile)) { VCString vsLines; VCString::iterator it; sFile.Split("\n", vsLines); for (it = vsLines.begin(); it != vsLines.end(); ++it) { CString sLine(*it); sLine.Trim(); PutUser(sLine); } } PutUser(":***[email protected] PRIVMSG " + sChan + " :Playback Complete."); }
void SetMechanismCommand(const CString& sLine) { CString sMechanisms = sLine.Token(1, true).AsUpper(); if (!sMechanisms.empty()) { VCString vsMechanisms; sMechanisms.Split(" ", vsMechanisms); for (VCString::const_iterator it = vsMechanisms.begin(); it != vsMechanisms.end(); ++it) { if (!SupportsMechanism(*it)) { PutModule("Unsupported mechanism: " + *it); return; } } SetNV(NV_MECHANISMS, sMechanisms); } PutModule("Current mechanisms set: " + GetMechanismsString()); }
bool ConvertCharset(const VCString& vsFrom, const CString& sTo, CString& sData) { CString sDataCopy(sData); if(!m_bForce) { // check whether sData already is encoded with the right charset: iconv_t icTest = iconv_open(sTo.c_str(), sTo.c_str()); if(icTest != (iconv_t)-1) { size_t uTest = GetConversionLength(icTest, sData); iconv_close(icTest); if(uTest != (size_t)-1 && uTest != (size_t)-2) { DEBUG("charset: [" + sData.Escape_n(CString::EURL) + "] is valid [" + sTo + "] already."); return true; } } } bool bConverted = false; // try all possible source charsets: for(VCString::const_iterator itf = vsFrom.begin(); itf != vsFrom.end(); ++itf) { if(ConvertCharset(*itf, sTo, sDataCopy)) { // conversion successful! sData = sDataCopy; bConverted = true; break; } else { // reset string and try the next charset: sDataCopy = sData; } } return bConverted; }
CString CMessage::GetParamsColon(unsigned int uIdx, unsigned int uLen) const { if (m_vsParams.empty() || uLen == 0) { return ""; } if (uLen > m_vsParams.size() - uIdx - 1) { uLen = m_vsParams.size() - uIdx; } VCString vsParams; unsigned uParams = m_vsParams.size(); for (unsigned int i = uIdx; i < uIdx + uLen; ++i) { CString sParam = m_vsParams[i]; if (i == uParams - 1 && (m_bColon || sParam.empty() || sParam.StartsWith(":") || sParam.Contains(" "))) { sParam = ":" + sParam; } vsParams.push_back(sParam); } return CString(" ").Join(vsParams.begin(), vsParams.end()); }
virtual bool OnLoad(const CString& sArgs, CString& sMessage) { OnBoot(); MCString::iterator it; for (it = BeginNV(); it != EndNV(); it++) { VCString vsKeys; VCString::iterator it2; if (CZNC::Get().FindUser(it->first) == NULL) { DEBUG("Unknown user in saved data [" + it->first + "]"); continue; } it->second.Split(" ", vsKeys, false); for (it2 = vsKeys.begin(); it2 != vsKeys.end(); it2++) { m_PubKeys[it->first].insert(*it2); } } return true; }
bool CDir::MakeDir(const CString& sPath, mode_t iMode) { CString sDir; VCString dirs; VCString::iterator it; // Just in case someone tries this... if (sPath.empty()) { errno = ENOENT; return false; } // If this is an absolute path, we need to handle this now! if (sPath.StartsWith("/")) sDir = "/"; // For every single subpath, do... sPath.Split("/", dirs, false); for (it = dirs.begin(); it != dirs.end(); ++it) { // Add this to the path we already created sDir += *it; int i = mkdir(sDir.c_str(), iMode); if (i != 0) { // All errors except EEXIST are fatal if (errno != EEXIST) return false; // If it's EEXIST we have to make sure it's a dir if (!CFile::IsDir(sDir)) return false; } sDir += "/"; } // All went well return true; }
virtual void OnModCommand(const CString& sCmdLine) { CString sCommand = sCmdLine.Token(0); CString sArgs = sCmdLine.Token(1, true); if (sCommand.Equals("setpass")) { PutModule("Password set to [" + sArgs + "]"); m_sPassword = CBlowfish::MD5(sArgs); } else if (sCommand.Equals("dumpbuff")) { CString sFile; if (DecryptChannel(sArgs, sFile)) { VCString vsLines; VCString::iterator it; sFile.Split("\n", vsLines); for (it = vsLines.begin(); it != vsLines.end(); ++it) { CString sLine(*it); sLine.Trim(); PutModule("[" + sLine + "]"); } } PutModule("//!-- EOF " + sArgs); } else if (sCommand.Equals("replay")) { Replay(sArgs); PutModule("Replayed " + sArgs); } else if (sCommand.Equals("save")) { SaveBufferToDisk(); PutModule("Done."); } else PutModule("Unknown command [" + sCommand + "]"); }
bool BootStrap() { CString sFile; if (DecryptMessages(sFile)) { VCString vsLines; VCString::iterator it; sFile.Split("\n", vsLines); for (it = vsLines.begin(); it != vsLines.end(); ++it) { CString sLine(*it); sLine.Trim(); AddMessage(sLine); } } else { m_sPassword = ""; CUtils::PrintError("[" + GetModName() + ".so] Failed to Decrypt Messages"); return(false); } return(true); }
bool OnLoad(const CString& sArgs, CString& sMessage) override { VCString vArgs; VCString::iterator it; MCString::iterator it2; // Load saved settings for (it2 = BeginNV(); it2 != EndNV(); ++it2) { // Ignore errors Block(it2->first); } // Parse arguments, each argument is a user name to block sArgs.Split(" ", vArgs, false); for (it = vArgs.begin(); it != vArgs.end(); ++it) { if (!Block(*it)) { sMessage = "Could not block [" + *it + "]"; return false; } } return true; }
virtual bool OnWebRequest(CWebSock& WebSock, const CString& sPageName, CTemplate& Tmpl) { if (sPageName != "index") { // only accept requests to /mods/perform/ return false; } if (WebSock.IsPost()) { VCString vsPerf; WebSock.GetRawParam("perform", true).Split("\n", vsPerf, false); m_vPerform.clear(); for (VCString::const_iterator it = vsPerf.begin(); it != vsPerf.end(); ++it) m_vPerform.push_back(ParsePerform(*it)); Save(); } for (VCString::const_iterator it = m_vPerform.begin(); it != m_vPerform.end(); ++it) { CTemplate& Row = Tmpl.AddRow("PerformLoop"); Row["Perform"] = *it; } return true; }
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 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; }
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; }