Example #1
0
bool CClient::OnJoinMessage(CJoinMessage& Message) {
    CString sChans = Message.GetTarget();
    CString sKeys = Message.GetKey();

    VCString vsChans;
    sChans.Split(",", vsChans, false);
    sChans.clear();

    VCString vsKeys;
    sKeys.Split(",", vsKeys, true);
    sKeys.clear();

    for (unsigned int a = 0; a < vsChans.size(); a++) {
        Message.SetTarget(vsChans[a]);
        Message.SetKey((a < vsKeys.size()) ? vsKeys[a] : "");
        if (m_pNetwork) {
            // May be nullptr.
            Message.SetChan(m_pNetwork->FindChan(vsChans[a]));
        }
        bool bContinue = false;
        NETWORKMODULECALL(OnUserJoinMessage(Message), m_pUser, m_pNetwork, this,
                          &bContinue);
        if (bContinue) continue;

        CString sChannel = Message.GetTarget();
        CString sKey = Message.GetKey();

        if (m_pNetwork) {
            CChan* pChan = m_pNetwork->FindChan(sChannel);
            if (pChan) {
                if (pChan->IsDetached())
                    pChan->AttachUser(this);
                else
                    pChan->JoinUser(sKey);
                continue;
            } else if (!sChannel.empty()) {
                pChan = new CChan(sChannel, m_pNetwork, false);
                if (m_pNetwork->AddChan(pChan)) {
                    pChan->SetKey(sKey);
                }
            }
        }

        if (!sChannel.empty()) {
            sChans += (sChans.empty()) ? sChannel : CString("," + sChannel);

            if (!vsKeys.empty()) {
                sKeys += (sKeys.empty()) ? sKey : CString("," + sKey);
            }
        }
    }

    Message.SetTarget(sChans);
    Message.SetKey(sKeys);

    return sChans.empty();
}
Example #2
0
CString getBasePath()
{
	CString homepath;

#if defined(_WIN32) || defined(_WIN64)
	// Get the path.
	char path[MAX_PATH];
	GetModuleFileNameA(0, path, MAX_PATH);

	// Find the program exe and remove it from the path.
	// Assign the path to homepath.
	homepath = path;
	int pos = homepath.findl('\\');
	if (pos == -1) homepath.clear();
	else if (pos != (homepath.length() - 1))
		homepath.removeI(++pos, homepath.length());
#else
	// Get the path to the program.
	char path[ 260 ];
	memset((void*)path, 0, 260);
	readlink("/proc/self/exe", path, sizeof(path));

	// Assign the path to homepath.
	char* end = strrchr(path, '/');
	if (end != 0)
	{
		end++;
		if (end != 0) *end = '\0';
		homepath = path;
	}
#endif

	return homepath;
}
Example #3
0
int CSocket::sendData(CString& data)
{
	int intError = 0;
	int size = 0;

	// Make sure the socket is connected!
	if (properties.state == SOCKET_STATE_DISCONNECTED)
		return SOCKET_INVALID;

	do
	{
		// See if we can send data.
		// If we can't, return how many bytes we did send.
		fd_set set;
		struct timeval tm;
		tm.tv_sec = tm.tv_usec = 0;
		FD_ZERO(&set);
		FD_SET(properties.handle, &set);
		select(properties.handle + 1, 0, &set, 0, &tm);
		if (!FD_ISSET(properties.handle, &set))
			return size;

		// Send our data, yay!
		int sent = 0;
		if ((sent = ::send(properties.handle, data.text(), data.length(), 0)) == SOCKET_ERROR)
		{
			intError = identifyError();
			switch (intError)
			{
				case ENETDOWN:
				case ENETRESET:
				case ENOTCONN:
				case EHOSTUNREACH:
				case ECONNABORTED:
				case ECONNRESET:
				case ETIMEDOUT:
					// Destroy the bad socket and create a new one.
					disconnect();
					return intError;
					break;
			}
			if (intError == EAGAIN || intError == EWOULDBLOCK || intError == EINPROGRESS) return size;
			disconnect();
			return intError;
		}

		// Remove what we sent.
		// Increase size by how much we sent.
		if (sent >= data.length())
			data.clear();
		else if (sent > 0)
			data.removeI(0, sent);
		size += sent;

	// Repeat while data is still left.
	} while (data.length() > 0 && intError == 0);

	// Return how much data was ultimately sent.
	return size;
}
Example #4
0
bool CClient::OnPartMessage(CPartMessage& Message) {
    CString sChans = Message.GetTarget();

    VCString vsChans;
    sChans.Split(",", vsChans, false);
    sChans.clear();

    for (CString& sChan : vsChans) {
        bool bContinue = false;
        Message.SetTarget(sChan);
        NETWORKMODULECALL(OnUserPartMessage(Message), m_pUser, m_pNetwork, this,
                          &bContinue);
        if (bContinue) continue;

        sChan = Message.GetTarget();

        CChan* pChan = m_pNetwork ? m_pNetwork->FindChan(sChan) : nullptr;

        if (pChan && !pChan->IsOn()) {
            PutStatusNotice("Removing channel [" + sChan + "]");
            m_pNetwork->DelChan(sChan);
        } else {
            sChans += (sChans.empty()) ? sChan : CString("," + sChan);
        }
    }

    if (sChans.empty()) {
        return true;
    }

    Message.SetTarget(sChans);

    return false;
}
Example #5
0
bool CTemplate::PrintString(CString& sRet) {
	sRet.clear();
	stringstream sStream;
	bool bRet = Print(sStream);

	sRet = sStream.str();

	return bRet;
}
Example #6
0
    void reload(CWizDatabase& db)
    {
        db.DocumentFromGUID(m_data.strGUID, m_data);
        m_abstract = WIZABSTRACT();
        m_tags.clear();

        setText("");    //force repaint
        setText(m_data.strTitle);
    }
Example #7
0
void loadServerMessage()
{
	CStringList fileData;
	if(!fileData.load("servermessage.html"))
		return;

	serverMessage.clear();
	for(int i = 0; i < fileData.count(); i++)
		serverMessage << fileData[i] << " ";
}
Example #8
0
ModHandle CModules::OpenModule(const CString& sModule, const CString& sModPath, bool &bVersionMismatch,
                               CModInfo& Info, CString& sRetMsg) {
    // Some sane defaults in case anything errors out below
    bVersionMismatch = false;
    sRetMsg.clear();

    for (unsigned int a = 0; a < sModule.length(); a++) {
        if (((sModule[a] < '0') || (sModule[a] > '9')) && ((sModule[a] < 'a') || (sModule[a] > 'z')) && ((sModule[a] < 'A') || (sModule[a] > 'Z')) && (sModule[a] != '_')) {
            sRetMsg = "Module names can only contain letters, numbers and underscores, [" + sModule + "] is invalid.";
            return NULL;
        }
    }

#ifndef _WIN32
    // The second argument to dlopen() has a long history. It seems clear
    // that (despite what the man page says) we must include either of
    // RTLD_NOW and RTLD_LAZY and either of RTLD_GLOBAL and RTLD_LOCAL.
    //
    // RTLD_NOW vs. RTLD_LAZY: We use RTLD_NOW to avoid znc dying due to
    // failed symbol lookups later on. Doesn't really seem to have much of a
    // performance impact.
    //
    // RTLD_GLOBAL vs. RTLD_LOCAL: If perl is loaded with RTLD_LOCAL and later on
    // loads own modules (which it apparently does with RTLD_LAZY), we will die in a
    // name lookup since one of perl's symbols isn't found. That's worse
    // than any theoretical issue with RTLD_GLOBAL.
    ModHandle p = dlopen((sModPath).c_str(), RTLD_NOW | RTLD_GLOBAL);
#else
    ModHandle p = dlopen((sModPath).c_str(), RTLD_NOW | RTLD_LOCAL);
#endif

    if (!p) {
        sRetMsg = "Unable to open module [" + sModule + "] [" + dlerror() + "]";
        return NULL;
    }

    typedef bool (*InfoFP)(double, CModInfo&);
    InfoFP ZNCModInfo = (InfoFP) dlsym(p, "ZNCModInfo");

    if (!ZNCModInfo) {
        dlclose(p);
        sRetMsg = "Could not find ZNCModInfo() in module [" + sModule + "]";
        return NULL;
    }

    if (ZNCModInfo(CModule::GetCoreVersion(), Info)) {
        sRetMsg = "";
        bVersionMismatch = false;
    } else {
        bVersionMismatch = true;
        sRetMsg = "Version mismatch, recompile this module.";
    }

    return p;
}
Example #9
0
File: Message.cpp Project: BtbN/znc
void CMessage::Parse(CString sMessage) {
    // <tags>
    m_mssTags.clear();
    if (sMessage.StartsWith("@")) {
        VCString vsTags;
        sMessage.Token(0).TrimPrefix_n("@").Split(";", vsTags, false);
        for (const CString& sTag : vsTags) {
            CString sKey = sTag.Token(0, false, "=", true);
            CString sValue = sTag.Token(1, true, "=", true);
            m_mssTags[sKey] =
                sValue.Escape(CString::EMSGTAG, CString::CString::EASCII);
        }
        sMessage = sMessage.Token(1, true);
    }

    //  <message>  ::= [':' <prefix> <SPACE> ] <command> <params> <crlf>
    //  <prefix>   ::= <servername> | <nick> [ '!' <user> ] [ '@' <host> ]
    //  <command>  ::= <letter> { <letter> } | <number> <number> <number>
    //  <SPACE>    ::= ' ' { ' ' }
    //  <params>   ::= <SPACE> [ ':' <trailing> | <middle> <params> ]
    //  <middle>   ::= <Any *non-empty* sequence of octets not including SPACE
    //                 or NUL or CR or LF, the first of which may not be ':'>
    //  <trailing> ::= <Any, possibly *empty*, sequence of octets not including
    //                   NUL or CR or LF>

    // <prefix>
    if (sMessage.TrimPrefix(":")) {
        m_Nick.Parse(sMessage.Token(0));
        sMessage = sMessage.Token(1, true);
    }

    // <command>
    m_sCommand = sMessage.Token(0);
    sMessage = sMessage.Token(1, true);

    // <params>
    m_bColon = false;
    m_vsParams.clear();
    while (!sMessage.empty()) {
        m_bColon = sMessage.TrimPrefix(":");
        if (m_bColon) {
            m_vsParams.push_back(sMessage);
            sMessage.clear();
        } else {
            m_vsParams.push_back(sMessage.Token(0));
            sMessage = sMessage.Token(1, true);
        }
    }

    InitType();
}
Example #10
0
File: q.cpp Project: Adam-/znc
    bool PackHex(const CString& sHex, CString& sPackedHex) {
        if (sHex.length() % 2) return false;

        sPackedHex.clear();

        CString::size_type len = sHex.length() / 2;
        for (CString::size_type i = 0; i < len; i++) {
            unsigned int value;
            int n = sscanf(&sHex[i * 2], "%02x", &value);
            if (n != 1 || value > 0xff) return false;
            sPackedHex += (unsigned char)value;
        }

        return true;
    }
Example #11
0
File: User.cpp Project: b3rend/znc
bool CUser::IsValid(CString& sErrMsg, bool bSkipPass) const {
	sErrMsg.clear();

	if (!bSkipPass && m_sPass.empty()) {
		sErrMsg = "Pass is empty";
		return false;
	}

	if (m_sUserName.empty()) {
		sErrMsg = "Username is empty";
		return false;
	}

	if (!CUser::IsValidUserName(m_sUserName)) {
		sErrMsg = "Username is invalid";
		return false;
	}

	return true;
}
Example #12
0
bool CFile::ReadFile(CString& sData, size_t iMaxSize) {
	char buff[4096];
	size_t iBytesRead = 0;

	sData.clear();

	while (iBytesRead < iMaxSize) {
		ssize_t iBytes = Read(buff, sizeof(buff));

		if (iBytes < 0)
			// Error
			return false;

		if (iBytes == 0)
			// EOF
			return true;

		sData.append(buff, iBytes);
		iBytesRead += iBytes;
	}

	// Buffer limit reached
	return false;
}
Example #13
0
int main(int argc, char *argv[])
{
	// Shut down the server if we get a kill signal.
	signal( SIGINT, (sighandler_t) shutdownServer );
	signal( SIGTERM, (sighandler_t) shutdownServer );

	// Grab the base path to the server executable.
	getBasePath();

	// Initialize data directory.
	filesystem[0].addDir("global");
	filesystem[1].addDir("global/heads");
	filesystem[2].addDir("global/bodies");
	filesystem[3].addDir("global/swords");
	filesystem[4].addDir("global/shields");

	// Definitions
	CSocket playerSock, playerSockOld, serverSock;
	playerList.clear();
	serverList.clear();

	// Load Settings
	settings = new CSettings(homepath + "settings.ini");
	if (!settings->isOpened())
	{
		serverlog.out( "[Error] Could not load settings.\n" );
		return ERR_SETTINGS;
	}

	// Load ip bans.
	ipBans = CString::loadToken(homepath + "ipbans.txt", "\n", true);
	serverlog.out("Loaded following IP bans:\n");
	for (std::vector<CString>::iterator i = ipBans.begin(); i != ipBans.end(); ++i)
		serverlog.out("\t%s\n", i->text());

	// Load server types.
	serverTypes = CString::loadToken("servertypes.txt", "\n", true);

	// Server sock.
	serverSock.setType( SOCKET_TYPE_SERVER );
	serverSock.setProtocol( SOCKET_PROTOCOL_TCP );
	serverSock.setDescription( "serverSock" );
	CString serverInterface = settings->getStr("gserverInterface");
	if (serverInterface == "AUTO") serverInterface.clear();
	if ( serverSock.init( (serverInterface.isEmpty() ? 0 : serverInterface.text()), settings->getStr("gserverPort").text() ) )
	{
		serverlog.out( "[Error] Could not initialize sockets.\n" );
		return ERR_LISTEN;
	}

	// Player sock.
	playerSock.setType( SOCKET_TYPE_SERVER );
	playerSock.setProtocol( SOCKET_PROTOCOL_TCP );
	playerSock.setDescription( "playerSock" );
	CString playerInterface = settings->getStr("clientInterface");
	if (playerInterface == "AUTO") playerInterface.clear();
	if ( playerSock.init( (playerInterface.isEmpty() ? 0 : playerInterface.text()), settings->getStr("clientPort").text() ) )
	{
		serverlog.out( "[Error] Could not initialize sockets.\n" );
		return ERR_LISTEN;
	}

	// Player sock.
	playerSockOld.setType( SOCKET_TYPE_SERVER );
	playerSockOld.setProtocol( SOCKET_PROTOCOL_TCP );
	playerSockOld.setDescription( "playerSockOld" );
	if ( playerSockOld.init( (playerInterface.isEmpty() ? 0 : playerInterface.text()), settings->getStr("clientPortOld").text() ) )
	{
		serverlog.out( "[Error] Could not initialize sockets.\n" );
		return ERR_LISTEN;
	}

	// Connect sockets.
	if ( serverSock.connect() || playerSock.connect() || playerSockOld.connect() )
	{
		serverlog.out( "[Error] Could not connect sockets.\n" );
		return ERR_SOCKETS;
	}

	// MySQL-Connect
#ifndef NO_MYSQL
	mySQL = new CMySQL(settings->getStr("server").text(), settings->getStr("user").text(), settings->getStr("password").text(), settings->getStr("database").text(), settings->getStr("sockfile").text());
	vBmySQL =  new CMySQL(settings->getStr("server").text(), settings->getStr("vbuser").text(), settings->getStr("vbpassword").text(), settings->getStr("vbdatabase").text(), settings->getStr("sockfile").text());
	if (!mySQL->ping())
	{
		serverlog.out( "[Error] No response from MySQL.\n" );
		return ERR_MYSQL;
	}

	// Truncate servers table from MySQL.
	CString query;
	query << "TRUNCATE TABLE " << settings->getStr("serverlist");
	mySQL->add_simple_query(query);
	query = CString("TRUNCATE TABLE ") << settings->getStr("securelogin");
	mySQL->add_simple_query(query);
	mySQL->update();
#endif

	// Create Packet-Functions
	createPLFunctions();
	createSVFunctions();

	// Flavor text
	serverlog.out( CString() << "Graal Reborn - List Server V2\n"
					<< "List server started..\n"
					<< "Client port: " << CString(settings->getInt("clientport")) << "\n"
					<< "GServer port: " << CString(settings->getInt("gserverport")) << "\n" );
#ifdef NO_MYSQL
	// Notify the user that they are running in No MySQL mode
	serverlog.out( CString() << "Running in No MySQL mode, all account and guild checks are disabled.\n");
#endif

	// Main Loop
	time_t t5min = time(0);
	while (running)
	{
		// Make sure MySQL is active
#ifndef NO_MYSQL
		if (!mySQL->ping())
			serverlog.out( "[Error] No response from MySQL.\n" );
		mySQL->update();
#endif

		// Accept New Connections
		acceptSock(playerSock, SOCK_PLAYER);
		acceptSock(playerSockOld, SOCK_PLAYEROLD);
		acceptSock(serverSock, SOCK_SERVER);

		// Player Sockets
		for ( std::vector<TPlayer*>::iterator iter = playerList.begin(); iter != playerList.end(); )
		{
			TPlayer* player = (TPlayer*)*iter;
			if ( player->doMain() == false )
			{
				player->sendCompress();
				delete player;
				iter = playerList.erase( iter );
			}
			else
				++iter;
		}

		// Server Sockets
		for ( std::vector<TServer*>::iterator iter = serverList.begin(); iter != serverList.end() ; )
		{
			TServer* server = (TServer*)*iter;
			if (server == 0)
			{
				serverlog.out(CString() << "Server disconnected: [Orphaned server]\n");
				iter = serverList.erase(iter);
				continue;
			}

			// Check for a timed out server.
			if ((int)server->getLastData() >= 300)
			{
				serverlog.out(CString() << "Server disconnected: " << server->getName() << " [Timed out]\n");
				server->sendCompress();
				delete server;
				iter = serverList.erase(iter);
				continue;
			}

			// Execute server stuff.
			if (server->doMain() == false)
			{
				serverlog.out(CString() << "Server disconnected: " << server->getName() << "\n");
				server->sendCompress();
				delete server;
				iter = serverList.erase(iter);
				continue;
			}
			
			++iter;
		}

		// Every 5 minutes...
		// Reload ip bans.
		// Resync the file system.
		if ((int)difftime(time(0), t5min) > (5*60))
		{
			ipBans = CString::loadToken("ipbans.txt", "\n", true);
			serverTypes = CString::loadToken("servertypes.txt", "\n", true);
			for (int i = 0; i < 5; ++i)
				filesystem[i].resync();
			t5min = time(0);
		}

		// Wait
		wait(100);
	}

	// Remove all servers.
	// This guarantees the server deconstructors are called.
	for ( std::vector<TServer*>::iterator iter = serverList.begin(); iter != serverList.end() ; )
	{
		TServer* server = (TServer*)*iter;
		delete server;
		iter = serverList.erase( iter );
	}

	return ERR_SUCCESS;
}
Example #14
0
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;
}
Example #15
0
File: User.cpp Project: b3rend/znc
bool CUser::Clone(const CUser& User, CString& sErrorRet, bool bCloneChans) {
	unsigned int a = 0;
	sErrorRet.clear();

	if (!User.IsValid(sErrorRet, true)) {
		return false;
	}

	// user names can only specified for the constructor, changing it later
	// on breaks too much stuff (e.g. lots of paths depend on the user name)
	if (GetUserName() != User.GetUserName()) {
		DEBUG("Ignoring username in CUser::Clone(), old username [" << GetUserName()
				<< "]; New username [" << User.GetUserName() << "]");
	}

	if (!User.GetPass().empty()) {
		SetPass(User.GetPass(), User.GetPassHashType(), User.GetPassSalt());
	}

	SetNick(User.GetNick(false));
	SetAltNick(User.GetAltNick(false));
	SetIdent(User.GetIdent(false));
	SetRealName(User.GetRealName());
	SetStatusPrefix(User.GetStatusPrefix());
	SetBindHost(User.GetBindHost());
	SetDCCBindHost(User.GetDCCBindHost());
	SetQuitMsg(User.GetQuitMsg());
	SetSkinName(User.GetSkinName());
	SetLanguage(User.GetLanguage());
	SetDefaultChanModes(User.GetDefaultChanModes());
	SetBufferCount(User.GetBufferCount(), true);
	SetJoinTries(User.JoinTries());
	SetMaxJoins(User.MaxJoins());

	// Allowed Hosts
	m_ssAllowedHosts.clear();
	const set<CString>& ssHosts = User.GetAllowedHosts();
	for (set<CString>::const_iterator it = ssHosts.begin(); it != ssHosts.end(); ++it) {
		AddAllowedHost(*it);
	}

	for (a = 0; a < m_vClients.size(); a++) {
		CClient* pSock = m_vClients[a];

		if (!IsHostAllowed(pSock->GetRemoteIP())) {
			pSock->PutStatusNotice("You are being disconnected because your IP is no longer allowed to connect to this user");
			pSock->Close();
		}
	}

	// !Allowed Hosts

	// Networks
	const vector<CIRCNetwork*>& vNetworks = User.GetNetworks();
	for (a = 0; a < vNetworks.size(); a++) {
		new CIRCNetwork(this, vNetworks[a], bCloneChans);
	}
	// !Networks

	// CTCP Replies
	m_mssCTCPReplies.clear();
	const MCString& msReplies = User.GetCTCPReplies();
	for (MCString::const_iterator it = msReplies.begin(); it != msReplies.end(); ++it) {
		AddCTCPReply(it->first, it->second);
	}
	// !CTCP Replies

	// Flags
	SetIRCConnectEnabled(User.GetIRCConnectEnabled());
	SetKeepBuffer(User.KeepBuffer());
	SetMultiClients(User.MultiClients());
	SetDenyLoadMod(User.DenyLoadMod());
	SetAdmin(User.IsAdmin());
	SetDenySetBindHost(User.DenySetBindHost());
	SetTimestampAppend(User.GetTimestampAppend());
	SetTimestampPrepend(User.GetTimestampPrepend());
	SetTimestampFormat(User.GetTimestampFormat());
	SetTimezoneOffset(User.GetTimezoneOffset());
	// !Flags

	// Modules
	set<CString> ssUnloadMods;
	CModules& vCurMods = GetModules();
	const CModules& vNewMods = User.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::UserModule, this, NULL, sModRet);
		} else if (pNewMod->GetArgs() != pCurMod->GetArgs()) {
			vCurMods.ReloadModule(pNewMod->GetModName(), pNewMod->GetArgs(), this, NULL, 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

	return true;
}
Example #16
0
int verifyAccount(CString& pAccount, const CString& pPassword, bool fromServer)
{
#ifdef NO_MYSQL
	return ACCSTAT_NORMAL;
#else
	// definitions
	CString query;
	std::vector<CString> result;
	CString password(pPassword);

	// make sure its not empty.
	if (pAccount.length() == 0)
		return ACCSTAT_INVALID;

	// See if we should try a secure login.
	int ret = ACCSTAT_INVALID;
	if (password.find("\xa7") != -1)
	{
		CString transaction = password.readString("\xa7");
		CString md5password = password.readString("");

		// Try our password.
		result.clear();
		query = CString() << "SELECT activated, banned, account FROM `" << settings->getStr("userlist") << "` WHERE account='" << pAccount.escape() << "' AND transactionnr='" << transaction.escape() << "' AND password2='" << md5password.escape() << "' LIMIT 1";
		int err = mySQL->try_query(query, result);

		// account/password correct?
		if (err == -1)
			ret = ACCSTAT_ERROR;
		else if (result.size() == 0)
			ret = ACCSTAT_INVALID;
		else if (result.size() >= 1 && result[0] == "0")
			ret = ACCSTAT_NONREG;
		else if (result.size() >= 2 && result[1] == "1")
			ret = ACCSTAT_BANNED;
		else
			ret = ACCSTAT_NORMAL;

		// Should we expire the password now?
		if (ret != ACCSTAT_INVALID && ret != ACCSTAT_ERROR)
		{
			unsigned char login_type = (char)(atoi(transaction.text()) & 0xFF);

			// Password expires after one server login.  Remove it.
			if (login_type == SECURELOGIN_ONEUSE && fromServer == true)
			{
				query.clear();
				query << "UPDATE `" << settings->getStr("userlist") << "` SET "
					<< "transactionnr='0',"
					<< "salt2='',"
					<< "password2='' "
					<< "WHERE account='" << pAccount.escape() << "'";
				mySQL->add_simple_query(query);
			}
		}

		// Get the correct account name.
		if (result.size() == 3)
			pAccount = result[2];

		return ret;
	}

	// If our ret is ACCSTAT_ERROR, that means there was a SQL error.
	if (ret == ACCSTAT_ERROR)
		return ret;

	// Either the secure login failed or we didn't try a secure login.
	// Try the old login method.
	if (ret == ACCSTAT_INVALID)
	{
		result.clear();
		query = CString() << "SELECT password, salt, activated, banned, account FROM `" << settings->getStr("userlist") << "` WHERE account='" << pAccount.escape() << "' AND password="******"MD5(CONCAT(MD5('" << pPassword.escape() << "'), `salt`)) LIMIT 1";
		int err = mySQL->try_query(query, result);
		if (err == -1) return ACCSTAT_ERROR;

		// account/password correct?
		if (result.size() == 0)
			return ACCSTAT_INVALID;

		// activated?
		if (result.size() < 3 || result[2] == "0")
			return ACCSTAT_NONREG;

		// banned?
		if (result.size() > 3 && result[3] == "1")
			return ACCSTAT_BANNED;

		// Get the case-sensitive account name.
		if (result.size() > 4)
			pAccount = result[4];

		// passed all tests :)
		return ACCSTAT_NORMAL;
	}

	return ACCSTAT_INVALID;
#endif
}
Example #17
0
void CClient::UserPortCommand(CString& sLine) {
	const CString sCommand = sLine.Token(0);

	if (sCommand.Equals("LISTPORTS")) {
		CTable Table;
		Table.AddColumn("Port");
		Table.AddColumn("BindHost");
		Table.AddColumn("SSL");
		Table.AddColumn("Proto");
		Table.AddColumn("IRC/Web");

		vector<CListener*>::const_iterator it;
		const vector<CListener*>& vpListeners = CZNC::Get().GetListeners();

		for (it = vpListeners.begin(); it < vpListeners.end(); ++it) {
			Table.AddRow();
			Table.SetCell("Port", CString((*it)->GetPort()));
			Table.SetCell("BindHost", ((*it)->GetBindHost().empty() ? CString("*") : (*it)->GetBindHost()));
			Table.SetCell("SSL", CString((*it)->IsSSL()));

			EAddrType eAddr = (*it)->GetAddrType();
			Table.SetCell("Proto", (eAddr == ADDR_ALL ? "All" : (eAddr == ADDR_IPV4ONLY ? "IPv4" : "IPv6")));

			CListener::EAcceptType eAccept = (*it)->GetAcceptType();
			Table.SetCell("IRC/Web", (eAccept == CListener::ACCEPT_ALL ? "All" : (eAccept == CListener::ACCEPT_IRC ? "IRC" : "Web")));
		}

		PutStatus(Table);

		return;
	}

	CString sPort = sLine.Token(1);
	CString sAddr = sLine.Token(2);
	EAddrType eAddr = ADDR_ALL;

	if (sAddr.Equals("IPV4")) {
		eAddr = ADDR_IPV4ONLY;
	} else if (sAddr.Equals("IPV6")) {
		eAddr = ADDR_IPV6ONLY;
	} else if (sAddr.Equals("ALL")) {
		eAddr = ADDR_ALL;
	} else {
		sAddr.clear();
	}

	unsigned short uPort = sPort.ToUShort();

	if (sCommand.Equals("ADDPORT")) {
		CListener::EAcceptType eAccept = CListener::ACCEPT_ALL;
		CString sAccept = sLine.Token(3);

		if (sAccept.Equals("WEB")) {
			eAccept = CListener::ACCEPT_HTTP;
		} else if (sAccept.Equals("IRC")) {
			eAccept = CListener::ACCEPT_IRC;
		} else if (sAccept.Equals("ALL")) {
			eAccept = CListener::ACCEPT_ALL;
		} else {
			sAccept.clear();
		}

		if (sPort.empty() || sAddr.empty() || sAccept.empty()) {
			PutStatus("Usage: AddPort <[+]port> <ipv4|ipv6|all> <web|irc|all> [bindhost]");
		} else {
			bool bSSL = (sPort.Left(1).Equals("+"));
			const CString sBindHost = sLine.Token(4);

			CListener* pListener = new CListener(uPort, sBindHost, bSSL, eAddr, eAccept);

			if (!pListener->Listen()) {
				delete pListener;
				PutStatus("Unable to bind [" + CString(strerror(errno)) + "]");
			} else {
				if (CZNC::Get().AddListener(pListener))
					PutStatus("Port Added");
				else
					PutStatus("Error?!");
			}
		}
	} else if (sCommand.Equals("DELPORT")) {
		if (sPort.empty() || sAddr.empty()) {
			PutStatus("Usage: DelPort <port> <ipv4|ipv6|all> [bindhost]");
		} else {
			const CString sBindHost = sLine.Token(3);

			CListener* pListener = CZNC::Get().FindListener(uPort, sBindHost, eAddr);

			if (pListener) {
				CZNC::Get().DelListener(pListener);
				PutStatus("Deleted Port");
			} else {
				PutStatus("Unable to find a matching port");
			}
		}
	}
}
Example #18
0
void
CDaemonApp::handleIpcMessage(const CEvent& e, void*)
{
	CIpcMessage* m = static_cast<CIpcMessage*>(e.getDataObject());
	switch (m->type()) {
		case kIpcCommand: {
			CIpcCommandMessage* cm = static_cast<CIpcCommandMessage*>(m);
			CString command = cm->command();

			// if empty quotes, clear.
			if (command == "\"\"") {
				command.clear();
			}

			if (!command.empty()) {
				LOG((CLOG_DEBUG "new command, elevate=%d command=%s", cm->elevate(), command.c_str()));

				CString debugArg("--debug");
				UInt32 debugArgPos = static_cast<UInt32>(command.find(debugArg));
				if (debugArgPos != CString::npos) {
					UInt32 from = debugArgPos + static_cast<UInt32>(debugArg.size()) + 1;
					UInt32 nextSpace = static_cast<UInt32>(command.find(" ", from));
					CString logLevel(command.substr(from, nextSpace - from));
				
					try {
						// change log level based on that in the command string
						// and change to that log level now.
						ARCH->setting("LogLevel", logLevel);
						CLOG->setFilter(logLevel.c_str());
					}
					catch (XArch& e) {
						LOG((CLOG_ERR "failed to save LogLevel setting, %s", e.what().c_str()));
					}
				}
			}
			else {
				LOG((CLOG_DEBUG "empty command, elevate=%d", cm->elevate()));
			}

			try {
				// store command in system settings. this is used when the daemon
				// next starts.
				ARCH->setting("Command", command);

				// TODO: it would be nice to store bools/ints...
				ARCH->setting("Elevate", CString(cm->elevate() ? "1" : "0"));
			}
			catch (XArch& e) {
				LOG((CLOG_ERR "failed to save settings, %s", e.what().c_str()));
			}

#if SYSAPI_WIN32
			// tell the relauncher about the new command. this causes the
			// relauncher to stop the existing command and start the new
			// command.
			m_watchdog->setCommand(command, cm->elevate());
#endif
			break;
		}

		case kIpcHello:
			CIpcHelloMessage* hm = static_cast<CIpcHelloMessage*>(m);
			CString type;
			switch (hm->clientType()) {
				case kIpcClientGui: type = "gui"; break;
				case kIpcClientNode: type = "node"; break;
				default: type = "unknown"; break;
			}

			LOG((CLOG_DEBUG "ipc hello, type=%s", type.c_str()));

#if SYSAPI_WIN32
			CString watchdogStatus = m_watchdog->isProcessActive() ? "ok" : "error";
			LOG((CLOG_INFO "watchdog status: %s", watchdogStatus.c_str()));
#endif

			m_ipcLogOutputter->notifyBuffer();
			break;
	}
}
Example #19
0
bool CTemplate::Print(const CString& sFileName, ostream& oOut) {
	if (sFileName.empty()) {
		DEBUG("Empty filename in CTemplate::Print()");
		return false;
	}

	CFile File(sFileName);

	if (!File.Open()) {
		DEBUG("Unable to open file [" + sFileName + "] in CTemplate::Print()");
		return false;
	}

	CString sLine;
	CString sSetBlockVar;
	bool bValidLastIf = false;
	bool bInSetBlock = false;
	unsigned long uFilePos = 0;
	unsigned long uCurPos = 0;
	unsigned int uLineNum = 0;
	unsigned int uNestedIfs = 0;
	unsigned int uSkip = 0;
	bool bLoopCont = false;
	bool bLoopBreak = false;
	bool bExit = false;

	while (File.ReadLine(sLine)) {
		CString sOutput;
		bool bFoundATag = false;
		bool bTmplLoopHasData = false;
		uLineNum++;
		CString::size_type iPos = 0;
		uCurPos = uFilePos;
		unsigned int uLineSize = sLine.size();
		bool bBroke = false;

		while (1) {
			iPos = sLine.find("<?");

			if (iPos == CString::npos) {
				break;
			}

			uCurPos += iPos;
			bFoundATag = true;

			if (!uSkip) {
				sOutput += sLine.substr(0, iPos);
			}

			sLine = sLine.substr(iPos +2);

			CString::size_type iPos2 = sLine.find("?>");

			// Make sure our tmpl tag is ended properly
			if (iPos2 == CString::npos) {
				DEBUG("Template tag not ended properly in file [" + sFileName + "] [<?" + sLine + "]");
				return false;
			}

			uCurPos += iPos2 +4;

			CString sMid = CString(sLine.substr(0, iPos2)).Trim_n();

			// Make sure we don't have a nested tag
			if (sMid.find("<?") == CString::npos) {
				sLine = sLine.substr(iPos2 +2);
				CString sAction = sMid.Token(0);
				CString sArgs = sMid.Token(1, true);
				bool bNotFound = false;

				// If we're breaking or continuing from within a loop, skip all tags that aren't ENDLOOP
				if ((bLoopCont || bLoopBreak) && !sAction.Equals("ENDLOOP")) {
					continue;
				}

				if (!uSkip) {
					if (sAction.Equals("INC")) {
						if (!Print(ExpandFile(sArgs, true), oOut)) {
							DEBUG("Unable to print INC'd file [" + sArgs + "]");
							return false;
						}
					} else if (sAction.Equals("SETOPTION")) {
						m_spOptions->Parse(sArgs);
					} else if (sAction.Equals("ADDROW")) {
						CString sLoopName = sArgs.Token(0);
						MCString msRow;

						if (sArgs.Token(1, true, " ").OptionSplit(msRow)) {
							CTemplate& NewRow = AddRow(sLoopName);

							for (MCString::iterator it = msRow.begin(); it != msRow.end(); ++it) {
								NewRow[it->first] = it->second;
							}
						}
					} else if (sAction.Equals("SET")) {
						CString sName = sArgs.Token(0);
						CString sValue = sArgs.Token(1, true);

						(*this)[sName] = sValue;
					} else if (sAction.Equals("JOIN")) {
						VCString vsArgs;
						//sArgs.Split(" ", vsArgs, false, "\"", "\"");
						sArgs.QuoteSplit(vsArgs);

						if (vsArgs.size() > 1) {
							CString sDelim = vsArgs[0];
							bool bFoundOne = false;
							CString::EEscape eEscape = CString::EASCII;

							for (unsigned int a = 1; a < vsArgs.size(); a++) {
								const CString& sArg = vsArgs[a];

								if (sArg.Equals("ESC=", false, 4)) {
									eEscape = CString::ToEscape(sArg.LeftChomp_n(4));
								} else {
									CString sValue = GetValue(sArg);

									if (!sValue.empty()) {
										if (bFoundOne) {
											sOutput += sDelim;
										}

										sOutput += sValue.Escape_n(eEscape);
										bFoundOne = true;
									}
								}
							}
						}
					} else if (sAction.Equals("SETBLOCK")) {
						sSetBlockVar = sArgs;
						bInSetBlock = true;
					} else if (sAction.Equals("EXPAND")) {
						sOutput += ExpandFile(sArgs, true);
					} else if (sAction.Equals("VAR")) {
						sOutput += GetValue(sArgs);
					} else if (sAction.Equals("LT")) {
						sOutput += "<?";
					} else if (sAction.Equals("GT")) {
						sOutput += "?>";
					} else if (sAction.Equals("CONTINUE")) {
						CTemplateLoopContext* pContext = GetCurLoopContext();

						if (pContext) {
							uSkip++;
							bLoopCont = true;

							break;
						} else {
							DEBUG("[" + sFileName + ":" + CString(uCurPos - iPos2 -4) + "] <? CONTINUE ?> must be used inside of a loop!");
						}
					} else if (sAction.Equals("BREAK")) {
						// break from loop
						CTemplateLoopContext* pContext = GetCurLoopContext();

						if (pContext) {
							uSkip++;
							bLoopBreak = true;

							break;
						} else {
							DEBUG("[" + sFileName + ":" + CString(uCurPos - iPos2 -4) + "] <? BREAK ?> must be used inside of a loop!");
						}
					} else if (sAction.Equals("EXIT")) {
						bExit = true;
					} else if (sAction.Equals("DEBUG")) {
						DEBUG("CTemplate DEBUG [" + sFileName + "@" + CString(uCurPos - iPos2 -4) + "b] -> [" + sArgs + "]");
					} else if (sAction.Equals("LOOP")) {
						CTemplateLoopContext* pContext = GetCurLoopContext();

						if (!pContext || pContext->GetFilePosition() != uCurPos) {
							// we are at a brand new loop (be it new or a first pass at an inner loop)

							CString sLoopName = sArgs.Token(0);
							bool bReverse = (sArgs.Token(1).Equals("REVERSE"));
							bool bSort = (sArgs.Token(1).Left(4).Equals("SORT"));
							vector<CTemplate*>* pvLoop = GetLoop(sLoopName);

							if (bSort && pvLoop != NULL &&  pvLoop->size() > 1) {
								CString sKey;

								if(sArgs.Token(1).TrimPrefix_n("SORT").Left(4).Equals("ASC=")) {
									sKey = sArgs.Token(1).TrimPrefix_n("SORTASC=");
								} else if(sArgs.Token(1).TrimPrefix_n("SORT").Left(5).Equals("DESC=")) {
									sKey = sArgs.Token(1).TrimPrefix_n("SORTDESC=");
									bReverse = true;
								}

								if (!sKey.empty()) {
									std::sort(pvLoop->begin(), pvLoop->end(), CLoopSorter(sKey));
								}
							}

							if (pvLoop) {
								// If we found data for this loop, add it to our context vector
								//unsigned long uBeforeLoopTag = uCurPos - iPos2 - 4;
								unsigned long uAfterLoopTag = uCurPos;

								for (CString::size_type t = 0; t < sLine.size(); t++) {
									char c = sLine[t];
									if (c == '\r' || c == '\n') {
										uAfterLoopTag++;
									} else {
										break;
									}
								}

								m_vLoopContexts.push_back(new CTemplateLoopContext(uAfterLoopTag, sLoopName, bReverse, pvLoop));
							} else {  // If we don't have data, just skip this loop and everything inside
								uSkip++;
							}
						}
					} else if (sAction.Equals("IF")) {
						if (ValidIf(sArgs)) {
							uNestedIfs++;
							bValidLastIf = true;
						} else {
							uSkip++;
							bValidLastIf = false;
						}
					} else if (sAction.Equals("REM")) {
						uSkip++;
					} else {
						bNotFound = true;
					}
				} else if (sAction.Equals("REM")) {
					uSkip++;
				} else if (sAction.Equals("IF")) {
					uSkip++;
				} else if (sAction.Equals("LOOP")) {
					uSkip++;
				}

				if (sAction.Equals("ENDIF")) {
					if (uSkip) {
						uSkip--;
					} else {
						uNestedIfs--;
					}
				} else if (sAction.Equals("ENDREM")) {
					if (uSkip) {
						uSkip--;
					}
				} else if (sAction.Equals("ENDSETBLOCK")) {
					bInSetBlock = false;
					sSetBlockVar = "";
				} else if (sAction.Equals("ENDLOOP")) {
					if (bLoopCont && uSkip == 1) {
						uSkip--;
						bLoopCont = false;
					}

					if (bLoopBreak && uSkip == 1) {
						uSkip--;
					}

					if (uSkip) {
						uSkip--;
					} else {
						// We are at the end of the loop so we need to inc the index
						CTemplateLoopContext* pContext = GetCurLoopContext();

						if (pContext) {
							pContext->IncRowIndex();

							// If we didn't go out of bounds we need to seek back to the top of our loop
							if (!bLoopBreak && pContext->GetCurRow()) {
								uCurPos = pContext->GetFilePosition();
								uFilePos = uCurPos;
								uLineSize = 0;

								File.Seek(uCurPos);
								bBroke = true;

								if (!sOutput.Trim_n().empty()) {
									pContext->SetHasData();
								}

								break;
							} else {
								if (sOutput.Trim_n().empty()) {
									sOutput.clear();
								}

								bTmplLoopHasData = pContext->HasData();
								DelCurLoopContext();
								bLoopBreak = false;
							}
						}
					}
				} else if (sAction.Equals("ELSE")) {
					if (!bValidLastIf && uSkip == 1) {
						CString sArg = sArgs.Token(0);

						if (sArg.empty() || (sArg.Equals("IF") && ValidIf(sArgs.Token(1, true)))) {
							uSkip = 0;
							bValidLastIf = true;
						}
					} else if (!uSkip) {
						uSkip = 1;
					}
				} else if (bNotFound) {
					// Unknown tag that isn't being skipped...
					vector<CSmartPtr<CTemplateTagHandler> >& vspTagHandlers = GetTagHandlers();

					if (!vspTagHandlers.empty()) { // @todo this should go up to the top to grab handlers
						CTemplate* pTmpl = GetCurTemplate();
						CString sCustomOutput;

						for (unsigned int j = 0; j < vspTagHandlers.size(); j++) {
							CSmartPtr<CTemplateTagHandler> spTagHandler = vspTagHandlers[j];

							if (spTagHandler->HandleTag(*pTmpl, sAction, sArgs, sCustomOutput)) {
								sOutput += sCustomOutput;
								bNotFound = false;
								break;
							}
						}

						if (bNotFound) {
							DEBUG("Unknown/Unhandled tag [" + sAction + "]");
						}
					}
				}

				continue;
			}

			DEBUG("Malformed tag on line " + CString(uLineNum) + " of [" << File.GetLongName() + "]");
			DEBUG("--------------- [" + sLine + "]");
		}

		if (!bBroke) {
			uFilePos += uLineSize;

			if (!uSkip) {
				sOutput += sLine;
			}
		}

		if (!bFoundATag || bTmplLoopHasData || sOutput.find_first_not_of(" \t\r\n") != CString::npos) {
			if (bInSetBlock) {
				CString sName = sSetBlockVar.Token(0);
				//CString sValue = sSetBlockVar.Token(1, true);
				(*this)[sName] += sOutput;
			} else {
				oOut << sOutput;
			}
		}

		if (bExit) {
			break;
		}
	}

	oOut.flush();

	return true;
}
Example #20
0
bool CUser::Clone(const CUser& User, CString& sErrorRet, bool bCloneNetworks) {
    sErrorRet.clear();

    if (!User.IsValid(sErrorRet, true)) {
        return false;
    }

    // user names can only specified for the constructor, changing it later
    // on breaks too much stuff (e.g. lots of paths depend on the user name)
    if (GetUserName() != User.GetUserName()) {
        DEBUG("Ignoring username in CUser::Clone(), old username ["
              << GetUserName() << "]; New username [" << User.GetUserName()
              << "]");
    }

    if (!User.GetPass().empty()) {
        SetPass(User.GetPass(), User.GetPassHashType(), User.GetPassSalt());
    }

    SetNick(User.GetNick(false));
    SetAltNick(User.GetAltNick(false));
    SetIdent(User.GetIdent(false));
    SetRealName(User.GetRealName());
    SetStatusPrefix(User.GetStatusPrefix());
    SetBindHost(User.GetBindHost());
    SetDCCBindHost(User.GetDCCBindHost());
    SetQuitMsg(User.GetQuitMsg());
    SetSkinName(User.GetSkinName());
    SetDefaultChanModes(User.GetDefaultChanModes());
    SetChanBufferSize(User.GetChanBufferSize(), true);
    SetQueryBufferSize(User.GetQueryBufferSize(), true);
    SetJoinTries(User.JoinTries());
    SetMaxNetworks(User.MaxNetworks());
    SetMaxQueryBuffers(User.MaxQueryBuffers());
    SetMaxJoins(User.MaxJoins());
    SetClientEncoding(User.GetClientEncoding());

    // Allowed Hosts
    m_ssAllowedHosts.clear();
    const set<CString>& ssHosts = User.GetAllowedHosts();
    for (const CString& sHost : ssHosts) {
        AddAllowedHost(sHost);
    }

    for (CClient* pSock : m_vClients) {
        if (!IsHostAllowed(pSock->GetRemoteIP())) {
            pSock->PutStatusNotice(
                "You are being disconnected because your IP is no longer "
                "allowed to connect to this user");
            pSock->Close();
        }
    }

    // !Allowed Hosts

    // Networks
    if (bCloneNetworks) {
        CloneNetworks(User);
    }
    // !Networks

    // CTCP Replies
    m_mssCTCPReplies.clear();
    const MCString& msReplies = User.GetCTCPReplies();
    for (const auto& it : msReplies) {
        AddCTCPReply(it.first, it.second);
    }
    // !CTCP Replies

    // Flags
    SetAutoClearChanBuffer(User.AutoClearChanBuffer());
    SetAutoClearQueryBuffer(User.AutoClearQueryBuffer());
    SetMultiClients(User.MultiClients());
    SetDenyLoadMod(User.DenyLoadMod());
    SetAdmin(User.IsAdmin());
    SetDenySetBindHost(User.DenySetBindHost());
    SetTimestampAppend(User.GetTimestampAppend());
    SetTimestampPrepend(User.GetTimestampPrepend());
    SetTimestampFormat(User.GetTimestampFormat());
    SetTimezone(User.GetTimezone());
    // !Flags

    // Modules
    set<CString> ssUnloadMods;
    CModules& vCurMods = GetModules();
    const CModules& vNewMods = User.GetModules();

    for (CModule* pNewMod : vNewMods) {
        CString sModRet;
        CModule* pCurMod = vCurMods.FindModule(pNewMod->GetModName());

        if (!pCurMod) {
            vCurMods.LoadModule(pNewMod->GetModName(), pNewMod->GetArgs(),
                                CModInfo::UserModule, this, nullptr, sModRet);
        } else if (pNewMod->GetArgs() != pCurMod->GetArgs()) {
            vCurMods.ReloadModule(pNewMod->GetModName(), pNewMod->GetArgs(),
                                  this, nullptr, 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

    return true;
}
Example #21
0
bool CUser::Clone(const CUser& User, CString& sErrorRet, bool bCloneChans) {
	unsigned int a = 0;
	sErrorRet.clear();

	if (!User.IsValid(sErrorRet, true)) {
		return false;
	}

	// user names can only specified for the constructor, changing it later
	// on breaks too much stuff (e.g. lots of paths depend on the user name)
	if (GetUserName() != User.GetUserName()) {
		DEBUG("Ignoring username in CUser::Clone(), old username [" << GetUserName()
				<< "]; New username [" << User.GetUserName() << "]");
	}

	if (!User.GetPass().empty()) {
		SetPass(User.GetPass(), User.GetPassHashType(), User.GetPassSalt());
	}

	SetNick(User.GetNick(false));
	SetAltNick(User.GetAltNick(false));
	SetIdent(User.GetIdent(false));
	SetRealName(User.GetRealName());
	SetStatusPrefix(User.GetStatusPrefix());
	SetBindHost(User.GetBindHost());
	SetDCCBindHost(User.GetDCCBindHost());
	SetQuitMsg(User.GetQuitMsg());
	SetSkinName(User.GetSkinName());
	SetDefaultChanModes(User.GetDefaultChanModes());
	SetBufferCount(User.GetBufferCount(), true);
	SetJoinTries(User.JoinTries());
	SetMaxJoins(User.MaxJoins());

	// Allowed Hosts
	m_ssAllowedHosts.clear();
	const set<CString>& ssHosts = User.GetAllowedHosts();
	for (set<CString>::const_iterator it = ssHosts.begin(); it != ssHosts.end(); ++it) {
		AddAllowedHost(*it);
	}

	for (a = 0; a < m_vClients.size(); a++) {
		CClient* pSock = m_vClients[a];

		if (!IsHostAllowed(pSock->GetRemoteIP())) {
			pSock->PutStatusNotice("You are being disconnected because your IP is no longer allowed to connect to this user");
			pSock->Close();
		}
	}

	// !Allowed Hosts

	// Servers
	const vector<CServer*>& vServers = User.GetServers();
	CString sServer;
	CServer* pCurServ = GetCurrentServer();

	if (pCurServ) {
		sServer = pCurServ->GetName();
	}

	DelServers();

	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 = User.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 = User.FindChan(pChan->GetName());

		if (!pNewChan) {
			pChan->SetInConfig(false);
		} else {
			if (bCloneChans)
				pChan->Clone(*pNewChan);
		}
	}
	// !Chans

	// CTCP Replies
	m_mssCTCPReplies.clear();
	const MCString& msReplies = User.GetCTCPReplies();
	for (MCString::const_iterator it = msReplies.begin(); it != msReplies.end(); ++it) {
		AddCTCPReply(it->first, it->second);
	}
	// !CTCP Replies

	// Flags
	SetIRCConnectEnabled(User.GetIRCConnectEnabled());
	SetKeepBuffer(User.KeepBuffer());
	SetMultiClients(User.MultiClients());
	SetBounceDCCs(User.BounceDCCs());
	SetUseClientIP(User.UseClientIP());
	SetDenyLoadMod(User.DenyLoadMod());
	SetAdmin(User.IsAdmin());
	SetDenySetBindHost(User.DenySetBindHost());
	SetTimestampAppend(User.GetTimestampAppend());
	SetTimestampPrepend(User.GetTimestampPrepend());
	SetTimestampFormat(User.GetTimestampFormat());
	SetTimezoneOffset(User.GetTimezoneOffset());
	// !Flags

	// Modules
	set<CString> ssUnloadMods;
	CModules& vCurMods = GetModules();
	const CModules& vNewMods = User.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(), this, sModRet);
		} else if (pNewMod->GetArgs() != pCurMod->GetArgs()) {
			vCurMods.ReloadModule(pNewMod->GetModName(), pNewMod->GetArgs(), 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

	return true;
}
Example #22
0
void CLanguage::LoadFile ( const CString& szLangName, const CString& szEntryName )
{
    CString szPath ( "../lang/%s/%s.txt", szLangName.c_str (), szEntryName.c_str () );

    FILE* fp;
#ifdef WIN32
    fopen_s ( &fp, szPath.c_str (), "r" );
#else
    fp = fopen ( szPath.c_str (), "r" );
#endif
    if ( !fp )
        return;

    CString szCurTopic;
    CString szCurTopicName;
    char szBuffer [ 4096 ];
    char* p;

    t_topicMap* map = new t_topicMap ( );
    map->set_deleted_key ( (char*)HASH_STRING_DELETED );
    map->set_empty_key ( (char*)HASH_STRING_EMPTY );

    char* szKey = strdup ( szEntryName.c_str () );
    m_entriesMap.insert ( t_entriesMap::value_type ( szKey, map ) );

    while ( !feof ( fp ) )
    {
        fgets ( szBuffer, sizeof ( szBuffer ), fp );
        p = szBuffer + strlen ( szBuffer ) - 1;
        while ( p >= szBuffer && ( *p == '\r' || *p == '\n' ) )
        {
            *p = '\0';
            --p;
        }

        if ( *p == '#' )
        {
            // Es un comentario
            continue;
        }

        if ( *p == '%' && szBuffer [ 0 ] == '%' )
        {
            if ( p > szBuffer + 1 )
            {
                // Inicio de un tema
                szCurTopic.clear ();
                *p = '\0';
                szCurTopicName = szBuffer + 1;
            }
            else
            {
                // Fin de un tema
                if ( szCurTopicName.length () > 0 )
                {
                    char* szKey = strdup ( szCurTopicName.c_str () );
                    map->insert ( t_topicMap::value_type ( szKey, szCurTopic ) );
                }
                szCurTopicName.clear ();
            }
        }
        else
        {
            szCurTopic.append ( szBuffer );
            szCurTopic.append ( "\n" );
        }
    }

    fclose ( fp );
}
Example #23
0
void
CDaemonApp::handleIpcMessage(const CEvent& e, void*)
{
	CIpcMessage* m = static_cast<CIpcMessage*>(e.getDataObject());
	switch (m->type()) {
		case kIpcCommand: {
			CIpcCommandMessage* cm = static_cast<CIpcCommandMessage*>(m);
			CString command = cm->command();

			// if empty quotes, clear.
			if (command == "\"\"") {
				command.clear();
			}

			if (!command.empty()) {
				LOG((CLOG_DEBUG "new command, elevate=%d command=%s", cm->elevate(), command.c_str()));

				std::vector<CString> argsArray;
				CArgParser::splitCommandString(command, argsArray);
				CArgParser argParser(NULL);
				const char** argv = argParser.getArgv(argsArray);
				CServerArgs serverArgs;
				CClientArgs clientArgs;
				int argc = static_cast<int>(argsArray.size());
				bool server = argsArray[0].find("synergys") != CString::npos ? true : false;
				CArgsBase* argBase = NULL;

				if (server) {
					argParser.parseServerArgs(serverArgs, argc, argv);
					argBase = &serverArgs;
				}
				else {
					argParser.parseClientArgs(clientArgs, argc, argv);
					argBase = &clientArgs;
				}

				delete[] argv;
				
				CString logLevel(argBase->m_logFilter);
				if (!logLevel.empty()) {
					try {
						// change log level based on that in the command string
						// and change to that log level now.
						ARCH->setting("LogLevel", logLevel);
						CLOG->setFilter(logLevel.c_str());
					}
					catch (XArch& e) {
						LOG((CLOG_ERR "failed to save LogLevel setting, %s", e.what()));
					}
				}

#if SYSAPI_WIN32
				CString logFilename;
				if (argBase->m_logFile != NULL) {
					logFilename = CString(argBase->m_logFile);
					ARCH->setting("LogFilename", logFilename);
					m_watchdog->setFileLogOutputter(m_fileLogOutputter);
					command = CArgParser::assembleCommand(argsArray, "--log", 1);
					LOG((CLOG_DEBUG "removed log file argument and filename %s from command ", logFilename.c_str()));
					LOG((CLOG_DEBUG "new command, elevate=%d command=%s", cm->elevate(), command.c_str()));
				}
				else {
					m_watchdog->setFileLogOutputter(NULL);
				}

				m_fileLogOutputter->setLogFilename(logFilename.c_str());
#endif
			}
			else {
				LOG((CLOG_DEBUG "empty command, elevate=%d", cm->elevate()));
			}

			try {
				// store command in system settings. this is used when the daemon
				// next starts.
				ARCH->setting("Command", command);

				// TODO: it would be nice to store bools/ints...
				ARCH->setting("Elevate", CString(cm->elevate() ? "1" : "0"));
			}
			catch (XArch& e) {
				LOG((CLOG_ERR "failed to save settings, %s", e.what()));
			}

#if SYSAPI_WIN32
			// tell the relauncher about the new command. this causes the
			// relauncher to stop the existing command and start the new
			// command.
			m_watchdog->setCommand(command, cm->elevate());
#endif
			break;
		}

		case kIpcHello:
			CIpcHelloMessage* hm = static_cast<CIpcHelloMessage*>(m);
			CString type;
			switch (hm->clientType()) {
				case kIpcClientGui: type = "gui"; break;
				case kIpcClientNode: type = "node"; break;
				default: type = "unknown"; break;
			}

			LOG((CLOG_DEBUG "ipc hello, type=%s", type.c_str()));

#if SYSAPI_WIN32
			CString watchdogStatus = m_watchdog->isProcessActive() ? "ok" : "error";
			LOG((CLOG_INFO "watchdog status: %s", watchdogStatus.c_str()));
#endif

			m_ipcLogOutputter->notifyBuffer();
			break;
	}
}
Example #24
0
ModHandle CModules::OpenModule(const CString& sModule, const CString& sModPath, bool &bVersionMismatch,
		bool &bIsGlobal, CString& sDesc, CString& sRetMsg) {
	// Some sane defaults in case anything errors out below
	bVersionMismatch = false;
	bIsGlobal = false;
	sDesc.clear();
	sRetMsg.clear();

	for (unsigned int a = 0; a < sModule.length(); a++) {
		if (((sModule[a] < '0') || (sModule[a] > '9')) && ((sModule[a] < 'a') || (sModule[a] > 'z')) && ((sModule[a] < 'A') || (sModule[a] > 'Z')) && (sModule[a] != '_')) {
			sRetMsg = "Module names can only contain letters, numbers and underscores, [" + sModule + "] is invalid.";
			return NULL;
		}
	}

#ifndef _WIN32
	// The second argument to dlopen() has a long history. It seems clear
	// that (despite what the man page says) we must include either of
	// RTLD_NOW and RTLD_LAZY and either of RTLD_GLOBAL and RTLD_LOCAL.
	//
	// RTLD_NOW vs. RTLD_LAZY: We use RTLD_NOW to avoid znc dying due to
	// failed symbol lookups later on. Doesn't really seem to have much of a
	// performance impact.
	//
	// RTLD_GLOBAL vs. RTLD_LOCAL: If perl is loaded with RTLD_LOCAL and later on
	// loads own modules (which it apparently does with RTLD_LAZY), we will die in a
	// name lookup since one of perl's symbols isn't found. That's worse
	// than any theoretical issue with RTLD_LOCAL.
	ModHandle p = dlopen((sModPath).c_str(), RTLD_NOW | RTLD_GLOBAL);
#else
	ModHandle p = dlopen((sModPath).c_str(), RTLD_NOW | RTLD_LOCAL);
#endif

	if (!p) {
		sRetMsg = "Unable to open module [" + sModule + "] [" + dlerror() + "]";
		return NULL;
	}

	typedef double (*dFP)();
	dFP Version = (dFP) dlsym(p, "ZNCModVersion");

	if (!Version) {
		dlclose(p);
		sRetMsg = "Could not find ZNCModVersion() in module [" + sModule + "]";
		return NULL;
	}

	typedef bool (*bFP)();
	bFP IsGlobal = (bFP) dlsym(p, "ZNCModGlobal");

	if (!IsGlobal) {
		dlclose(p);
		sRetMsg = "Could not find ZNCModGlobal() in module [" + sModule + "]";
		return NULL;
	}

	typedef const char *(*sFP)();
	sFP GetDesc = (sFP) dlsym(p, "ZNCModDescription");

	if (!GetDesc) {
		dlclose(p);
		sRetMsg = "Could not find ZNCModDescription() in module [" + sModule + "]";
		return false;
	}

	if (CModule::GetCoreVersion() != Version()) {
		bVersionMismatch = true;
#ifndef _WIN32
		sRetMsg = "Version mismatch, recompile this module.";
#else
		sRetMsg = "Module version is '" + CString(Version(), 3) + "', but core expects '" +
			CString(CModule::GetCoreVersion(), 3) + "'. Please re-download/re-install/re-compile the module.";
#endif
	} else {
		sRetMsg = "";
		bVersionMismatch = false;
		bIsGlobal = IsGlobal();
		sDesc = GetDesc();
	}

	return p;
}
Example #25
0
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;
}
Example #26
0
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;
}
Example #27
0
void ListServer_Main()
{
	static CBuffer packetBuffer;
	CStringList lines;

	if ( listServerFields[5] == "localhost" ) return;
	if (!lsConnected) return;

	// Read any new data into the socket.
	if ( listServer.getData() == -1 )
	{
		errorOut( "serverlog.txt", "Disconnected from list server." );
		lsConnected = false;
		return;
	}

	// Grab all the data from the socket buffer.
	packetBuffer << listServer.getBuffer();
	listServer.getBuffer().clear();

	// Search for a packet.  If none is found, break out of the loop.
	while (packetBuffer.length() != 0)
	{
		CPacket line;
		if (!nextIsRaw)
		{
			int lineEnd = packetBuffer.find( '\n' );
			if ( lineEnd == -1 ) return;

			// Copy the packet out and remove the \n
			line = packetBuffer.copy( 0, lineEnd + 1 );
			packetBuffer.remove(0, line.length());
			line.remove(line.length() - 1, 1);
		}
		else
		{
			if (packetBuffer.length() < rawPacketSize) return;
			line.writeBytes(packetBuffer.readChars(rawPacketSize), rawPacketSize);
			packetBuffer.remove(0, line.length());
			line.remove(line.length() - 1, 1);
			nextIsRaw = false;
		}
		packetBuffer.setRead(0);

		int messageId = line.readByte1();
		switch (messageId)
		{
			case GSVOLD:
			{
				printf("[%s] SERVER VERSION CHECK - Current: %i, Latest: %i - Old version, please upgrade.\n", getTimeStr(1).text(), GSERVER_BUILD, line.readByte2());
				break;
			}

			case GSVCURRENT:
			{
				printf("[%s] SERVER VERSION CHECK - Current: %i, Latest: %i - You are up to date :)\n", getTimeStr(1).text(), GSERVER_BUILD, GSERVER_BUILD);
				break;
			}

			case GSVACCOUNT:
			{
				CString accountName = line.readChars(line.readByte1());
				CString errorMsg = line.readString("");

				for (int i = 0; i < newPlayers.count(); i++)
				{
					CPlayer *player = (CPlayer *)newPlayers[i];

					if (player->accountName.comparei(accountName) == 0)
					{
						// The serverlist will return case sensitive account names.
						// This helps case sensitive file systems open/save the correct
						// acount.
						player->accountName = accountName;
						if (errorMsg == "SUCCESS")
						{
							player->sendAccount();
						}
						else
						{
							player->sendPacket(CPacket() << (char)DISMESSAGE << errorMsg);
							player->deleteMe = true;
						}

						break;
					}
				}

				break;
			}

			case GSVGUILD:
			{
				int playerId = line.readByte2();
				CPlayer *player = (CPlayer *)playerIds[playerId];

				if (player != NULL)
				{
					CString nick = line.readChars((unsigned char)line.readByte1());
					CString guild = nick.copy( nick.findl( '(' ) ).remove( ")" );

					if ( globalGuilds == false )
					{
						if ( globalGuildList.find( guild ) != -1 )
							player->setNick(nick, false);
					}
					else
						player->setNick(nick, false);
				}

				break;
			}

			case GSVPROFILE: /* Unsure if this works, temp */
			{
				CPacket profile;
				CPlayer *player1 = (CPlayer *)playerIds[line.readByte2()];
				CPlayer *player2 = findPlayerId(line.readChars(line.readByte1()));
				if (player1 == NULL || player2 == NULL)
					return;

				profile << (char)player2->accountName.length() << player2->accountName << line.readString("");

				int time = player2->onlineSecs;
				CString line2;
				//Online time
				line2 << toString((int)time/3600) << " hrs ";
				line2 << toString((int)(time/60)%60) << " mins ";
				line2 << toString((int)time%60) << " secs";
				profile << (char)line2.length() << line2;

				for (int i = 0; i < profileList.count(); i++)
				{
					CStringList a;
					a.load(profileList[i].text(), ":=");
					if (a[0].length() < 1)
						continue;

					CString n;

					if (a[1] == "playerkills")
						n = toString(player2->kills);
					else if (a[1] == "playerdeaths")
						n = toString(player2->deaths);
					else if (a[1] == "playerfullhearts")
					{
						if ( (float)(int)player2->maxPower == (float)player2->maxPower )
							n = toString((int)player2->maxPower);
						else
						{
							n = toString(player2->maxPower);
							n = n.copy( 0, n.length() - 1 );
						}
					}
					else if (a[1] == "playerrating")
						n = toString((int)player2->rating) << "/" << toString((int)player2->deviation);
					else if (a[1] == "playerap")
						n = toString(player2->ap);
					else if (a[1] == "playerrupees")
						n = toString(player2->rubins);
					else if (a[1] == "playerswordpower")
						n = toString(player2->swordPower);
					else if (a[1] == "canspin")
						n = (player2->status & 64 ? "true" : "false");
					else if (a[1] == "playerhearts")
					{
						if ( (float)(int)player2->power == (float)player2->power )
							n = toString((int)player2->power);
						else
						{
							n = toString(player2->power);
							n = n.copy( 0, n.length() - 1 );
						}
					}
					else if (a[1] == "playerdarts")
						n = toString(player2->darts);
					else if (a[1] == "playerbombs")
						n = toString(player2->bombs);
					else if (a[1] == "playermp")
						n = toString(player2->magicPoints);
					else if (a[1] == "playershieldpower")
						n = toString(player2->shieldPower);
					else if (a[1] == "playerglovepower")
						n = toString(player2->glovePower);
					else
					{
						for (int i = 0; i < player2->myFlags.count(); i++)
						{
							CStringList b;
							b.load(player2->myFlags[i].text(), "=");
							if (b[0] == a[1])
							{
								n = b[1];
								break;
							}
						}
					}

					profile << (char)(a[0].length() + n.length() + 2) << a[0] << ":=" << n;
				}

				player1->sendPacket(CPacket() << (char)DPROFILE << profile);
				break;
			}

			case GSVMSG:
				printf("[%s] %s\n", getTimeStr(1).text(), line.readString(""));
			break;

			case GSVFILESTART3:
			{
				unsigned char pTy = (unsigned char)line.readByte1();
				CString fileData, fileName = CString() << dataDir << "global" << fSep;
				switch (pTy)
				{
					case 0: // head
						fileName << "heads" << fSep;
					break;

					case 1: // body
						fileName << "bodies" << fSep;
					break;

					case 2: // sword
						fileName << "swords" << fSep;
					break;

					case 3: // shield
						fileName << "shields" << fSep;
					break;
				}
				fileName << line.readChars(line.readByte1());
				fileData.save(fileName.text());
				break;
			}

			case GSVFILEDATA3:
			{
				unsigned char pTy = (unsigned char)line.readByte1();
				CString fileData, fileName, newData, shortName;
				shortName = line.readChars(line.readByte1());
				fileName = CString() << dataDir << "global" << fSep;
				switch (pTy)
				{
					case 0: // head
						fileName << "heads" << fSep;
					break;

					case 1: // body
						fileName << "bodies" << fSep;
					break;

					case 2: // sword
						fileName << "swords" << fSep;
					break;

					case 3: // shield
						fileName << "shields" << fSep;
					break;
				}
				fileName << shortName.text();
				newData.writeBytes(line.readChars(line.bytesLeft()), line.bytesLeft());

				fileData.load(fileName.text());
				fileData << newData;
				fileData.save(fileName.text());
				break;
			}

			case GSVFILEEND3:
			{
				CPlayer *player = (CPlayer *)playerIds[line.readByte2()];
				int type = line.readByte1();
				char doCompress = line.readByte1();
				time_t modTime = line.readByte5();
				int fileLength = line.readByte5();
				CString shortName = line.readString("");
				CString fileName = CString() << dataDir << "global" << fSep;
				switch (type)
				{
					case 0: // head
						fileName << "heads" << fSep;
					break;

					case 1: // body
						fileName << "bodies" << fSep;
					break;

					case 2: // sword
						fileName << "swords" << fSep;
					break;

					case 3: // shield
						fileName << "shields" << fSep;
					break;
				}
				fileName << shortName.text();

				// If the file was sent compressed, we need to uncompress it.
				if (doCompress == 1)
				{
					// Open the file so we can uncompress it.
					CString fileData;
					fileData.load(fileName.text());

					// Uncompress the file.
					char* buffer = new char[fileLength];
					memset((void*)buffer, 0, fileLength);
					int cLen = fileLength;
					int error = uncompress((Bytef*)buffer,(uLongf*)&cLen,(const Bytef*)fileData.text(), fileData.length());
					if (error != Z_OK) printf("Failed to decompress file: %s\n", shortName.text());

					// Save the file now.
					fileData.clear();
					fileData.writeBytes(buffer, cLen);
					fileData.save(fileName.text());
					delete [] buffer;
				}

				// Set the file mod time.
				if (setFileModTime(fileName.text(), modTime) == false)
					printf("** [WARNING] Could not set modification time on file %s\n", shortName.text());

				if (player)
				{
					player->fileList.add(new COutFile(shortName, 0));
					switch (type)
					{
						case 0: // head
							player->headImage = shortName;
							player->updateProp(HEADGIF);
						break;

						case 1: // body
							player->bodyImage = shortName;
							player->updateProp(BODYIMG);
						break;

						case 2: // sword
							player->swordImage = shortName;
							player->updateProp(SWORDPOWER);
						break;

						case 3: // shield
							player->shieldImage = shortName;
							player->updateProp(SHIELDPOWER);
						break;
					}
				}
				break;
			}

			case GSVPING:
				// Sent every 60 seconds, do nothing.
			break;

			case GSVRAWDATA:
				nextIsRaw = true;
				rawPacketSize = line.readByte3();
			break;

			default:
				printf("[%s] Invalid List Server Message: %i\n", getTimeStr(1).text(), messageId);
			break;
		}
	}
}