mirror of
https://github.com/znc/znc.git
synced 2026-08-06 00:43:19 +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:
@@ -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; }
|
||||
|
||||
Reference in New Issue
Block a user