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
+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; }