Add CIRCNetwork which now hold each IRC Connection.

This allows a user to have multiple networks.

A user can login as a network by supplying PASS [user[/network]:]pass or
USER user[/network] on connect. A user can also switch between networks
by using /msg *status JumpNetwork <network>
This commit is contained in:
Kyle Fuller
2011-08-24 13:52:34 +01:00
parent 88033a5b3e
commit fec1a3fe91
9 changed files with 1204 additions and 662 deletions
+12 -4
View File
@@ -67,13 +67,17 @@ public:
return true;
}
bool FindStringVector(const CString& sName, VCString& vsList) {
bool FindStringVector(const CString& sName, VCString& vsList, bool bErase = true) {
EntryMap::iterator it = m_ConfigEntries.find(sName);
vsList.clear();
if (it == m_ConfigEntries.end())
return false;
vsList = it->second;
m_ConfigEntries.erase(it);
if (bErase) {
m_ConfigEntries.erase(it);
}
return true;
}
@@ -109,14 +113,18 @@ public:
return false;
}
bool FindSubConfig(const CString& sName, SubConfig& Config) {
bool FindSubConfig(const CString& sName, SubConfig& Config, bool bErase = true) {
SubConfigMap::iterator it = m_SubConfigs.find(sName);
if (it == m_SubConfigs.end()) {
Config.clear();
return false;
}
Config = it->second;
m_SubConfigs.erase(it);
if (bErase) {
m_SubConfigs.erase(it);
}
return true;
}
+796
View File
@@ -0,0 +1,796 @@
/*
* Copyright (C) 2004-2011 See the AUTHORS file for details.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include "IRCNetwork.h"
#include "Modules.h"
#include "User.h"
#include "FileUtils.h"
#include "Config.h"
#include "Client.h"
#include "IRCSock.h"
#include "Server.h"
#include "Chan.h"
#include "znc.h"
bool CIRCNetwork::IsValidNetwork(const CString& sNetwork) {
// ^[-\w]+$
if (sNetwork.empty()) {
return false;
}
const char *p = sNetwork.c_str();
while (*p) {
if (*p != '_' && *p != '-' && !isalnum(*p)) {
return false;
}
p++;
}
return true;
}
CIRCNetwork::CIRCNetwork(CUser *pUser, const CString& sName) {
m_pUser = NULL;
SetUser(pUser);
m_sName = sName;
m_pModules = new CModules;
m_pIRCSock = NULL;
m_uServerIdx = 0;
m_sChanPrefixes = "";
m_bIRCAway = false;
m_RawBuffer.SetLineCount(100); // This should be more than enough raws, especially since we are buffering the MOTD separately
m_MotdBuffer.SetLineCount(200); // This should be more than enough motd lines
m_QueryBuffer.SetLineCount(250);
}
CIRCNetwork::CIRCNetwork(CUser *pUser, const CIRCNetwork *pNetwork, bool bCloneChans) {
m_pUser = NULL;
SetUser(pUser);
m_sName = pNetwork->GetName();
m_pModules = new CModules;
m_pIRCSock = NULL;
m_uServerIdx = 0;
m_sChanPrefixes = "";
m_bIRCAway = false;
m_RawBuffer.SetLineCount(100); // This should be more than enough raws, especially since we are buffering the MOTD separately
m_MotdBuffer.SetLineCount(200); // This should be more than enough motd lines
m_QueryBuffer.SetLineCount(250);
// Servers
const vector<CServer*>& vServers = pNetwork->GetServers();
CString sServer;
CServer* pCurServ = GetCurrentServer();
if (pCurServ) {
sServer = pCurServ->GetName();
}
DelServers();
unsigned int a;
for (a = 0; a < vServers.size(); a++) {
CServer* pServer = vServers[a];
AddServer(pServer->GetName(), pServer->GetPort(), pServer->GetPass(), pServer->IsSSL());
}
m_uServerIdx = 0;
for (a = 0; a < m_vServers.size(); a++) {
if (sServer.Equals(m_vServers[a]->GetName())) {
m_uServerIdx = a + 1;
break;
}
}
if (m_uServerIdx == 0) {
m_uServerIdx = m_vServers.size();
CIRCSock* pSock = GetIRCSock();
if (pSock) {
PutStatus("Jumping servers because this server is no longer in the list");
pSock->Quit();
}
}
// !Servers
// Chans
const vector<CChan*>& vChans = pNetwork->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 = pNetwork->FindChan(pChan->GetName());
if (!pNewChan) {
pChan->SetInConfig(false);
} else {
if (bCloneChans)
pChan->Clone(*pNewChan);
}
}
// !Chans
}
CIRCNetwork::~CIRCNetwork() {
DelClients();
DelServers();
DelModules();
SetUser(NULL);
for (unsigned int b = 0; b < m_vChans.size(); b++) {
delete m_vChans[b];
}
}
CString CIRCNetwork::GetNetworkPath() {
CString sNetworkPath = m_pUser->GetUserPath() + "/networks/" + m_sName;
if (!CFile::Exists(sNetworkPath)) {
CDir::MakeDir(sNetworkPath);
}
return sNetworkPath;
}
void CIRCNetwork::DelClients() {
for (unsigned int c = 0; c < m_vClients.size(); c++) {
CClient* pClient = m_vClients[c];
CZNC::Get().GetManager().DelSockByAddr(pClient);
}
m_vClients.clear();
}
void CIRCNetwork::DelServers() {
for (unsigned int a = 0; a < m_vServers.size(); a++) {
delete m_vServers[a];
}
m_vServers.clear();
}
void CIRCNetwork::DelModules() {
delete m_pModules;
m_pModules = NULL;
}
bool CIRCNetwork::ParseConfig(CConfig *pConfig, CString& sError, bool bUpgrade) {
VCString vsList;
VCString::const_iterator vit;
if (!bUpgrade) {
pConfig->FindStringVector("loadmodule", vsList);
for (vit = vsList.begin(); vit != vsList.end(); ++vit) {
CString sValue = *vit;
CString sModName = sValue.Token(0);
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;
}
CConfig CIRCNetwork::ToConfig() {
CConfig config;
// Modules
CModules& Mods = GetModules();
if (!Mods.empty()) {
for (unsigned int a = 0; a < Mods.size(); a++) {
CString sArgs = Mods[a]->GetArgs();
if (!sArgs.empty()) {
sArgs = " " + sArgs;
}
config.AddKeyValuePair("LoadModule", Mods[a]->GetModName() + sArgs);
}
}
// Servers
for (unsigned int b = 0; b < m_vServers.size(); b++) {
config.AddKeyValuePair("Server", m_vServers[b]->GetString());
}
// Chans
for (unsigned int c = 0; c < m_vChans.size(); c++) {
CChan* pChan = m_vChans[c];
if (pChan->InConfig()) {
config.AddSubConfig("Chan", pChan->GetName(), pChan->ToConfig());
}
}
return config;
}
void CIRCNetwork::BounceAllClients() {
for (unsigned int a = 0; a < m_vClients.size(); a++) {
m_vClients[a]->BouncedOff();
}
m_vClients.clear();
}
void CIRCNetwork::ClientConnected(CClient *pClient) {
if (!m_pUser->MultiClients()) {
BounceAllClients();
}
m_vClients.push_back(pClient);
if (m_RawBuffer.IsEmpty()) {
pClient->PutClient(":irc.znc.in 001 " + pClient->GetNick() + " :- Welcome to ZNC -");
} else {
unsigned int uIdx = 0;
CString sLine;
while (m_RawBuffer.GetLine(GetIRCNick().GetNick(), sLine, uIdx++)) {
pClient->PutClient(sLine);
}
// The assumption is that the client got this nick from the 001 reply
pClient->SetNick(GetIRCNick().GetNick());
}
// Send the cached MOTD
unsigned int uIdx = 0;
CString sLine;
while (m_MotdBuffer.GetLine(GetIRCNick().GetNick(), sLine, uIdx++)) {
pClient->PutClient(sLine);
}
if (GetIRCSock() != NULL) {
CString sUserMode("");
const set<unsigned char>& scUserModes = GetIRCSock()->GetUserModes();
for (set<unsigned char>::const_iterator it = scUserModes.begin();
it != scUserModes.end(); ++it) {
sUserMode += *it;
}
if (!sUserMode.empty()) {
pClient->PutClient(":" + GetIRCNick().GetNickMask() + " MODE " + GetIRCNick().GetNick() + " :+" + sUserMode);
}
}
if (m_bIRCAway) {
// If they want to know their away reason they'll have to whois
// themselves. At least we can tell them their away status...
pClient->PutClient(":irc.znc.in 306 " + GetIRCNick().GetNick() + " :You have been marked as being away");
}
const vector<CChan*>& vChans = GetChans();
for (unsigned int a = 0; a < vChans.size(); a++) {
if ((vChans[a]->IsOn()) && (!vChans[a]->IsDetached())) {
vChans[a]->JoinUser(true, "", pClient);
}
}
CString sBufLine;
while (m_QueryBuffer.GetNextLine(GetIRCNick().GetNick(), sBufLine)) {
MODULECALL(OnPrivBufferPlayLine(*pClient, sBufLine), m_pUser, this, NULL, continue);
pClient->PutClient(sBufLine);
}
// Tell them why they won't connect
if (!m_pUser->GetIRCConnectEnabled())
pClient->PutStatus("You are currently disconnected from IRC. "
"Use 'connect' to reconnect.");
}
void CIRCNetwork::ClientDisconnected(CClient *pClient) {
for (unsigned int a = 0; a < m_vClients.size(); a++) {
if (m_vClients[a] == pClient) {
m_vClients.erase(m_vClients.begin() + a);
break;
}
}
}
CUser* CIRCNetwork::GetUser() {
return m_pUser;
}
const CString& CIRCNetwork::GetName() const {
return m_sName;
}
void CIRCNetwork::SetUser(CUser *pUser) {
for (unsigned int a = 0; a < m_vClients.size(); a++) {
m_vClients[a]->PutStatus("This network is being deleted or moved to another user.");
m_vClients[a]->SetNetwork(NULL);
}
m_vClients.clear();
if (m_pUser) {
m_pUser->RemoveNetwork(this);
}
m_pUser = pUser;
if (m_pUser) {
m_pUser->AddNetwork(this);
}
}
bool CIRCNetwork::SetName(const CString& sName) {
if (IsValidNetwork(sName)) {
m_sName = sName;
return true;
}
return false;
}
bool CIRCNetwork::PutUser(const CString& sLine, CClient* pClient, CClient* pSkipClient) {
for (unsigned int a = 0; a < m_vClients.size(); a++) {
if ((!pClient || pClient == m_vClients[a]) && pSkipClient != m_vClients[a]) {
m_vClients[a]->PutClient(sLine);
if (pClient) {
return true;
}
}
}
return (pClient == NULL);
}
bool CIRCNetwork::PutStatus(const CString& sLine, CClient* pClient, CClient* pSkipClient) {
for (unsigned int a = 0; a < m_vClients.size(); a++) {
if ((!pClient || pClient == m_vClients[a]) && pSkipClient != m_vClients[a]) {
m_vClients[a]->PutStatus(sLine);
if (pClient) {
return true;
}
}
}
return (pClient == NULL);
}
// Channels
const vector<CChan*>& CIRCNetwork::GetChans() const { return m_vChans; }
CChan* CIRCNetwork::FindChan(const CString& sName) const {
for (unsigned int a = 0; a < m_vChans.size(); a++) {
CChan* pChan = m_vChans[a];
if (sName.Equals(pChan->GetName())) {
return pChan;
}
}
return NULL;
}
bool CIRCNetwork::AddChan(CChan* pChan) {
if (!pChan) {
return false;
}
for (unsigned int a = 0; a < m_vChans.size(); a++) {
if (m_vChans[a]->GetName().Equals(pChan->GetName())) {
delete pChan;
return false;
}
}
m_vChans.push_back(pChan);
return true;
}
bool CIRCNetwork::AddChan(const CString& sName, bool bInConfig) {
if (sName.empty() || FindChan(sName)) {
return false;
}
CChan* pChan = new CChan(sName, this, bInConfig);
m_vChans.push_back(pChan);
return true;
}
bool CIRCNetwork::DelChan(const CString& sName) {
for (vector<CChan*>::iterator a = m_vChans.begin(); a != m_vChans.end(); ++a) {
if (sName.Equals((*a)->GetName())) {
delete *a;
m_vChans.erase(a);
return true;
}
}
return false;
}
void CIRCNetwork::JoinChans() {
// Avoid divsion by zero, it's bad!
if (m_vChans.empty())
return;
// We start at a random offset into the channel list so that if your
// first 3 channels are invite-only and you got MaxJoins == 3, ZNC will
// still be able to join the rest of your channels.
unsigned int start = rand() % m_vChans.size();
unsigned int uJoins = m_pUser->MaxJoins();
set<CChan*> sChans;
for (unsigned int a = 0; a < m_vChans.size(); a++) {
unsigned int idx = (start + a) % m_vChans.size();
CChan* pChan = m_vChans[idx];
if (!pChan->IsOn() && !pChan->IsDisabled()) {
if (!JoinChan(pChan))
continue;
sChans.insert(pChan);
// Limit the number of joins
if (uJoins != 0 && --uJoins == 0)
break;
}
}
while (!sChans.empty())
JoinChans(sChans);
}
void CIRCNetwork::JoinChans(set<CChan*>& sChans) {
CString sKeys, sJoin;
bool bHaveKey = false;
size_t uiJoinLength = strlen("JOIN ");
while (!sChans.empty()) {
set<CChan*>::iterator it = sChans.begin();
const CString& sName = (*it)->GetName();
const CString& sKey = (*it)->GetKey();
size_t len = sName.length() + sKey.length();
len += 2; // two comma
if (!sKeys.empty() && uiJoinLength + len >= 512)
break;
if (!sJoin.empty()) {
sJoin += ",";
sKeys += ",";
}
uiJoinLength += len;
sJoin += sName;
if (!sKey.empty()) {
sKeys += sKey;
bHaveKey = true;
}
sChans.erase(it);
}
if (bHaveKey)
PutIRC("JOIN " + sJoin + " " + sKeys);
else
PutIRC("JOIN " + sJoin);
}
bool CIRCNetwork::JoinChan(CChan* pChan) {
if (m_pUser->JoinTries() != 0 && pChan->GetJoinTries() >= m_pUser->JoinTries()) {
PutStatus("The channel " + pChan->GetName() + " could not be joined, disabling it.");
pChan->Disable();
} else {
pChan->IncJoinTries();
MODULECALL(OnTimerAutoJoin(*pChan), m_pUser, this, NULL, return false);
return true;
}
return false;
}
bool CIRCNetwork::IsChan(const CString& sChan) const {
if (sChan.empty())
return false; // There is no way this is a chan
if (GetChanPrefixes().empty())
return true; // We can't know, so we allow everything
// Thanks to the above if (empty), we can do sChan[0]
return GetChanPrefixes().find(sChan[0]) != CString::npos;
}
// Server list
const vector<CServer*>& CIRCNetwork::GetServers() const { return m_vServers; }
CServer* CIRCNetwork::FindServer(const CString& sName) const {
for (unsigned int a = 0; a < m_vServers.size(); a++) {
CServer* pServer = m_vServers[a];
if (sName.Equals(pServer->GetName())) {
return pServer;
}
}
return NULL;
}
bool CIRCNetwork::DelServer(const CString& sName, unsigned short uPort, const CString& sPass) {
if (sName.empty()) {
return false;
}
unsigned int a = 0;
bool bSawCurrentServer = false;
CServer* pCurServer = GetCurrentServer();
for (vector<CServer*>::iterator it = m_vServers.begin(); it != m_vServers.end(); it++, a++) {
CServer* pServer = *it;
if (pServer == pCurServer)
bSawCurrentServer = true;
if (!pServer->GetName().Equals(sName))
continue;
if (uPort != 0 && pServer->GetPort() != uPort)
continue;
if (!sPass.empty() && pServer->GetPass() != sPass)
continue;
m_vServers.erase(it);
if (pServer == pCurServer) {
CIRCSock* pIRCSock = GetIRCSock();
// Make sure we don't skip the next server in the list!
if (m_uServerIdx) {
m_uServerIdx--;
}
if (pIRCSock) {
pIRCSock->Quit();
PutStatus("Your current server was removed, jumping...");
}
} else if (!bSawCurrentServer) {
// Our current server comes after the server which we
// are removing. This means that it now got a different
// index in m_vServers!
m_uServerIdx--;
}
delete pServer;
return true;
}
return false;
}
bool CIRCNetwork::AddServer(const CString& sName) {
if (sName.empty()) {
return false;
}
bool bSSL = false;
CString sLine = sName;
sLine.Trim();
CString sHost = sLine.Token(0);
CString sPort = sLine.Token(1);
if (sPort.Left(1) == "+") {
bSSL = true;
sPort.LeftChomp();
}
unsigned short uPort = sPort.ToUShort();
CString sPass = sLine.Token(2, true);
return AddServer(sHost, uPort, sPass, bSSL);
}
bool CIRCNetwork::AddServer(const CString& sName, unsigned short uPort, const CString& sPass, bool bSSL) {
#ifndef HAVE_LIBSSL
if (bSSL) {
return false;
}
#endif
if (sName.empty()) {
return false;
}
if (!uPort) {
uPort = 6667;
}
// Check if server is already added
for (unsigned int a = 0; a < m_vServers.size(); a++) {
CServer* pServer = m_vServers[a];
if (!sName.Equals(pServer->GetName()))
continue;
if (uPort != pServer->GetPort())
continue;
if (sPass != pServer->GetPass())
continue;
if (bSSL != pServer->IsSSL())
continue;
// Server is already added
return false;
}
CServer* pServer = new CServer(sName, uPort, sPass, bSSL);
m_vServers.push_back(pServer);
CheckIRCConnect();
return true;
}
CServer* CIRCNetwork::GetNextServer() {
if (m_vServers.empty()) {
return NULL;
}
if (m_uServerIdx >= m_vServers.size()) {
m_uServerIdx = 0;
}
return m_vServers[m_uServerIdx++];
}
CServer* CIRCNetwork::GetCurrentServer() const {
unsigned int uIdx = (m_uServerIdx) ? m_uServerIdx -1 : 0;
if (uIdx >= m_vServers.size()) {
return NULL;
}
return m_vServers[uIdx];
}
void CIRCNetwork::SetIRCServer(const CString& s) { m_sIRCServer = s; }
bool CIRCNetwork::SetNextServer(const CServer* pServer) {
for (unsigned int a = 0; a < m_vServers.size(); a++) {
if (m_vServers[a] == pServer) {
m_uServerIdx = a;
return true;
}
}
return false;
}
bool CIRCNetwork::IsLastServer() const {
return (m_uServerIdx >= m_vServers.size());
}
const CString& CIRCNetwork::GetIRCServer() const { return m_sIRCServer; }
const CNick& CIRCNetwork::GetIRCNick() const { return m_IRCNick; }
void CIRCNetwork::SetIRCNick(const CNick& n) {
m_IRCNick = n;
for (unsigned int a = 0; a < m_vClients.size(); a++) {
m_vClients[a]->SetNick(n.GetNick());
}
}
CString CIRCNetwork::GetCurNick() const {
const CIRCSock* pIRCSock = GetIRCSock();
if (pIRCSock) {
return pIRCSock->GetNick();
}
if (!m_vClients.empty()) {
return m_vClients[0]->GetNick();
}
return "";
}
bool CIRCNetwork::IsIRCConnected() const {
const CIRCSock* pSock = GetIRCSock();
return (pSock && pSock->IsAuthed());
}
void CIRCNetwork::SetIRCSocket(CIRCSock* pIRCSock) {
m_pIRCSock = pIRCSock;
}
void CIRCNetwork::IRCDisconnected() {
m_pIRCSock = NULL;
SetIRCServer("");
m_bIRCAway = false;
// Get the reconnect going
CheckIRCConnect();
}
void CIRCNetwork::CheckIRCConnect() {
// Do we want to connect?
if (m_pUser->GetIRCConnectEnabled() && GetIRCSock() == NULL)
CZNC::Get().EnableConnectUser();
}
bool CIRCNetwork::PutIRC(const CString& sLine) {
CIRCSock* pIRCSock = GetIRCSock();
if (!pIRCSock) {
return false;
}
pIRCSock->PutIRC(sLine);
return true;
}
+153
View File
@@ -0,0 +1,153 @@
/*
* Copyright (C) 2004-2011 See the AUTHORS file for details.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#ifndef _IRCNETWORK_H
#define _IRCNETWORK_H
#include "zncconfig.h"
#include "ZNCString.h"
#include "Buffer.h"
#include "Nick.h"
#include "znc.h"
class CModules;
class CUser;
class CFile;
class CConfig;
class CClient;
class CConfig;
class CChan;
class CServer;
class CIRCSock;
class CIRCNetwork {
public:
static bool IsValidNetwork(const CString& sNetwork);
CIRCNetwork(CUser *pUser, const CString& sName);
CIRCNetwork(CUser *pUser, const CIRCNetwork *pNetwork, bool bCloneChans = true);
~CIRCNetwork();
CString GetNetworkPath();
void DelClients();
void DelServers();
bool ParseConfig(CConfig *pConfig, CString& sError, bool bUpgrade = false);
CConfig ToConfig();
void BounceAllClients();
bool IsUserAttached() const { return !m_vClients.empty(); }
void ClientConnected(CClient *pClient);
void ClientDisconnected(CClient *pClient);
CUser* GetUser();
const CString& GetName() const;
bool IsNetworkAttached() const { return !m_vClients.empty(); };
vector<CClient*>& GetClients() { return m_vClients; }
void SetUser(CUser *pUser);
bool SetName(const CString& sName);
// Modules
void DelModules();
CModules& GetModules() { return *m_pModules; }
const CModules& GetModules() const { return *m_pModules; }
// !Modules
bool PutUser(const CString& sLine, CClient* pClient = NULL, CClient* pSkipClient = NULL);
bool PutStatus(const CString& sLine, CClient* pClient = NULL, CClient* pSkipClient = NULL);
const vector<CChan*>& GetChans() const;
CChan* FindChan(const CString& sName) const;
bool AddChan(CChan* pChan);
bool AddChan(const CString& sName, bool bInConfig);
bool DelChan(const CString& sName);
void JoinChans();
const CString& GetChanPrefixes() const { return m_sChanPrefixes; };
void SetChanPrefixes(const CString& s) { m_sChanPrefixes = s; };
bool IsChan(const CString& sChan) const;
const vector<CServer*>& GetServers() const;
bool HasServers() const { return !m_vServers.empty(); }
CServer* FindServer(const CString& sName) const;
bool DelServer(const CString& sName, unsigned short uPort, const CString& sPass);
bool AddServer(const CString& sName);
bool AddServer(const CString& sName, unsigned short uPort, const CString& sPass = "", bool bSSL = false);
CServer* GetNextServer();
CServer* GetCurrentServer() const;
void SetIRCServer(const CString& s);
bool SetNextServer(const CServer* pServer);
bool IsLastServer() const;
CIRCSock* GetIRCSock() { return m_pIRCSock; }
const CIRCSock* GetIRCSock() const { return m_pIRCSock; }
const CString& GetIRCServer() const;
const CNick& GetIRCNick() const;
void SetIRCNick(const CNick& n);
CString GetCurNick() const;
bool IsIRCAway() const { return m_bIRCAway; }
void SetIRCAway(bool b) { m_bIRCAway = b; }
/** This method will return whether the user is connected and authenticated to an IRC server.
*/
bool IsIRCConnected() const;
void SetIRCSocket(CIRCSock* pIRCSock);
void IRCDisconnected();
void CheckIRCConnect();
bool PutIRC(const CString& sLine);
// Buffers
void AddRawBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_RawBuffer.AddLine(sPre, sPost, bIncNick); }
void UpdateRawBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_RawBuffer.UpdateLine(sPre, sPost, bIncNick); }
void UpdateExactRawBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_RawBuffer.UpdateExactLine(sPre, sPost, bIncNick); }
void ClearRawBuffer() { m_RawBuffer.Clear(); }
void AddMotdBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_MotdBuffer.AddLine(sPre, sPost, bIncNick); }
void UpdateMotdBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_MotdBuffer.UpdateLine(sPre, sPost, bIncNick); }
void ClearMotdBuffer() { m_MotdBuffer.Clear(); }
void AddQueryBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_QueryBuffer.AddLine(sPre, sPost, bIncNick); }
void UpdateQueryBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_QueryBuffer.UpdateLine(sPre, sPost, bIncNick); }
void ClearQueryBuffer() { m_QueryBuffer.Clear(); }
// !Buffers
private:
bool JoinChan(CChan* pChan);
void JoinChans(set<CChan*>& sChans);
protected:
CString m_sName;
CUser* m_pUser;
CModules* m_pModules;
vector<CClient*> m_vClients;
CIRCSock* m_pIRCSock;
vector<CChan*> m_vChans;
CString m_sChanPrefixes;
CString m_sIRCServer;
vector<CServer*> m_vServers;
unsigned int m_uServerIdx; ///< Index in m_vServers of our current server + 1
CNick m_IRCNick;
bool m_bIRCAway;
CBuffer m_RawBuffer;
CBuffer m_MotdBuffer;
CBuffer m_QueryBuffer;
};
#endif // !_IRCNETWORK_H
+2 -2
View File
@@ -55,11 +55,11 @@ bool CRealListener::ConnectionFrom(const CString& sHost, unsigned short uPort) {
Csock* CRealListener::GetSockObj(const CString& sHost, unsigned short uPort) {
CIncomingConnection *pClient = new CIncomingConnection(sHost, uPort, m_pParent->GetAcceptType());
if (CZNC::Get().AllowConnectionFrom(sHost)) {
GLOBALMODULECALL(OnClientConnect(pClient, sHost, uPort), NULL, NULL, NOTHING);
GLOBALMODULECALL(OnClientConnect(pClient, sHost, uPort), NULL, NULL, NULL, NOTHING);
} else {
pClient->Write(":irc.znc.in 464 unknown-nick :Too many anonymous connections from your IP\r\n");
pClient->Close(Csock::CLT_AFTERWRITE);
GLOBALMODULECALL(OnFailedLogin("", sHost), NULL, NULL, NOTHING);
GLOBALMODULECALL(OnFailedLogin("", sHost), NULL, NULL, NULL, NOTHING);
}
return pClient;
}
+2 -2
View File
@@ -28,8 +28,8 @@ INSTALL_PROGRAM := @INSTALL_PROGRAM@
INSTALL_SCRIPT := @INSTALL_SCRIPT@
INSTALL_DATA := @INSTALL_DATA@
LIB_SRCS := ZNCString.cpp Csocket.cpp znc.cpp User.cpp IRCSock.cpp Client.cpp \
Chan.cpp Nick.cpp Server.cpp Modules.cpp MD5.cpp Buffer.cpp Utils.cpp \
LIB_SRCS := ZNCString.cpp Csocket.cpp znc.cpp IRCNetwork.cpp User.cpp IRCSock.cpp \
Client.cpp Chan.cpp Nick.cpp Server.cpp Modules.cpp MD5.cpp Buffer.cpp Utils.cpp \
FileUtils.cpp HTTPSock.cpp Template.cpp ClientCommand.cpp Socket.cpp SHA256.cpp \
WebModules.cpp Listener.cpp Config.cpp ZNCDebug.cpp
BIN_SRCS := main.cpp
+181 -559
View File
@@ -10,6 +10,7 @@
#include "Chan.h"
#include "Config.h"
#include "FileUtils.h"
#include "IRCNetwork.h"
#include "IRCSock.h"
#include "Server.h"
#include "znc.h"
@@ -26,23 +27,28 @@ public:
private:
protected:
virtual void RunJob() {
vector<CClient*>& vClients = m_pUser->GetClients();
CIRCSock* pIRCSock = m_pUser->GetIRCSock();
vector<CIRCNetwork*> vNetworks = m_pUser->GetNetworks();
if (pIRCSock && pIRCSock->GetTimeSinceLastDataTransaction() >= 270) {
pIRCSock->PutIRC("PING :ZNC");
}
for (size_t a = 0; a < vNetworks.size(); a++) {
CIRCNetwork* pNetwork = vNetworks[a];
CIRCSock* pIRCSock = pNetwork->GetIRCSock();
for (size_t a = 0; a < vClients.size(); a++) {
CClient* pClient = vClients[a];
if (pClient->GetTimeSinceLastDataTransaction() >= 270) {
pClient->PutClient("PING :ZNC");
if (pIRCSock && pIRCSock->GetTimeSinceLastDataTransaction() >= 270) {
pIRCSock->PutIRC("PING :ZNC");
}
}
if (m_pUser->IsIRCConnected()) {
m_pUser->JoinChans();
if (pNetwork->IsIRCConnected()) {
pNetwork->JoinChans();
}
vector<CClient*>& vClients = pNetwork->GetClients();
for (size_t b = 0; b < vClients.size(); b++) {
CClient* pClient = vClients[b];
if (pClient->GetTimeSinceLastDataTransaction() >= 270) {
pClient->PutClient("PING :ZNC");
}
}
}
}
@@ -55,26 +61,19 @@ CUser::CUser(const CString& sUserName)
// set path that depends on the user name:
m_sUserPath = CZNC::Get().GetUserPath() + "/" + m_sUserName;
m_pIRCSock = NULL;
m_fTimezoneOffset = 0;
m_sNick = m_sCleanUserName;
m_sIdent = m_sCleanUserName;
m_sRealName = sUserName;
m_uServerIdx = 0;
m_uBytesRead = 0;
m_uBytesWritten = 0;
m_pModules = new CModules;
m_RawBuffer.SetLineCount(100); // This should be more than enough raws, especially since we are buffering the MOTD separately
m_MotdBuffer.SetLineCount(200); // This should be more than enough motd lines
m_QueryBuffer.SetLineCount(250);
m_bMultiClients = true;
m_eHashType = HASH_NONE;
m_bDenyLoadMod = false;
m_bAdmin= false;
m_bIRCAway = false;
m_bDenySetBindHost= false;
m_sStatusPrefix = "*";
m_sChanPrefixes = "";
m_uBufferCount = 50;
m_uMaxJoinTries = 10;
m_uMaxJoins = 5;
@@ -89,16 +88,12 @@ CUser::CUser(const CString& sUserName)
}
CUser::~CUser() {
DelNetworks();
DelClients();
DelModules();
DelServers();
for (unsigned int b = 0; b < m_vChans.size(); b++) {
delete m_vChans[b];
}
CZNC::Get().GetManager().DelCronByAddr(m_pUserTimer);
}
@@ -169,15 +164,6 @@ bool CUser::ParseConfig(CConfig* pConfig, CString& sError) {
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;
@@ -187,7 +173,7 @@ bool CUser::ParseConfig(CConfig* pConfig, CString& sError) {
if (sValue.ToBool()) {
CUtils::PrintAction("Loading Module [bouncedcc]");
CString sModRet;
bool bModRet = GetModules().LoadModule("bouncedcc", "", CModInfo::UserModule, this, sModRet);
bool bModRet = GetModules().LoadModule("bouncedcc", "", CModInfo::UserModule, this, NULL, sModRet);
CUtils::PrintStatus(bModRet, sModRet);
if (!bModRet) {
@@ -315,29 +301,34 @@ bool CUser::ParseConfig(CConfig* pConfig, CString& sError) {
return false;
}
pConfig->FindSubConfig("chan", subConf);
pConfig->FindSubConfig("network", 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);
const CString& sNetworkName = subIt->first;
if (!pSubConf->empty()) {
sError = "Unhandled lines in config for User [" + GetUserName() + "], Channel [" + sChanName + "]!";
CUtils::PrintError(sError);
CIRCNetwork *pNetwork = FindNetwork(sNetworkName);
CZNC::DumpConfig(pSubConf);
return false;
if (!pNetwork) {
pNetwork = new CIRCNetwork(this, sNetworkName);
}
// 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);
if (!pNetwork->ParseConfig(subIt->second.m_pSubConfig, sError)) {
return false;
}
sError.clear();
}
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 named [user]");
if (!pNetwork->ParseConfig(pConfig, sError, true)) {
return false;
}
}
}
pConfig->FindStringVector("loadmodule", vsList);
@@ -360,8 +351,38 @@ bool CUser::ParseConfig(CConfig* pConfig, CString& sError) {
CUtils::PrintAction("Loading Module [" + sModName + "]");
CString sModRet;
CString sArgs = sValue.Token(1, true);
bool bModRet;
bool bModRet = GetModules().LoadModule(sModName, sArgs, CModInfo::UserModule, this, sModRet);
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) {
@@ -396,7 +417,7 @@ bool CUser::UpdateModule(const CString &sModule) {
CString sErr;
for (it2 = Affected.begin(); it2 != Affected.end(); ++it2) {
if (!it2->first->GetModules().LoadModule(sModule, it2->second, CModInfo::UserModule, it2->first, sErr)) {
if (!it2->first->GetModules().LoadModule(sModule, it2->second, CModInfo::UserModule, it2->first, NULL, sErr)) {
error = true;
DEBUG("Failed to reload [" << sModule << "] for [" << it2->first->GetUserName()
<< "]: " << sErr);
@@ -406,6 +427,15 @@ bool CUser::UpdateModule(const CString &sModule) {
return !error;
}
void CUser::DelNetworks() {
for (unsigned int c = 0; c < m_vIRCNetworks.size(); c++) {
CIRCNetwork* pNetwork = m_vIRCNetworks[c];
delete pNetwork;
}
m_vIRCNetworks.clear();
}
void CUser::DelClients() {
for (unsigned int c = 0; c < m_vClients.size(); c++) {
CClient* pClient = m_vClients[c];
@@ -415,33 +445,57 @@ void CUser::DelClients() {
m_vClients.clear();
}
void CUser::DelServers()
{
for (unsigned int a = 0; a < m_vServers.size(); a++) {
delete m_vServers[a];
CIRCNetwork* CUser::AddNetwork(const CString &sNetwork) {
if (!CIRCNetwork::IsValidNetwork(sNetwork) || FindNetwork(sNetwork)) {
return NULL;
}
m_vServers.clear();
return new CIRCNetwork(this, sNetwork);
}
void CUser::SetIRCSocket(CIRCSock* pIRCSock) {
m_pIRCSock = pIRCSock;
bool CUser::AddNetwork(CIRCNetwork *pNetwork) {
if (FindNetwork(pNetwork->GetName())) {
return false;
}
m_vIRCNetworks.push_back(pNetwork);
return true;
}
bool CUser::IsIRCConnected() const
{
const CIRCSock* pSock = GetIRCSock();
return (pSock && pSock->IsAuthed());
void CUser::RemoveNetwork(CIRCNetwork *pNetwork) {
for (vector<CIRCNetwork*>::iterator it = m_vIRCNetworks.begin(); it != m_vIRCNetworks.end(); ++it) {
if (pNetwork == *it) {
m_vIRCNetworks.erase(it);
return;
}
}
}
void CUser::IRCDisconnected() {
m_pIRCSock = NULL;
bool CUser::DeleteNetwork(CString sNetwork) {
CIRCNetwork *pNetwork = FindNetwork(sNetwork);
SetIRCServer("");
m_bIRCAway = false;
if (pNetwork) {
delete pNetwork;
return true;
}
// Get the reconnect going
CheckIRCConnect();
return false;
}
CIRCNetwork* CUser::FindNetwork(const CString& sNetwork) {
for (vector<CIRCNetwork*>::iterator it = m_vIRCNetworks.begin(); it != m_vIRCNetworks.end(); ++it) {
CIRCNetwork *pNetwork = *it;
if (pNetwork->GetName().Equals(sNetwork)) {
return pNetwork;
}
}
return NULL;
}
const vector<CIRCNetwork*>& CUser::GetNetworks() const {
return m_vIRCNetworks;
}
CString CUser::ExpandString(const CString& sStr) const {
@@ -464,7 +518,7 @@ CString& CUser::ExpandString(const CString& sStr, CString& sRet) const {
sRet = sStr;
sRet.Replace("%user%", GetUserName());
sRet.Replace("%defnick%", GetNick());
sRet.Replace("%nick%", GetCurNick());
sRet.Replace("%nick%", GetNick());
sRet.Replace("%altnick%", GetAltNick());
sRet.Replace("%ident%", GetIdent());
sRet.Replace("%realname%", GetRealName());
@@ -526,65 +580,9 @@ void CUser::UserConnected(CClient* pClient) {
BounceAllClients();
}
pClient->PutClient(":irc.znc.in 001 " + pClient->GetNick() + " :- Welcome to ZNC -");
m_vClients.push_back(pClient);
if (m_RawBuffer.IsEmpty()) {
pClient->PutClient(":irc.znc.in 001 " + pClient->GetNick() + " :- Welcome to ZNC -");
} else {
unsigned int uIdx = 0;
CString sLine;
while (m_RawBuffer.GetLine(GetIRCNick().GetNick(), sLine, uIdx++)) {
pClient->PutClient(sLine);
}
// The assumption is that the client got this nick from the 001 reply
pClient->SetNick(GetIRCNick().GetNick());
}
// Send the cached MOTD
unsigned int uIdx = 0;
CString sLine;
while (m_MotdBuffer.GetLine(GetIRCNick().GetNick(), sLine, uIdx++)) {
pClient->PutClient(sLine);
}
if (GetIRCSock() != NULL) {
CString sUserMode("");
const set<unsigned char>& scUserModes = GetIRCSock()->GetUserModes();
for (set<unsigned char>::const_iterator it = scUserModes.begin();
it != scUserModes.end(); ++it) {
sUserMode += *it;
}
if (!sUserMode.empty()) {
pClient->PutClient(":" + GetIRCNick().GetNickMask() + " MODE " + GetIRCNick().GetNick() + " :+" + sUserMode);
}
}
if (m_bIRCAway) {
// If they want to know their away reason they'll have to whois
// themselves. At least we can tell them their away status...
pClient->PutClient(":irc.znc.in 306 " + GetIRCNick().GetNick() + " :You have been marked as being away");
}
const vector<CChan*>& vChans = GetChans();
for (unsigned int a = 0; a < vChans.size(); a++) {
if ((vChans[a]->IsOn()) && (!vChans[a]->IsDetached())) {
vChans[a]->JoinUser(true, "", pClient);
}
}
CString sBufLine;
while (m_QueryBuffer.GetNextLine(GetIRCNick().GetNick(), sBufLine)) {
MODULECALL(OnPrivBufferPlayLine(*pClient, sBufLine), this, NULL, continue);
pClient->PutClient(sBufLine);
}
// Tell them why they won't connect
if (!GetIRCConnectEnabled())
pClient->PutStatus("You are currently disconnected from IRC. "
"Use 'connect' to reconnect.");
}
void CUser::UserDisconnected(CClient* pClient) {
@@ -647,65 +645,12 @@ bool CUser::Clone(const CUser& User, CString& sErrorRet, bool bCloneChans) {
// !Allowed Hosts
// Servers
const vector<CServer*>& vServers = User.GetServers();
CString sServer;
CServer* pCurServ = GetCurrentServer();
if (pCurServ) {
sServer = pCurServ->GetName();
// Networks
const vector<CIRCNetwork*>& vNetworks = User.GetNetworks();
for (a = 0; a < vNetworks.size(); a++) {
new CIRCNetwork(this, vNetworks[a], bCloneChans);
}
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
// !Networks
// CTCP Replies
m_mssCTCPReplies.clear();
@@ -739,9 +684,9 @@ bool CUser::Clone(const CUser& User, CString& sErrorRet, bool bCloneChans) {
CModule* pCurMod = vCurMods.FindModule(pNewMod->GetModName());
if (!pCurMod) {
vCurMods.LoadModule(pNewMod->GetModName(), pNewMod->GetArgs(), CModInfo::UserModule, this, sModRet);
vCurMods.LoadModule(pNewMod->GetModName(), pNewMod->GetArgs(), CModInfo::UserModule, this, NULL, sModRet);
} else if (pNewMod->GetArgs() != pCurMod->GetArgs()) {
vCurMods.ReloadModule(pNewMod->GetModName(), pNewMod->GetArgs(), this, sModRet);
vCurMods.ReloadModule(pNewMod->GetModName(), pNewMod->GetArgs(), this, NULL, sModRet);
}
}
@@ -834,44 +779,6 @@ bool CUser::IsValid(CString& sErrMsg, bool bSkipPass) const {
return true;
}
bool CUser::AddChan(CChan* pChan) {
if (!pChan) {
return false;
}
for (unsigned int a = 0; a < m_vChans.size(); a++) {
if (m_vChans[a]->GetName().Equals(pChan->GetName())) {
delete pChan;
return false;
}
}
m_vChans.push_back(pChan);
return true;
}
bool CUser::AddChan(const CString& sName, bool bInConfig) {
if (sName.empty() || FindChan(sName)) {
return false;
}
CChan* pChan = new CChan(sName, this, bInConfig);
m_vChans.push_back(pChan);
return true;
}
bool CUser::DelChan(const CString& sName) {
for (vector<CChan*>::iterator a = m_vChans.begin(); a != m_vChans.end(); ++a) {
if (sName.Equals((*a)->GetName())) {
delete *a;
m_vChans.erase(a);
return true;
}
}
return false;
}
CConfig CUser::ToConfig() {
CConfig config;
CConfig passConfig;
@@ -947,276 +854,15 @@ CConfig CUser::ToConfig() {
}
}
// Servers
for (unsigned int b = 0; b < m_vServers.size(); b++) {
config.AddKeyValuePair("Server", m_vServers[b]->GetString());
}
// Chans
for (unsigned int c = 0; c < m_vChans.size(); c++) {
CChan* pChan = m_vChans[c];
if (pChan->InConfig()) {
config.AddSubConfig("Chan", pChan->GetName(), pChan->ToConfig());
}
// Networks
for (unsigned int d = 0; d < m_vIRCNetworks.size(); d++) {
CIRCNetwork *pNetwork = m_vIRCNetworks[d];
config.AddSubConfig("Network", pNetwork->GetName(), pNetwork->ToConfig());
}
return config;
}
CChan* CUser::FindChan(const CString& sName) const {
for (unsigned int a = 0; a < m_vChans.size(); a++) {
CChan* pChan = m_vChans[a];
if (sName.Equals(pChan->GetName())) {
return pChan;
}
}
return NULL;
}
void CUser::JoinChans() {
// Avoid divsion by zero, it's bad!
if (m_vChans.empty())
return;
// We start at a random offset into the channel list so that if your
// first 3 channels are invite-only and you got MaxJoins == 3, ZNC will
// still be able to join the rest of your channels.
unsigned int start = rand() % m_vChans.size();
unsigned int uJoins = m_uMaxJoins;
set<CChan*> sChans;
for (unsigned int a = 0; a < m_vChans.size(); a++) {
unsigned int idx = (start + a) % m_vChans.size();
CChan* pChan = m_vChans[idx];
if (!pChan->IsOn() && !pChan->IsDisabled()) {
if (!JoinChan(pChan))
continue;
sChans.insert(pChan);
// Limit the number of joins
if (uJoins != 0 && --uJoins == 0)
break;
}
}
while (!sChans.empty())
JoinChans(sChans);
}
void CUser::JoinChans(set<CChan*>& sChans) {
CString sKeys, sJoin;
bool bHaveKey = false;
size_t uiJoinLength = strlen("JOIN ");
while (!sChans.empty()) {
set<CChan*>::iterator it = sChans.begin();
const CString& sName = (*it)->GetName();
const CString& sKey = (*it)->GetKey();
size_t len = sName.length() + sKey.length();
len += 2; // two comma
if (!sKeys.empty() && uiJoinLength + len >= 512)
break;
if (!sJoin.empty()) {
sJoin += ",";
sKeys += ",";
}
uiJoinLength += len;
sJoin += sName;
if (!sKey.empty()) {
sKeys += sKey;
bHaveKey = true;
}
sChans.erase(it);
}
if (bHaveKey)
PutIRC("JOIN " + sJoin + " " + sKeys);
else
PutIRC("JOIN " + sJoin);
}
bool CUser::JoinChan(CChan* pChan) {
if (JoinTries() != 0 && pChan->GetJoinTries() >= JoinTries()) {
PutStatus("The channel " + pChan->GetName() + " could not be joined, disabling it.");
pChan->Disable();
} else {
pChan->IncJoinTries();
MODULECALL(OnTimerAutoJoin(*pChan), this, NULL, return false);
return true;
}
return false;
}
CServer* CUser::FindServer(const CString& sName) const {
for (unsigned int a = 0; a < m_vServers.size(); a++) {
CServer* pServer = m_vServers[a];
if (sName.Equals(pServer->GetName())) {
return pServer;
}
}
return NULL;
}
bool CUser::DelServer(const CString& sName, unsigned short uPort, const CString& sPass) {
if (sName.empty()) {
return false;
}
unsigned int a = 0;
bool bSawCurrentServer = false;
CServer* pCurServer = GetCurrentServer();
for (vector<CServer*>::iterator it = m_vServers.begin(); it != m_vServers.end(); it++, a++) {
CServer* pServer = *it;
if (pServer == pCurServer)
bSawCurrentServer = true;
if (!pServer->GetName().Equals(sName))
continue;
if (uPort != 0 && pServer->GetPort() != uPort)
continue;
if (!sPass.empty() && pServer->GetPass() != sPass)
continue;
m_vServers.erase(it);
if (pServer == pCurServer) {
CIRCSock* pIRCSock = GetIRCSock();
// Make sure we don't skip the next server in the list!
if (m_uServerIdx) {
m_uServerIdx--;
}
if (pIRCSock) {
pIRCSock->Quit();
PutStatus("Your current server was removed, jumping...");
}
} else if (!bSawCurrentServer) {
// Our current server comes after the server which we
// are removing. This means that it now got a different
// index in m_vServers!
m_uServerIdx--;
}
delete pServer;
return true;
}
return false;
}
bool CUser::AddServer(const CString& sName) {
if (sName.empty()) {
return false;
}
bool bSSL = false;
CString sLine = sName;
sLine.Trim();
CString sHost = sLine.Token(0);
CString sPort = sLine.Token(1);
if (sPort.Left(1) == "+") {
bSSL = true;
sPort.LeftChomp();
}
unsigned short uPort = sPort.ToUShort();
CString sPass = sLine.Token(2, true);
return AddServer(sHost, uPort, sPass, bSSL);
}
bool CUser::AddServer(const CString& sName, unsigned short uPort, const CString& sPass, bool bSSL) {
#ifndef HAVE_LIBSSL
if (bSSL) {
return false;
}
#endif
if (sName.empty()) {
return false;
}
if (!uPort) {
uPort = 6667;
}
// Check if server is already added
for (unsigned int a = 0; a < m_vServers.size(); a++) {
CServer* pServer = m_vServers[a];
if (!sName.Equals(pServer->GetName()))
continue;
if (uPort != pServer->GetPort())
continue;
if (sPass != pServer->GetPass())
continue;
if (bSSL != pServer->IsSSL())
continue;
// Server is already added
return false;
}
CServer* pServer = new CServer(sName, uPort, sPass, bSSL);
m_vServers.push_back(pServer);
CheckIRCConnect();
return true;
}
bool CUser::IsLastServer() const {
return (m_uServerIdx >= m_vServers.size());
}
CServer* CUser::GetNextServer() {
if (m_vServers.empty()) {
return NULL;
}
if (m_uServerIdx >= m_vServers.size()) {
m_uServerIdx = 0;
}
return m_vServers[m_uServerIdx++];
}
CServer* CUser::GetCurrentServer() const {
unsigned int uIdx = (m_uServerIdx) ? m_uServerIdx -1 : 0;
if (uIdx >= m_vServers.size()) {
return NULL;
}
return m_vServers[uIdx];
}
bool CUser::SetNextServer(const CServer* pServer) {
for (unsigned int a = 0; a < m_vServers.size(); a++) {
if (m_vServers[a] == pServer) {
m_uServerIdx = a;
return true;
}
}
return false;
}
bool CUser::CheckPass(const CString& sPass) const {
switch (m_eHashType)
{
@@ -1247,35 +893,23 @@ bool CUser::CheckPass(const CString& sPass) const {
return (CClient*) CZNC::Get().GetManager().FindSockByName(sSockName);
}*/
CString CUser::GetLocalIP() {
CIRCSock* pIRCSock = GetIRCSock();
if (pIRCSock) {
return pIRCSock->GetLocalIP();
}
if (!m_vClients.empty()) {
return m_vClients[0]->GetLocalIP();
}
return "";
}
CString CUser::GetLocalDCCIP() {
if (!GetDCCBindHost().empty())
return GetDCCBindHost();
return GetLocalIP();
}
bool CUser::PutIRC(const CString& sLine) {
CIRCSock* pIRCSock = GetIRCSock();
if (!pIRCSock) {
return false;
for (vector<CIRCNetwork*>::iterator it = m_vIRCNetworks.begin(); it != m_vIRCNetworks.end(); ++it) {
CIRCNetwork *pNetwork = *it;
CIRCSock* pIRCSock = pNetwork->GetIRCSock();
if (pIRCSock) {
return pIRCSock->GetLocalIP();
}
}
pIRCSock->PutIRC(sLine);
return true;
if (!GetAllClients().empty()) {
return GetAllClients()[0]->GetLocalIP();
}
return "";
}
bool CUser::PutUser(const CString& sLine, CClient* pClient, CClient* pSkipClient) {
@@ -1292,6 +926,19 @@ bool CUser::PutUser(const CString& sLine, CClient* pClient, CClient* pSkipClient
return (pClient == NULL);
}
bool CUser::PutAllUser(const CString& sLine, CClient* pClient, CClient* pSkipClient) {
PutUser(sLine, pClient, pSkipClient);
for (vector<CIRCNetwork*>::iterator it = m_vIRCNetworks.begin(); it != m_vIRCNetworks.end(); ++it) {
CIRCNetwork* pNetwork = *it;
if (pNetwork->PutUser(sLine, pClient, pSkipClient)) {
return true;
}
}
return (pClient == NULL);
}
bool CUser::PutStatus(const CString& sLine, CClient* pClient, CClient* pSkipClient) {
for (unsigned int a = 0; a < m_vClients.size(); a++) {
if ((!pClient || pClient == m_vClients[a]) && pSkipClient != m_vClients[a]) {
@@ -1348,34 +995,11 @@ bool CUser::PutModNotice(const CString& sModule, const CString& sLine, CClient*
return (pClient == NULL);
}
CString CUser::GetCurNick() const {
const CIRCSock* pIRCSock = GetIRCSock();
if (pIRCSock) {
return pIRCSock->GetNick();
}
if (!m_vClients.empty()) {
return m_vClients[0]->GetNick();
}
return "";
}
CString CUser::MakeCleanUserName(const CString& sUserName) {
return sUserName.Token(0, false, "@").Replace_n(".", "");
}
// Setters
bool CUser::IsChan(const CString& sChan) const {
if (sChan.empty())
return false; // There is no way this is a chan
if (GetChanPrefixes().empty())
return true; // We can't know, so we allow everything
// Thanks to the above if (empty), we can do sChan[0]
return GetChanPrefixes().find(sChan[0]) != CString::npos;
}
void CUser::SetNick(const CString& s) { m_sNick = s; }
void CUser::SetAltNick(const CString& s) { m_sAltNick = s; }
void CUser::SetIdent(const CString& s) { m_sIdent = s; }
@@ -1392,7 +1016,6 @@ void CUser::SetDenyLoadMod(bool b) { m_bDenyLoadMod = b; }
void CUser::SetAdmin(bool b) { m_bAdmin = b; }
void CUser::SetDenySetBindHost(bool b) { m_bDenySetBindHost = b; }
void CUser::SetDefaultChanModes(const CString& s) { m_sDefaultChanModes = s; }
void CUser::SetIRCServer(const CString& s) { m_sIRCServer = s; }
void CUser::SetQuitMsg(const CString& s) { m_sQuitMsg = s; }
void CUser::SetKeepBuffer(bool b) { m_bKeepBuffer = b; }
@@ -1403,20 +1026,6 @@ bool CUser::SetBufferCount(unsigned int u, bool bForce) {
return true;
}
void CUser::CheckIRCConnect() {
// Do we want to connect?
if (m_bIRCConnectEnabled && GetIRCSock() == NULL)
CZNC::Get().EnableConnectUser();
}
void CUser::SetIRCNick(const CNick& n) {
m_IRCNick = n;
for (unsigned int a = 0; a < m_vClients.size(); a++) {
m_vClients[a]->SetNick(n.GetNick());
}
}
bool CUser::AddCTCPReply(const CString& sCTCP, const CString& sReply) {
// Reject CTCP requests containing spaces
if (sCTCP.find_first_of(' ') != CString::npos) {
@@ -1445,6 +1054,22 @@ bool CUser::SetStatusPrefix(const CString& s) {
// !Setters
// Getters
vector<CClient*> CUser::GetAllClients() {
vector<CClient*> vClients;
for (unsigned int a = 0; a < m_vIRCNetworks.size(); a++) {
for (unsigned int b = 0; b < m_vIRCNetworks[a]->GetClients().size(); b++) {
vClients.push_back(m_vIRCNetworks[a]->GetClients()[b]);
}
}
for (unsigned int a = 0; a < m_vClients.size(); a++) {
vClients.push_back(m_vClients[a]);
}
return vClients;
}
const CString& CUser::GetUserName() const { return m_sUserName; }
const CString& CUser::GetCleanUserName() const { return m_sCleanUserName; }
const CString& CUser::GetNick(bool bAllowDefault) const { return (bAllowDefault && m_sNick.empty()) ? GetCleanUserName() : m_sNick; }
@@ -1456,17 +1081,14 @@ const CString& CUser::GetDCCBindHost() const { return m_sDCCBindHost; }
const CString& CUser::GetPass() const { return m_sPass; }
CUser::eHashType CUser::GetPassHashType() const { return m_eHashType; }
const CString& CUser::GetPassSalt() const { return m_sPassSalt; }
bool CUser::DenyLoadMod() const { return m_bDenyLoadMod; }
bool CUser::IsAdmin() const { return m_bAdmin; }
bool CUser::DenySetBindHost() const { return m_bDenySetBindHost; }
bool CUser::MultiClients() const { return m_bMultiClients; }
const CString& CUser::GetStatusPrefix() const { return m_sStatusPrefix; }
const CString& CUser::GetDefaultChanModes() const { return m_sDefaultChanModes; }
const vector<CChan*>& CUser::GetChans() const { return m_vChans; }
const vector<CServer*>& CUser::GetServers() const { return m_vServers; }
const CNick& CUser::GetIRCNick() const { return m_IRCNick; }
const CString& CUser::GetIRCServer() const { return m_sIRCServer; }
CString CUser::GetQuitMsg() const { return (!m_sQuitMsg.Trim_n().empty()) ? m_sQuitMsg : CZNC::GetTag(false); }
const MCString& CUser::GetCTCPReplies() const { return m_mssCTCPReplies; }
unsigned int CUser::GetBufferCount() const { return m_uBufferCount; }
+17 -68
View File
@@ -23,6 +23,7 @@ class CChan;
class CClient;
class CConfig;
class CFile;
class CIRCNetwork;
class CIRCSock;
class CUserTimer;
class CServer;
@@ -49,28 +50,15 @@ public:
}
CConfig ToConfig();
CChan* FindChan(const CString& sName) const;
bool AddChan(CChan* pChan);
bool AddChan(const CString& sName, bool bInConfig);
bool DelChan(const CString& sName);
void JoinChans();
CServer* FindServer(const CString& sName) const;
bool DelServer(const CString& sName, unsigned short uPort, const CString& sPass);
bool AddServer(const CString& sName);
bool AddServer(const CString& sName, unsigned short uPort, const CString& sPass = "", bool bSSL = false);
CServer* GetNextServer();
CServer* GetCurrentServer() const;
bool SetNextServer(const CServer* pServer);
bool CheckPass(const CString& sPass) const;
bool AddAllowedHost(const CString& sHostMask);
bool IsHostAllowed(const CString& sHostMask) const;
bool IsValid(CString& sErrMsg, bool bSkipPass = false) const;
static bool IsValidUserName(const CString& sUserName);
static CString MakeCleanUserName(const CString& sUserName);
bool IsLastServer() const;
void DelNetworks();
void DelClients();
void DelServers();
void DelModules();
// Unloads a module on all users who have it loaded and loads it again.
@@ -81,23 +69,17 @@ public:
const CModules& GetModules() const { return *m_pModules; }
// !Modules
// Buffers
void AddRawBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_RawBuffer.AddLine(sPre, sPost, bIncNick); }
void UpdateRawBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_RawBuffer.UpdateLine(sPre, sPost, bIncNick); }
void UpdateExactRawBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_RawBuffer.UpdateExactLine(sPre, sPost, bIncNick); }
void ClearRawBuffer() { m_RawBuffer.Clear(); }
// Networks
CIRCNetwork* AddNetwork(const CString &sNetwork);
bool DeleteNetwork(CString sNetwork);
bool AddNetwork(CIRCNetwork *pNetwork);
void RemoveNetwork(CIRCNetwork *pNetwork);
CIRCNetwork* FindNetwork(const CString& sNetwork);
const vector<CIRCNetwork*>& GetNetworks() const;
// !Networks
void AddMotdBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_MotdBuffer.AddLine(sPre, sPost, bIncNick); }
void UpdateMotdBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_MotdBuffer.UpdateLine(sPre, sPost, bIncNick); }
void ClearMotdBuffer() { m_MotdBuffer.Clear(); }
void AddQueryBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_QueryBuffer.AddLine(sPre, sPost, bIncNick); }
void UpdateQueryBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_QueryBuffer.UpdateLine(sPre, sPost, bIncNick); }
void ClearQueryBuffer() { m_QueryBuffer.Clear(); }
// !Buffers
bool PutIRC(const CString& sLine);
bool PutUser(const CString& sLine, CClient* pClient = NULL, CClient* pSkipClient = NULL);
bool PutAllUser(const CString& sLine, CClient* pClient = NULL, CClient* pSkipClient = NULL);
bool PutStatus(const CString& sLine, CClient* pClient = NULL, CClient* pSkipClient = NULL);
bool PutStatusNotice(const CString& sLine, CClient* pClient = NULL, CClient* pSkipClient = NULL);
bool PutModule(const CString& sModule, const CString& sLine, CClient* pClient = NULL, CClient* pSkipClient = NULL);
@@ -107,23 +89,14 @@ public:
void UserConnected(CClient* pClient);
void UserDisconnected(CClient* pClient);
CString GetLocalIP();
CString GetLocalDCCIP();
/** This method will return whether the user is connected and authenticated to an IRC server.
*/
bool IsIRCConnected() const;
void SetIRCSocket(CIRCSock* pIRCSock);
void IRCDisconnected();
void CheckIRCConnect();
CString ExpandString(const CString& sStr) const;
CString& ExpandString(const CString& sStr, CString& sRet) const;
CString AddTimestamp(const CString& sStr) const;
CString& AddTimestamp(const CString& sStr, CString& sRet) const;
CString GetCurNick() const;
bool Clone(const CUser& User, CString& sErrorRet, bool bCloneChans = true);
void BounceAllClients();
@@ -144,14 +117,12 @@ public:
void SetDenySetBindHost(bool b);
bool SetStatusPrefix(const CString& s);
void SetDefaultChanModes(const CString& s);
void SetIRCNick(const CNick& n);
void SetIRCServer(const CString& s);
void SetQuitMsg(const CString& s);
bool AddCTCPReply(const CString& sCTCP, const CString& sReply);
bool DelCTCPReply(const CString& sCTCP);
bool SetBufferCount(unsigned int u, bool bForce = false);
void SetKeepBuffer(bool b);
void SetChanPrefixes(const CString& s) { m_sChanPrefixes = s; }
void SetBeingDeleted(bool b) { m_bBeingDeleted = b; }
void SetTimestampFormat(const CString& s) { m_sTimestampFormat = s; }
void SetTimestampAppend(bool b) { m_bAppendTimestamp = b; }
@@ -161,13 +132,11 @@ public:
void SetMaxJoins(unsigned int i) { m_uMaxJoins = i; }
void SetSkinName(const CString& s) { m_sSkinName = s; }
void SetIRCConnectEnabled(bool b) { m_bIRCConnectEnabled = b; }
void SetIRCAway(bool b) { m_bIRCAway = b; }
// !Setters
// Getters
vector<CClient*>& GetClients() { return m_vClients; }
CIRCSock* GetIRCSock() { return m_pIRCSock; }
const CIRCSock* GetIRCSock() const { return m_pIRCSock; }
vector<CClient*>& GetUserClients() { return m_vClients; }
vector<CClient*> GetAllClients();
const CString& GetUserName() const;
const CString& GetCleanUserName() const;
const CString& GetNick(bool bAllowDefault = true) const;
@@ -185,9 +154,6 @@ public:
bool GetTimestampPrepend() const;
bool GetIRCConnectEnabled() const { return m_bIRCConnectEnabled; }
const CString& GetChanPrefixes() const { return m_sChanPrefixes; }
bool IsChan(const CString& sChan) const;
const CString& GetUserPath() const;
bool DenyLoadMod() const;
@@ -196,27 +162,19 @@ public:
bool MultiClients() const;
const CString& GetStatusPrefix() const;
const CString& GetDefaultChanModes() const;
const vector<CChan*>& GetChans() const;
const vector<CServer*>& GetServers() const;
const CNick& GetIRCNick() const;
const CString& GetIRCServer() const;
CString GetQuitMsg() const;
const MCString& GetCTCPReplies() const;
unsigned int GetBufferCount() const;
bool KeepBuffer() const;
bool IsBeingDeleted() const { return m_bBeingDeleted; }
bool HasServers() const { return !m_vServers.empty(); }
float GetTimezoneOffset() const { return m_fTimezoneOffset; }
unsigned long long BytesRead() const { return m_uBytesRead; }
unsigned long long BytesWritten() const { return m_uBytesWritten; }
unsigned int JoinTries() const { return m_uMaxJoinTries; }
unsigned int MaxJoins() const { return m_uMaxJoins; }
bool IsIRCAway() const { return m_bIRCAway; }
CString GetSkinName() const;
// !Getters
private:
bool JoinChan(CChan* pChan);
void JoinChans(set<CChan*>& sChans);
protected:
const CString m_sUserName;
@@ -231,10 +189,7 @@ protected:
CString m_sPassSalt;
CString m_sStatusPrefix;
CString m_sDefaultChanModes;
CString m_sChanPrefixes;
CNick m_IRCNick;
bool m_bIRCAway;
CString m_sIRCServer;
CString m_sQuitMsg;
MCString m_mssCTCPReplies;
CString m_sTimestampFormat;
@@ -245,9 +200,6 @@ protected:
CString m_sUserPath;
// !Paths
CBuffer m_RawBuffer;
CBuffer m_MotdBuffer;
CBuffer m_QueryBuffer;
bool m_bMultiClients;
bool m_bDenyLoadMod;
bool m_bAdmin;
@@ -257,15 +209,12 @@ protected:
bool m_bAppendTimestamp;
bool m_bPrependTimestamp;
bool m_bIRCConnectEnabled;
CIRCSock* m_pIRCSock;
CUserTimer* m_pUserTimer;
vector<CServer*> m_vServers;
vector<CChan*> m_vChans;
vector<CIRCNetwork*> m_vIRCNetworks;
vector<CClient*> m_vClients;
set<CString> m_ssAllowedHosts;
unsigned int m_uServerIdx; ///< Index in m_vServers of our current server + 1
unsigned int m_uBufferCount;
unsigned long long m_uBytesRead;
unsigned long long m_uBytesWritten;
+39 -26
View File
@@ -12,6 +12,7 @@
#include "IRCSock.h"
#include "Server.h"
#include "User.h"
#include "IRCNetwork.h"
#include "Listener.h"
#include "Config.h"
#include <list>
@@ -102,17 +103,18 @@ bool CZNC::OnBoot() {
return true;
}
bool CZNC::ConnectUser(CUser *pUser) {
CString sSockName = "IRC::" + pUser->GetUserName();
CIRCSock* pIRCSock = pUser->GetIRCSock();
bool CZNC::ConnectNetwork(CIRCNetwork *pNetwork) {
CUser *pUser = pNetwork->GetUser();
CString sSockName = "IRC::" + pUser->GetUserName() + "::" + pNetwork->GetName();
CIRCSock* pIRCSock = pNetwork->GetIRCSock();
if (!pUser->GetIRCConnectEnabled())
return false;
if (pIRCSock || !pUser->HasServers())
if (pIRCSock || !pNetwork->HasServers())
return false;
CServer* pServer = pUser->GetNextServer();
CServer* pServer = pNetwork->GetNextServer();
if (!pServer)
return false;
@@ -122,10 +124,10 @@ bool CZNC::ConnectUser(CUser *pUser) {
m_sConnectThrottle.AddItem(pServer->GetName());
DEBUG("User [" << pUser->GetUserName() << "] is connecting to [" << pServer->GetString(false) << "] ...");
pUser->PutStatus("Attempting to connect to [" + pServer->GetString(false) + "] ...");
DEBUG("User [" << pUser->GetUserName() << "] is connecting to [" << pServer->GetString(false) << "] on network [" << pNetwork->GetName() << "]");
pNetwork->PutStatus("Attempting to connect to [" + pServer->GetString(false) + "] ...");
pIRCSock = new CIRCSock(pUser);
pIRCSock = new CIRCSock(pNetwork);
pIRCSock->SetPass(pServer->GetPass());
bool bSSL = false;
@@ -135,7 +137,7 @@ bool CZNC::ConnectUser(CUser *pUser) {
}
#endif
MODULECALL(OnIRCConnecting(pIRCSock), pUser, NULL,
MODULECALL(OnIRCConnecting(pIRCSock), pUser, pNetwork, NULL,
DEBUG("Some module aborted the connection attempt");
pUser->PutStatus("Some module aborted the connection attempt");
delete pIRCSock;
@@ -143,7 +145,7 @@ bool CZNC::ConnectUser(CUser *pUser) {
);
if (!m_Manager.Connect(pServer->GetName(), pServer->GetPort(), sSockName, 120, bSSL, pUser->GetBindHost(), pIRCSock)) {
pUser->PutStatus("Unable to connect. (Bad host?)");
pNetwork->PutStatus("Unable to connect. (Bad host?)");
}
return true;
@@ -168,12 +170,17 @@ bool CZNC::HandleUserDeletion()
}
m_msUsers.erase(pUser->GetUserName());
CIRCSock* pIRCSock = pUser->GetIRCSock();
vector<CIRCNetwork*> vNetworks;
for (vector<CIRCNetwork*>::iterator it2 = vNetworks.begin(); it2 != vNetworks.end(); ++it2) {
CIRCNetwork *pNetwork = *it2;
CIRCSock* pIRCSock = pNetwork->GetIRCSock();
if (pIRCSock) {
m_Manager.DelSockByAddr(pIRCSock);
if (pIRCSock) {
m_Manager.DelSockByAddr(pIRCSock);
}
}
pUser->DelNetworks();
pUser->DelClients();
pUser->DelModules();
CWebSock::FinishUserSessions(*pUser);
@@ -1739,26 +1746,32 @@ protected:
it++;
m_uiPosNextUser = (m_uiPosNextUser + 1) % uiUserCount;
// Is this user disconnected?
if (pUser->GetIRCSock() != NULL)
continue;
// Does this user want to connect?
if (!pUser->GetIRCConnectEnabled())
continue;
// Does this user have any servers?
if (!pUser->HasServers())
continue;
vector<CIRCNetwork*> vNetworks = pUser->GetNetworks();
for (vector<CIRCNetwork*>::iterator it2 = vNetworks.begin(); it2 != vNetworks.end(); ++it2) {
CIRCNetwork* pNetwork = *it2;
// The timer runs until it once didn't find any users to connect
bUsersLeft = true;
// Is this network disconnected?
if (pNetwork->GetIRCSock() != NULL)
continue;
DEBUG("Connecting user [" << pUser->GetUserName() << "]");
// Does this user have any servers?
if (!pNetwork->HasServers())
continue;
if (CZNC::Get().ConnectUser(pUser))
// User connecting, wait until next time timer fires
return;
// The timer runs until it once didn't find any users to connect
bUsersLeft = true;
DEBUG("Connecting user [" << pUser->GetUserName() << "/" << pNetwork->GetName() << "]");
if (CZNC::Get().ConnectNetwork(pNetwork)) {
// User connecting, wait until next time timer fires
return;
}
}
}
if (bUsersLeft == false) {
+2 -1
View File
@@ -20,6 +20,7 @@ using std::map;
class CListener;
class CUser;
class CIRCNetwork;
class CConnectUserTimer;
class CConfig;
class CFile;
@@ -138,7 +139,7 @@ public:
// !MOTD
// Create a CIRCSocket. Return false if user cant connect
bool ConnectUser(CUser *pUser);
bool ConnectNetwork(CIRCNetwork *pNetwork);
// This creates a CConnectUserTimer if we haven't got one yet
void EnableConnectUser();
void DisableConnectUser();