mirror of
https://github.com/znc/znc.git
synced 2026-08-07 01:13:25 +02:00
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:
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user