Added preliminary support for multiple clients per user

git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@547 726aef4b-f618-498e-8847-2d620e286838
This commit is contained in:
prozacx
2005-10-09 08:40:40 +00:00
parent a26fdbdf91
commit aaec84a317
12 changed files with 283 additions and 230 deletions
+10 -13
View File
@@ -64,7 +64,7 @@ void CChan::Cycle() const {
m_pUser->PutIRC("PART " + GetName() + "\r\nJOIN " + GetName() + " " + GetKey());
}
void CChan::JoinUser(bool bForce, const CString& sKey) {
void CChan::JoinUser(bool bForce, const CString& sKey, CUserSock* pUserSock) {
if (!bForce && (!IsOn() || !IsDetached())) {
IncClientRequests();
@@ -72,11 +72,11 @@ void CChan::JoinUser(bool bForce, const CString& sKey) {
return;
}
m_pUser->PutUser(":" + m_pUser->GetIRCNick().GetNickMask() + " JOIN :" + GetName());
m_pUser->PutUser(":" + m_pUser->GetIRCNick().GetNickMask() + " JOIN :" + GetName(), pUserSock);
if (!GetTopic().empty()) {
m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 332 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " :" + GetTopic());
m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 333 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " " + GetTopicOwner() + " " + CString::ToString(GetTopicDate()));
m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 332 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " :" + GetTopic(), pUserSock);
m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 333 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " " + GetTopicOwner() + " " + CString::ToString(GetTopicDate()), pUserSock);
}
CString sPre = ":" + m_pUser->GetIRCServer() + " 353 " + m_pUser->GetIRCNick().GetNick() + " = " + GetName() + " :";
@@ -91,35 +91,32 @@ void CChan::JoinUser(bool bForce, const CString& sKey) {
sLine += a->first;
if (sLine.size() >= 490 || a == (--m_msNicks.end())) {
m_pUser->PutUser(sLine);
m_pUser->PutUser(sLine, pUserSock);
sLine = sPre;
} else {
sLine += " ";
}
}
m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 366 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " :End of /NAMES list.");
SendBuffer();
m_pUser->PutUser(":" + m_pUser->GetIRCServer() + " 366 " + m_pUser->GetIRCNick().GetNick() + " " + GetName() + " :End of /NAMES list.", pUserSock);
m_bDetached = false;
}
void CChan::SendBuffer() {
// Send Buffer
if (m_pUser->IsUserAttached()) {
const vector<CString>& vsBuffer = GetBuffer();
if (vsBuffer.size()) {
m_pUser->PutUser(":***!znc@znc.com PRIVMSG " + GetName() + " :Buffer Playback...");
m_pUser->PutUser(":***!znc@znc.com PRIVMSG " + GetName() + " :Buffer Playback...", pUserSock);
for (unsigned int a = 0; a < vsBuffer.size(); a++) {
m_pUser->PutUser(vsBuffer[a]);
m_pUser->PutUser(vsBuffer[a], pUserSock);
}
if (!KeepBuffer()) {
ClearBuffer();
}
m_pUser->PutUser(":***!znc@znc.com PRIVMSG " + GetName() + " :Playback Complete.");
m_pUser->PutUser(":***!znc@znc.com PRIVMSG " + GetName() + " :Playback Complete.", pUserSock);
}
}
}
+2 -2
View File
@@ -5,6 +5,7 @@
#include "Nick.h"
#include "String.h"
#include "FileUtils.h"
#include "UserSock.h"
#include <vector>
#include <map>
#include <set>
@@ -48,10 +49,9 @@ public:
bool WriteConfig(CFile& File);
void Joined();
void Cycle() const;
void JoinUser(bool bForce = false, const CString& sKey = "");
void JoinUser(bool bForce = false, const CString& sKey = "", CUserSock* pUserSock = NULL);
void DetachUser();
void AttachUser();
void SendBuffer();
void IncClientRequests();
bool DecClientRequests();
+50 -124
View File
@@ -7,16 +7,12 @@
CIRCSock::CIRCSock(CUser* pUser) : Csock() {
m_pUser = pUser;
m_pUserSock = NULL;
m_pAwayNickTimer = NULL;
m_uQueryBufferCount = 50;
m_bISpoofReleased = false;
m_bKeepNick = true;
m_bAuthed = false;
m_bOrigNickPending = false;
EnableReadLine();
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_Nick.SetIdent(pUser->GetIdent());
m_Nick.SetHost(pUser->GetVHost());
@@ -41,10 +37,7 @@ CIRCSock::~CIRCSock() {
vChans[a]->Reset();
}
if (m_pUserSock) {
m_pUserSock->IRCDisconnected();
m_pUserSock = NULL;
}
m_pUser->IRCDisconnected();
for (map<CString, CChan*>::iterator a = m_msChans.begin(); a != m_msChans.end(); a++) {
delete a->second;
@@ -103,18 +96,22 @@ void CIRCSock::ReadLine(const CString& sData) {
m_bAuthed = true;
m_pUser->PutStatus("Connected!");
if (m_pUserSock) {
CString sClientNick = m_pUserSock->GetNick();
vector<CUserSock*>& vUserSocks = m_pUser->GetUserSocks();
for (unsigned int a = 0; a < vUserSocks.size(); a++) {
CUserSock* pUserSock = vUserSocks[a];
CString sClientNick = pUserSock->GetNick();
if (sClientNick.CaseCmp(sNick) != 0) {
// If they connected with a nick that doesn't match the one we got on irc, then we need to update them
PutUser(":" + sClientNick + "!" + m_Nick.GetIdent() + "@" + m_Nick.GetHost() + " NICK :" + sNick);
pUserSock->PutServ(":" + sClientNick + "!" + m_Nick.GetIdent() + "@" + m_Nick.GetHost() + " NICK :" + sNick);
}
}
SetNick(sNick);
m_RawBuffer.Clear();
m_RawBuffer.AddLine(":" + sServer + " " + sCmd + " ", " " + sRest);
m_pUser->ClearRawBuffer();
m_pUser->AddRawBuffer(":" + sServer + " " + sCmd + " ", " " + sRest);
// Now that we are connected, we need to join our chans
const vector<CChan*>& vChans = m_pUser->GetChans();
@@ -140,18 +137,18 @@ void CIRCSock::ReadLine(const CString& sData) {
case 255: // client count
case 265: // local users
case 266: // global users
m_RawBuffer.AddLine(":" + sServer + " " + sCmd + " ", " " + sRest);
m_pUser->AddRawBuffer(":" + sServer + " " + sCmd + " ", " " + sRest);
break;
case 375: // begin motd
m_MotdBuffer.Clear();
m_pUser->ClearMotdBuffer();
case 372: // motd
case 376: // end motd
m_MotdBuffer.AddLine(":" + sServer + " " + sCmd + " ", " " + sRest);
m_pUser->AddMotdBuffer(":" + sServer + " " + sCmd + " ", " " + sRest);
break;
case 471: // :irc.server.net 471 nick #chan :Cannot join channel (+l)
case 473: // :irc.server.net 473 nick #chan :Cannot join channel (+i)
case 475: // :irc.server.net 475 nick #chan :Cannot join channel (+k)
if (m_pUserSock) {
if (m_pUser->IsUserAttached()) {
CChan* pChan = m_pUser->FindChan(sRest.substr(0, sRest.find(' ')));
if ((pChan) && (!pChan->IsOn())) {
@@ -207,9 +204,15 @@ void CIRCSock::ReadLine(const CString& sData) {
// :irc.server.net 433 mynick badnick :Nickname is already in use.
if ((m_bKeepNick) && (m_pUser->GetKeepNick())) {
if (sBadNick.CaseCmp(sConfNick) == 0) {
if ((!m_pUserSock) || (!m_pUserSock->DecKeepNickCounter())) {
SetOrigNickPending(false);
return;
vector<CUserSock*>& vUserSocks = m_pUser->GetUserSocks();
for (unsigned int a = 0; a < vUserSocks.size(); a++) {
CUserSock* pUserSock = vUserSocks[a];
if (!pUserSock || !pUserSock->DecKeepNickCounter()) {
SetOrigNickPending(false);
return;
}
}
}
}
@@ -311,27 +314,27 @@ void CIRCSock::ReadLine(const CString& sData) {
}
break;
case 366: { // end of names list
PutUser(sLine); // First send them the raw
m_pUser->PutUser(sLine); // First send them the raw
// :irc.server.com 366 nick #chan :End of /NAMES list.
CChan* pChan = m_pUser->FindChan(sRest.Token(0));
if (pChan) {
if (IsUserAttached()) {
if (m_pUser->IsUserAttached()) {
const vector<CString>& vsBuffer = pChan->GetBuffer();
if (vsBuffer.size()) {
PutUser(":***!znc@znc.com PRIVMSG " + pChan->GetName() + " :Buffer Playback...");
m_pUser->PutUser(":***!znc@znc.com PRIVMSG " + pChan->GetName() + " :Buffer Playback...");
for (unsigned int a = 0; a < vsBuffer.size(); a++) {
PutUser(vsBuffer[a]);
m_pUser->PutUser(vsBuffer[a]);
}
if (!pChan->KeepBuffer()) {
pChan->ClearBuffer();
}
PutUser(":***!znc@znc.com PRIVMSG " + pChan->GetName() + " :Playback Complete.");
m_pUser->PutUser(":***!znc@znc.com PRIVMSG " + pChan->GetName() + " :Playback Complete.");
}
}
@@ -527,7 +530,7 @@ void CIRCSock::ReadLine(const CString& sData) {
}
}
PutUser(":" + Nick.GetNickMask() + " NOTICE " + sTarget + " :\001" + sMsg + "\001");
m_pUser->PutUser(":" + Nick.GetNickMask() + " NOTICE " + sTarget + " :\001" + sMsg + "\001");
return;
} else {
if (sTarget.CaseCmp(GetNick()) == 0) {
@@ -541,7 +544,7 @@ void CIRCSock::ReadLine(const CString& sData) {
}
}
PutUser(":" + Nick.GetNickMask() + " NOTICE " + sTarget + " :" + sMsg);
m_pUser->PutUser(":" + Nick.GetNickMask() + " NOTICE " + sTarget + " :" + sMsg);
return;
} else if (sCmd.CaseCmp("TOPIC") == 0) {
// :nick!ident@host.com TOPIC #chan :This is a topic
@@ -551,7 +554,7 @@ void CIRCSock::ReadLine(const CString& sData) {
CString sTopic = sLine.Token(3, true);
sTopic.LeftChomp();
pChan->SetTopicOwner(Nick.GetNick());
pChan->SetTopicDate((unsigned long) time(NULL)); // @todo use local time
pChan->SetTopicDate((unsigned long) time(NULL));
pChan->SetTopic(sTopic);
}
} else if (sCmd.CaseCmp("PRIVMSG") == 0) {
@@ -577,7 +580,7 @@ void CIRCSock::ReadLine(const CString& sData) {
}
}
PutUser(":" + Nick.GetNickMask() + " PRIVMSG " + sTarget + " :\001" + sMsg + "\001");
m_pUser->PutUser(":" + Nick.GetNickMask() + " PRIVMSG " + sTarget + " :\001" + sMsg + "\001");
return;
} else {
if (sTarget.CaseCmp(GetNick()) == 0) {
@@ -590,14 +593,14 @@ void CIRCSock::ReadLine(const CString& sData) {
}
}
PutUser(":" + Nick.GetNickMask() + " PRIVMSG " + sTarget + " :" + sMsg);
m_pUser->PutUser(":" + Nick.GetNickMask() + " PRIVMSG " + sTarget + " :" + sMsg);
return;
}
}
}
}
PutUser(sLine);
m_pUser->PutUser(sLine);
}
void CIRCSock::KeepNick(bool bForce) {
@@ -628,26 +631,26 @@ bool CIRCSock::OnPrivCTCP(CNick& Nick, CString& sMessage) {
unsigned long uFileSize = strtoul(sMessage.Token(5).c_str(), NULL, 10);
if (sType.CaseCmp("CHAT") == 0) {
if (m_pUserSock) {
if (m_pUser->IsUserAttached()) {
CNick FromNick(Nick.GetNickMask());
unsigned short uBNCPort = CDCCBounce::DCCRequest(FromNick.GetNick(), uLongIP, uPort, "", true, m_pUser, GetLocalIP(), CUtils::GetIP(uLongIP));
if (uBNCPort) {
PutUser(":" + Nick.GetNickMask() + " PRIVMSG " + GetNick() + " :\001DCC CHAT chat " + CString::ToString(CUtils::GetLongIP(GetLocalIP())) + " " + CString::ToString(uBNCPort) + "\001");
m_pUser->PutUser(":" + Nick.GetNickMask() + " PRIVMSG " + GetNick() + " :\001DCC CHAT chat " + CString::ToString(CUtils::GetLongIP(GetLocalIP())) + " " + CString::ToString(uBNCPort) + "\001");
}
}
} else if (sType.CaseCmp("SEND") == 0) {
// DCC SEND readme.txt 403120438 5550 1104
unsigned short uBNCPort = CDCCBounce::DCCRequest(Nick.GetNick(), uLongIP, uPort, sFile, false, m_pUser, GetLocalIP(), CUtils::GetIP(uLongIP));
if (uBNCPort) {
PutUser(":" + Nick.GetNickMask() + " PRIVMSG " + GetNick() + " :\001DCC SEND " + sFile + " " + CString::ToString(CUtils::GetLongIP(GetLocalIP())) + " " + CString::ToString(uBNCPort) + " " + CString::ToString(uFileSize) + "\001");
m_pUser->PutUser(":" + Nick.GetNickMask() + " PRIVMSG " + GetNick() + " :\001DCC SEND " + sFile + " " + CString::ToString(CUtils::GetLongIP(GetLocalIP())) + " " + CString::ToString(uBNCPort) + " " + CString::ToString(uFileSize) + "\001");
}
} else if (sType.CaseCmp("RESUME") == 0) {
// Need to lookup the connection by port, filter the port, and forward to the user
CDCCBounce* pSock = (CDCCBounce*) CZNC::Get().GetManager().FindSockByLocalPort(atoi(sMessage.Token(3).c_str()));
if ((pSock) && (strncasecmp(pSock->GetSockName().c_str(), "DCC::", 5) == 0)) {
PutUser(":" + Nick.GetNickMask() + " PRIVMSG " + GetNick() + " :\001DCC " + sType + " " + sFile + " " + CString::ToString(pSock->GetUserPort()) + " " + sMessage.Token(4) + "\001");
m_pUser->PutUser(":" + Nick.GetNickMask() + " PRIVMSG " + GetNick() + " :\001DCC " + sType + " " + sFile + " " + CString::ToString(pSock->GetUserPort()) + " " + sMessage.Token(4) + "\001");
}
} else if (sType.CaseCmp("ACCEPT") == 0) {
// Need to lookup the connection by port, filter the port, and forward to the user
@@ -658,7 +661,7 @@ bool CIRCSock::OnPrivCTCP(CNick& Nick, CString& sMessage) {
if ((pSock) && (strncasecmp(pSock->GetSockName().c_str(), "DCC::", 5) == 0)) {
if (pSock->GetUserPort() == atoi(sMessage.Token(3).c_str())) {
PutUser(":" + Nick.GetNickMask() + " PRIVMSG " + GetNick() + " :\001DCC " + sType + " " + sFile + " " + CString::ToString(pSock->GetLocalPort()) + " " + sMessage.Token(4) + "\001");
m_pUser->PutUser(":" + Nick.GetNickMask() + " PRIVMSG " + GetNick() + " :\001DCC " + sType + " " + sFile + " " + CString::ToString(pSock->GetLocalPort()) + " " + sMessage.Token(4) + "\001");
}
}
}
@@ -675,7 +678,7 @@ bool CIRCSock::OnPrivCTCP(CNick& Nick, CString& sMessage) {
sReply = it->second;
}
if (sReply.empty() && sQuery == "VERSION" && !IsUserAttached()) {
if (sReply.empty() && sQuery == "VERSION" && !m_pUser->IsUserAttached()) {
sReply = "ZNC by prozac - http://znc.sourceforge.net";
}
@@ -691,9 +694,9 @@ bool CIRCSock::OnPrivCTCP(CNick& Nick, CString& sMessage) {
bool CIRCSock::OnPrivNotice(CNick& Nick, CString& sMessage) {
MODULECALL(OnPrivNotice(Nick, sMessage));
if (!m_pUserSock) {
if (!m_pUser->IsUserAttached()) {
// If the user is detached, add to the buffer
m_QueryBuffer.AddLine(":" + Nick.GetNickMask() + " NOTICE ", " :" + sMessage);
m_pUser->AddQueryBuffer(":" + Nick.GetNickMask() + " NOTICE ", " :" + sMessage);
}
return false;
@@ -702,9 +705,9 @@ bool CIRCSock::OnPrivNotice(CNick& Nick, CString& sMessage) {
bool CIRCSock::OnPrivMsg(CNick& Nick, CString& sMessage) {
MODULECALL(OnPrivMsg(Nick, sMessage));
if (!m_pUserSock) {
if (!m_pUser->IsUserAttached()) {
// If the user is detached, add to the buffer
m_QueryBuffer.AddLine(":" + Nick.GetNickMask() + " PRIVMSG ", " :" + sMessage);
m_pUser->AddQueryBuffer(":" + Nick.GetNickMask() + " PRIVMSG ", " :" + sMessage);
}
return false;
@@ -728,7 +731,7 @@ bool CIRCSock::OnChanNotice(CNick& Nick, const CString& sChan, CString& sMessage
if (pChan) {
MODULECALL(OnChanNotice(Nick, *pChan, sMessage));
if ((pChan->KeepBuffer()) || (!m_pUserSock)) {
if ((pChan->KeepBuffer()) || (!m_pUser->IsUserAttached())) {
pChan->AddBuffer(":" + Nick.GetNickMask() + " NOTICE " + sChan + " :" + sMessage);
}
}
@@ -741,7 +744,7 @@ bool CIRCSock::OnChanMsg(CNick& Nick, const CString& sChan, CString& sMessage) {
if (pChan) {
MODULECALL(OnChanMsg(Nick, *pChan, sMessage));
if ((pChan->KeepBuffer()) || (!m_pUserSock)) {
if (pChan->KeepBuffer() || !m_pUser->IsUserAttached()) {
pChan->AddBuffer(":" + Nick.GetNickMask() + " PRIVMSG " + sChan + " :" + sMessage);
}
}
@@ -749,98 +752,19 @@ bool CIRCSock::OnChanMsg(CNick& Nick, const CString& sChan, CString& sMessage) {
return ((pChan) && (pChan->IsDetached()));
}
void CIRCSock::UserConnected(CUserSock* pUserSock) {
if (m_pUserSock) {
m_pUserSock->BouncedOff();
}
m_pUserSock = pUserSock;
CString sConfNick = m_pUser->GetNick();
if (GetNick().CaseCmp(CNick::Concat(sConfNick, m_pUser->GetAwaySuffix(), GetMaxNickLen())) == 0) {
PutServ("NICK " + sConfNick);
}
if (m_RawBuffer.IsEmpty()) {
PutUser(":irc.znc.com 001 " + m_pUserSock->GetNick() + " :- Welcome to ZNC -");
} else {
unsigned int uIdx = 0;
CString sLine;
while (m_RawBuffer.GetLine(GetNick(), sLine, uIdx++)) {
PutUser(sLine);
}
}
// Send the cached MOTD
if (m_MotdBuffer.IsEmpty()) {
PutServ("MOTD");
} else {
unsigned int uIdx = 0;
CString sLine;
while (m_MotdBuffer.GetLine(GetNick(), sLine, uIdx++)) {
PutUser(sLine);
}
}
const vector<CChan*>& vChans = m_pUser->GetChans();
for (unsigned int a = 0; a < vChans.size(); a++) {
if ((vChans[a]->IsOn()) && (!vChans[a]->IsDetached())) {
vChans[a]->JoinUser(true);
}
}
CString sBufLine;
while (m_QueryBuffer.GetNextLine(GetNick(), sBufLine)) {
PutUser(sBufLine);
}
}
void CIRCSock::UserDisconnected() {
if (m_pUserSock && !m_pAwayNickTimer) {
m_pAwayNickTimer = new CAwayNickTimer(m_pUser);
CZNC::Get().GetManager().AddCron(m_pAwayNickTimer);
}
m_pUserSock = NULL;
}
void CIRCSock::PutServ(const CString& sLine) {
DEBUG_ONLY(cout << GetSockName() << " -> [" << sLine << "]" << endl);
Write(sLine + "\r\n");
}
void CIRCSock::PutUser(const CString& sLine) {
if (m_pUserSock) {
m_pUserSock->PutServ(sLine);
}
}
void CIRCSock::PutStatus(const CString& sLine) {
if (m_pUserSock) {
m_pUserSock->PutStatus(sLine);
}
}
void CIRCSock::SetNick(const CString& sNick) {
m_Nick.SetNick(sNick);
m_pUser->SetIRCNick(m_Nick);
if (m_pUserSock) {
m_pUserSock->SetNick(sNick);
}
}
void CIRCSock::Connected() {
DEBUG_ONLY(cout << GetSockName() << " == Connected()" << endl);
CUserSock* pUserSock = (CUserSock*) CZNC::Get().FindSockByName("USR::" + m_pUser->GetUserName());
if (pUserSock) {
m_pUserSock = pUserSock;
pUserSock->IRCConnected(this);
}
m_pUser->IRCConnected(this);
if (!m_sPass.empty()) {
PutServ("PASS " + m_sPass);
@@ -889,7 +813,9 @@ void CIRCSock::ParseISupport(const CString& sLine) {
m_sPerms = sPrefixes;
m_sPermModes = sPermModes;
}
} else if (sName.CaseCmp("CHANMODES") == 0) {
} else if (sName.CaseCmp("CHANTYPES") == 0) {
m_pUser->SetChanPrefixes(sValue);
} else if (sName.CaseCmp("NICKLEN") == 0) {
unsigned int uMax = sValue.ToUInt();
if (uMax) {
-11
View File
@@ -8,7 +8,6 @@
// Forward Declarations
class CZNC;
class CUserSock;
class CAwayNickTimer;
// !Forward Declarations
@@ -42,12 +41,7 @@ public:
virtual void Timeout();
void KeepNick(bool bForce = false);
bool IsUserAttached() { return (m_pUserSock != NULL); }
void UserConnected(CUserSock* pUserSock);
void UserDisconnected();
void PutServ(const CString& sLine);
void PutUser(const CString& sLine);
void PutStatus(const CString& sLine);
void CIRCSock::ParseISupport(const CString& sLine);
// Setters
@@ -84,14 +78,9 @@ protected:
CUser* m_pUser;
CNick m_Nick;
CString m_sPass;
CBuffer m_RawBuffer;
CBuffer m_MotdBuffer;
CUserSock* m_pUserSock;
map<CString, CChan*> m_msChans;
unsigned int m_uMaxNickLen;
unsigned int m_uQueryBufferCount;
CAwayNickTimer* m_pAwayNickTimer;
CBuffer m_QueryBuffer;
};
#endif // !_IRCSOCK_H
+7 -4
View File
@@ -164,6 +164,7 @@ CModule::CModule(void* pDLL, CUser* pUser, const CString& sModName) {
m_pDLL = pDLL;
m_pManager = &(CZNC::Get().GetManager());;
m_pUser = pUser;
m_pUserSock = NULL;
m_sModName = sModName;
if (m_pUser) {
@@ -177,6 +178,7 @@ CModule::CModule(void* pDLL, const CString& sModName) {
m_pDLL = pDLL;
m_pManager = &(CZNC::Get().GetManager());
m_pUser = NULL;
m_pUserSock = NULL;
m_sModName = sModName;
m_sSavePath = CZNC::Get().GetZNCPath() + "/moddata/" + m_sModName;
@@ -196,6 +198,7 @@ CModule::~CModule() {
}
void CModule::SetUser(CUser* pUser) { m_pUser = pUser; }
void CModule::SetUserSock(CUserSock* pUserSock) { m_pUserSock = pUserSock; }
void CModule::Unload() { throw UNLOAD; }
bool CModule::LoadRegistry() {
@@ -478,16 +481,16 @@ bool CModule::PutIRC(const CString& sLine) {
return (m_pUser) ? m_pUser->PutIRC(sLine) : false;
}
bool CModule::PutUser(const CString& sLine) {
return (m_pUser) ? m_pUser->PutUser(sLine) : false;
return (m_pUser) ? m_pUser->PutUser(sLine, m_pUserSock) : false;
}
bool CModule::PutStatus(const CString& sLine) {
return (m_pUser) ? m_pUser->PutStatus(sLine) : false;
return (m_pUser) ? m_pUser->PutStatus(sLine, m_pUserSock) : false;
}
bool CModule::PutModule(const CString& sLine, const CString& sIdent, const CString& sHost) {
return (m_pUser) ? m_pUser->PutUser(":" + GetModNick() + "!" + sIdent + "@" + sHost + " PRIVMSG " + m_pUser->GetCurNick() + " :" + sLine) : false;
return (m_pUser) ? m_pUser->PutUser(":" + GetModNick() + "!" + sIdent + "@" + sHost + " PRIVMSG " + m_pUser->GetCurNick() + " :" + sLine, m_pUserSock) : false;
}
bool CModule::PutModNotice(const CString& sLine, const CString& sIdent, const CString& sHost) {
return (m_pUser) ? m_pUser->PutUser(":" + GetModNick() + "!" + sIdent + "@" + sHost + " NOTICE " + m_pUser->GetCurNick() + " :" + sLine) : false;
return (m_pUser) ? m_pUser->PutUser(":" + GetModNick() + "!" + sIdent + "@" + sHost + " NOTICE " + m_pUser->GetCurNick() + " :" + sLine, m_pUserSock) : false;
}
+4
View File
@@ -3,6 +3,7 @@
#include "main.h"
#include "FileUtils.h"
#include "UserSock.h"
#include <dlfcn.h>
#include <vector>
#include <set>
@@ -192,6 +193,7 @@ public:
} EModException;
void SetUser(CUser* pUser);
void SetUserSock(CUserSock* pUserSock);
void Unload();
virtual bool OnLoad(const CString& sArgs);
@@ -290,6 +292,7 @@ public:
const CString& GetDescription() const { return m_sDescription; }
const CString& GetArgs() const { return m_sArgs; }
CUser* GetUser() { return m_pUser; }
CUserSock* GetUserSock() { return m_pUserSock; }
TSocketManager<Csock>* GetManager() { return m_pManager; }
// !Getters
@@ -301,6 +304,7 @@ protected:
void* m_pDLL;
TSocketManager<Csock>* m_pManager;
CUser* m_pUser;
CUserSock* m_pUserSock;
CString m_sModName;
CString m_sSavePath;
CString m_sArgs;
+142 -50
View File
@@ -19,6 +19,8 @@ CUser::CUser(const CString& sUserName) {
#ifdef _MODULES
m_pModules = new CModules;
#endif
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_bBounceDCCs = true;
m_bPassHashed = false;
m_bUseClientIP = false;
@@ -26,6 +28,7 @@ CUser::CUser(const CString& sUserName) {
m_bDenyLoadMod = false;
m_bAdmin= false;
m_sStatusPrefix = "*";
m_sChanPrefixes = "#&";
m_uBufferCount = 50;
m_bKeepBuffer = false;
m_bAutoCycle = true;
@@ -49,6 +52,10 @@ CUser::~CUser() {
delete m_vChans[b];
}
for (unsigned int c = 0; c < m_vUserSocks.size(); c++) {
CZNC::Get().GetManager().DelSockByAddr(m_vUserSocks[c]);
}
CZNC::Get().GetManager().DelCronByAddr(m_pKeepNickTimer);
CZNC::Get().GetManager().DelCronByAddr(m_pJoinTimer);
}
@@ -60,6 +67,84 @@ bool CUser::OnBoot() {
return true;
}
void CUser::IRCConnected(CIRCSock* pIRCSock) {
TSocketManager<Csock>& Manager = CZNC::Get().GetManager();
for (unsigned int a = 0; a < Manager.size(); a++) {
CUserSock* pUserSock = (CUserSock*) Manager[a];
const CString& sSockName = pUserSock->GetSockName();
if (sSockName == ("USR::" + GetUserName())) {
m_vUserSocks.push_back(pUserSock);
pUserSock->IRCConnected(pIRCSock);
}
}
}
void CUser::IRCDisconnected() {
for (unsigned int a = 0; a < m_vUserSocks.size(); a++) {
m_vUserSocks[a]->IRCDisconnected();
}
}
void CUser::UserConnected(CUserSock* pUserSock) {
m_vUserSocks.push_back(pUserSock);
CString sConfNick = GetNick();
/*if (ircsock.Nick().CaseCmp(CNick::Concat(sConfNick, GetAwaySuffix(), GetMaxNickLen())) == 0) {
PutIRC("NICK " + sConfNick);
} nigs */
if (m_RawBuffer.IsEmpty()) {
pUserSock->PutServ(":irc.znc.com 001 " + pUserSock->GetNick() + " :- Welcome to ZNC -");
} else {
unsigned int uIdx = 0;
CString sLine;
while (m_RawBuffer.GetLine(GetNick(), sLine, uIdx++)) {
pUserSock->PutServ(sLine);
}
}
// Send the cached MOTD
if (m_MotdBuffer.IsEmpty()) {
PutIRC("MOTD");
} else {
unsigned int uIdx = 0;
CString sLine;
while (m_MotdBuffer.GetLine(GetNick(), sLine, uIdx++)) {
pUserSock->PutServ(sLine);
}
}
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, "", pUserSock);
}
}
CString sBufLine;
while (m_QueryBuffer.GetNextLine(GetNick(), sBufLine)) {
pUserSock->PutServ(sBufLine);
}
}
void CUser::UserDisconnected(CUserSock* pUserSock) {
/*if (!m_pAwayNickTimer) {
m_pAwayNickTimer = new CAwayNickTimer(this);
CZNC::Get().GetManager().AddCron(m_pAwayNickTimer);
}*/
for (unsigned int a = 0; a < m_vUserSocks.size(); a++) {
if (m_vUserSocks[a] == pUserSock) {
m_vUserSocks.erase(m_vUserSocks.begin() + a);
break;
}
}
}
bool CUser::Clone(const CUser& User, CString& sErrorRet) {
unsigned int a = 0;
sErrorRet.clear();
@@ -99,8 +184,9 @@ bool CUser::Clone(const CUser& User, CString& sErrorRet) {
AddAllowedHost(*it);
}
CUserSock* pSock = GetUserSock();
if (pSock) {
for (unsigned int a = 0; a < m_vUserSocks.size(); a++) {
CUserSock* pSock = m_vUserSocks[a];
if (!IsHostAllowed(pSock->GetRemoteIP())) {
pSock->PutStatusNotice("You are being disconnected because your IP is no longer allowed to connect to this user");
pSock->Close();
@@ -540,7 +626,7 @@ bool CUser::CheckPass(const CString& sPass) {
return (m_sPass.CaseCmp((char*) CMD5(sPass)) == 0);
}
CUserSock* CUser::GetUserSock() {
/*CUserSock* CUser::GetUserSock() {
// Todo: optimize this by saving a pointer to the sock
TSocketManager<Csock>& Manager = CZNC::Get().GetManager();
CString sSockName = "USR::" + m_sUserName;
@@ -555,17 +641,7 @@ CUserSock* CUser::GetUserSock() {
}
return (CUserSock*) CZNC::Get().GetManager().FindSockByName(sSockName);
}
bool CUser::IsUserAttached() {
CUserSock* pUserSock = GetUserSock();
if (!pUserSock) {
return false;
}
return pUserSock->IsAttached();
}
}*/
CIRCSock* CUser::GetIRCSock() {
// Todo: optimize this by saving a pointer to the sock
@@ -579,10 +655,8 @@ CString CUser::GetLocalIP() {
return pIRCSock->GetLocalIP();
}
CUserSock* pUserSock = GetUserSock();
if (pUserSock) {
return pUserSock->GetLocalIP();
if (m_vUserSocks.size()) {
return m_vUserSocks[0]->GetLocalIP();
}
return "";
@@ -599,48 +673,60 @@ bool CUser::PutIRC(const CString& sLine) {
return true;
}
bool CUser::PutUser(const CString& sLine) {
CUserSock* pUserSock = GetUserSock();
bool CUser::PutUser(const CString& sLine, CUserSock* pUserSock) {
for (unsigned int a = 0; a < m_vUserSocks.size(); a++) {
if (!pUserSock || pUserSock == m_vUserSocks[a]) {
m_vUserSocks[a]->PutServ(sLine);
if (!pUserSock) {
return false;
if (pUserSock) {
return true;
}
}
}
pUserSock->PutServ(sLine);
return true;
return (pUserSock == NULL);
}
bool CUser::PutStatus(const CString& sLine) {
CUserSock* pUserSock = GetUserSock();
bool CUser::PutStatus(const CString& sLine, CUserSock* pUserSock) {
for (unsigned int a = 0; a < m_vUserSocks.size(); a++) {
if (!pUserSock || pUserSock == m_vUserSocks[a]) {
m_vUserSocks[a]->PutStatus(sLine);
if (!pUserSock) {
return false;
if (pUserSock) {
return true;
}
}
}
pUserSock->PutStatus(sLine);
return true;
return (pUserSock == NULL);
}
bool CUser::PutStatusNotice(const CString& sLine) {
CUserSock* pUserSock = GetUserSock();
bool CUser::PutStatusNotice(const CString& sLine, CUserSock* pUserSock) {
for (unsigned int a = 0; a < m_vUserSocks.size(); a++) {
if (!pUserSock || pUserSock == m_vUserSocks[a]) {
m_vUserSocks[a]->PutStatusNotice(sLine);
if (!pUserSock) {
return false;
if (pUserSock) {
return true;
}
}
}
pUserSock->PutStatusNotice(sLine);
return true;
return (pUserSock == NULL);
}
bool CUser::PutModule(const CString& sModule, const CString& sLine) {
CUserSock* pUserSock = GetUserSock();
bool CUser::PutModule(const CString& sModule, const CString& sLine, CUserSock* pUserSock) {
for (unsigned int a = 0; a < m_vUserSocks.size(); a++) {
if (!pUserSock || pUserSock == m_vUserSocks[a]) {
m_vUserSocks[a]->PutModule(sModule, sLine);
if (!pUserSock) {
return false;
if (pUserSock) {
return true;
}
}
}
pUserSock->PutModule(sModule, sLine);
return true;
return (pUserSock == NULL);
}
bool CUser::ResumeFile(const CString& sRemoteNick, unsigned short uPort, unsigned long uFileSize) {
@@ -718,10 +804,8 @@ CString CUser::GetCurNick() {
return pIRCSock->GetNick();
}
CUserSock* pUserSock = GetUserSock();
if (pUserSock) {
return pUserSock->GetNick();
if (m_vUserSocks.size()) {
return m_vUserSocks[0]->GetNick();
}
return "";
@@ -742,9 +826,20 @@ void CUser::SetKeepNick(bool b) { m_bKeepNick = b; }
void CUser::SetDenyLoadMod(bool b) { m_bDenyLoadMod = b; }
void CUser::SetAdmin(bool b) { m_bAdmin = b; }
void CUser::SetDefaultChanModes(const CString& s) { m_sDefaultChanModes = s; }
void CUser::SetIRCNick(const CNick& n) { m_IRCNick = n; }
void CUser::SetIRCServer(const CString& s) { m_sIRCServer = s; }
void CUser::SetQuitMsg(const CString& s) { m_sQuitMsg = s; }
void CUser::SetBufferCount(unsigned int u) { m_uBufferCount = u; }
void CUser::SetKeepBuffer(bool b) { m_bKeepBuffer = b; }
void CUser::SetAutoCycle(bool b) { m_bAutoCycle = b; }
void CUser::SetIRCNick(const CNick& n) {
m_IRCNick = n;
for (unsigned int a = 0; a < m_vUserSocks.size(); a++) {
m_vUserSocks[a]->SetNick(n.GetNick());
}
}
bool CUser::AddCTCPReply(const CString& sCTCP, const CString& sReply) {
if (sCTCP.empty() || sReply.empty()) {
return false;
@@ -753,9 +848,6 @@ bool CUser::AddCTCPReply(const CString& sCTCP, const CString& sReply) {
m_mssCTCPReplies[sCTCP.AsUpper()] = sReply;
return true;
}
void CUser::SetBufferCount(unsigned int u) { m_uBufferCount = u; }
void CUser::SetKeepBuffer(bool b) { m_bKeepBuffer = b; }
void CUser::SetAutoCycle(bool b) { m_bAutoCycle = b; }
bool CUser::SetStatusPrefix(const CString& s) {
if ((!s.empty()) && (s.length() < 6) && (s.find(' ') == CString::npos)) {
+30 -6
View File
@@ -10,6 +10,7 @@
#include <set>
#include "Nick.h"
#include "FileUtils.h"
#include "Buffer.h"
using std::vector;
using std::set;
@@ -55,16 +56,29 @@ public:
// !Modules
#endif
// Buffers
void AddRawBuffer(const CString& sPre, const CString& sPost) { m_RawBuffer.AddLine(sPre, sPost); }
void AddMotdBuffer(const CString& sPre, const CString& sPost) { m_MotdBuffer.AddLine(sPre, sPost); }
void AddQueryBuffer(const CString& sPre, const CString& sPost) { m_QueryBuffer.AddLine(sPre, sPost); }
void ClearRawBuffer() { m_RawBuffer.Clear(); }
void ClearMotdBuffer() { m_MotdBuffer.Clear(); }
void ClearQueryBuffer() { m_QueryBuffer.Clear(); }
// !Buffers
bool OnBoot();
bool IsUserAttached();
bool PutIRC(const CString& sLine);
bool PutUser(const CString& sLine);
bool PutStatus(const CString& sLine);
bool PutStatusNotice(const CString& sLine);
bool PutModule(const CString& sModule, const CString& sLine);
bool PutUser(const CString& sLine, CUserSock* pUserSock = NULL);
bool PutStatus(const CString& sLine, CUserSock* pUserSock = NULL);
bool PutStatusNotice(const CString& sLine, CUserSock* pUserSock = NULL);
bool PutModule(const CString& sModule, const CString& sLine, CUserSock* pUserSock = NULL);
bool IsUserAttached() { return (m_vUserSocks.size() > 0); }
void UserConnected(CUserSock* pUserSock);
void UserDisconnected(CUserSock* pUserSock);
CString GetLocalIP();
void IRCConnected(CIRCSock* pIRCSock);
void IRCDisconnected();
bool SendFile(const CString& sRemoteNick, const CString& sFileName, const CString& sModuleName = "");
bool GetFile(const CString& sRemoteNick, const CString& sRemoteIP, unsigned short uRemotePort, const CString& sFileName, unsigned long uFileSize, const CString& sModuleName = "");
@@ -95,10 +109,11 @@ public:
void SetBufferCount(unsigned int u);
void SetKeepBuffer(bool b);
void SetAutoCycle(bool b);
void SetChanPrefixes(const CString& s) { m_sChanPrefixes = (s.empty()) ? "#&" : s; }
// !Setters
// Getters
CUserSock* GetUserSock();
vector<CUserSock*>& GetUserSocks() { return m_vUserSocks; }
CIRCSock* GetIRCSock();
const CString& GetUserName() const;
const CString& GetNick() const;
@@ -111,6 +126,9 @@ public:
bool IsPassHashed() const;
const set<CString>& GetAllowedHosts() const;
const CString& GetChanPrefixes() const { return m_sChanPrefixes; }
bool IsChan(const CString& sChan) const { return (sChan.size() && GetChanPrefixes().find(sChan[0]) != CString::npos); }
const CString& GetUserPath() const { if (!CFile::Exists(m_sUserPath)) { CUtils::MakeDir(m_sUserPath); } return m_sUserPath; }
const CString& GetDLPath() const { if (!CFile::Exists(m_sDLPath)) { CUtils::MakeDir(m_sDLPath); } return m_sDLPath; }
@@ -144,6 +162,7 @@ protected:
CString m_sPass;
CString m_sStatusPrefix;
CString m_sDefaultChanModes;
CString m_sChanPrefixes;
CNick m_IRCNick;
CString m_sIRCServer;
CString m_sQuitMsg;
@@ -154,6 +173,10 @@ protected:
CString m_sDLPath;
// !Paths
CBuffer m_RawBuffer;
CBuffer m_MotdBuffer;
CBuffer m_QueryBuffer;
bool m_bBounceDCCs;
bool m_bPassHashed;
bool m_bUseClientIP;
@@ -168,6 +191,7 @@ protected:
vector<CServer*> m_vServers;
vector<CChan*> m_vChans;
vector<CUserSock*> m_vUserSocks;
set<CString> m_ssAllowedHosts;
unsigned int m_uServerIdx;
unsigned int m_uBufferCount;
+26 -3
View File
@@ -142,7 +142,7 @@ void CUserSock::ReadLine(const CString& sData) {
}
} else if (sCommand.CaseCmp("QUIT") == 0) {
if (m_pIRCSock) {
m_pIRCSock->UserDisconnected();
m_pUser->UserDisconnected(this);
}
Close(); // Treat a client quit as a detach
@@ -168,9 +168,13 @@ void CUserSock::ReadLine(const CString& sData) {
CModule* pModule = CZNC::Get().GetModules().FindModule(sModule);
if (pModule) {
pModule->SetUserSock(this);
pModule->OnModNotice(sMsg);
pModule->SetUserSock(NULL);
} else if ((pModule = m_pUser->GetModules().FindModule(sModule))) {
pModule->SetUserSock(this);
pModule->OnModNotice(sMsg);
pModule->SetUserSock(NULL);
} else {
PutStatus("No such module [" + sModule + "]");
}
@@ -318,7 +322,9 @@ void CUserSock::ReadLine(const CString& sData) {
CModule* pModule = m_pUser->GetModules().FindModule(sModule);
if (pModule) {
pModule->SetUserSock(this);
pModule->OnModCTCP(sCTCP);
pModule->SetUserSock(NULL);
} else {
PutStatus("No such module [" + sModule + "]");
}
@@ -349,7 +355,9 @@ void CUserSock::ReadLine(const CString& sData) {
CModule* pModule = m_pUser->GetModules().FindModule(sModule);
if (pModule) {
pModule->SetUserSock(this);
pModule->OnModCommand(sMsg);
pModule->SetUserSock(NULL);
} else {
PutStatus("No such module [" + sModule + "]");
}
@@ -369,6 +377,21 @@ void CUserSock::ReadLine(const CString& sData) {
}
PutIRC("PRIVMSG " + sTarget + " :" + sMsg);
// Relay to the rest of the clients that may be connected to this user
if (m_pUser && m_pUser->IsChan(sTarget)) {
vector<CUserSock*>& vUserSocks = m_pUser->GetUserSocks();
for (unsigned int a = 0; a < vUserSocks.size(); a++) {
CUserSock* pUserSock = vUserSocks[a];
if (pUserSock != this) {
pUserSock->PutServ(":" + GetNickMask() + " PRIVMSG " + sTarget + " :" + sMsg);
}
}
}
return;
}
@@ -974,7 +997,7 @@ void CUserSock::AuthUser() {
if (pIRCSock) {
m_pIRCSock = pIRCSock;
pIRCSock->UserConnected(this);
m_pUser->UserConnected(this);
}
VOIDMODULECALL(OnUserAttached());
@@ -992,7 +1015,7 @@ void CUserSock::ConnectionRefused() {
void CUserSock::Disconnected() {
if (m_pIRCSock) {
m_pIRCSock->UserDisconnected();
m_pUser->UserDisconnected(this);
m_pIRCSock = NULL;
}
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef _MAIN_H
#define _MAIN_H
#define VERSION 0.041
#define VERSION 0.042
#ifndef _MODDIR_
#define _MODDIR_ "/usr/share/znc"
+9 -2
View File
@@ -14,9 +14,10 @@ class CShellMod;
class CExecSock : public Csock {
public:
CExecSock(CShellMod* pShellMod, const CString& sExec) : Csock() {
CExecSock(CShellMod* pShellMod, CUserSock* pUserSock, const CString& sExec) : Csock() {
EnableReadLine();
m_pParent = pShellMod;
m_pUserSock = pUserSock;
int iReadFD, iWriteFD;
m_iPid = popen2(iReadFD, iWriteFD, sExec);
ConnectFD(iReadFD, iWriteFD, "0.0.0.0:0");
@@ -83,6 +84,8 @@ public:
}
return;
}
private:
CUserSock* m_pUserSock;
};
class CShellMod : public CModule {
@@ -185,7 +188,7 @@ public:
}
void RunCommand(const CString& sCommand) {
m_pManager->AddSock((Csock*) new CExecSock(this, "cd " + m_sPath + " && " + sCommand), "SHELL");
m_pManager->AddSock((Csock*) new CExecSock(this, m_pUserSock, "cd " + m_sPath + " && " + sCommand), "SHELL");
}
private:
CString m_sPath;
@@ -204,11 +207,15 @@ void CExecSock::ReadLine(const CString& sData) {
a = sLine.find('\t');
}
m_pParent->SetUserSock(m_pUserSock);
m_pParent->PutShell(sLine);
m_pParent->SetUserSock(NULL);
}
void CExecSock::Disconnected() {
m_pParent->SetUserSock(m_pUserSock);
m_pParent->PutShell("znc$");
m_pParent->SetUserSock(NULL);
}
MODULEDEFS(CShellMod, "Gives shell access")
+2 -14
View File
@@ -74,11 +74,6 @@ int CZNC::Loop() {
for (set<CUser*>::iterator it = m_ssDelUsers.begin(); it != m_ssDelUsers.end(); it++) {
CUser* pUser = *it;
m_msUsers.erase(pUser->GetUserName());
CUserSock* pUserSock = pUser->GetUserSock();
if (pUserSock) {
m_Manager.DelSockByAddr(pUserSock);
}
CIRCSock* pIRCSock = pUser->GetIRCSock();
@@ -148,11 +143,7 @@ int CZNC::Loop() {
}
DEBUG_ONLY( cout << "User [" << pUser->GetUserName() << "] is connecting to [" << pServer->GetName() << ":" << pServer->GetPort() << "] ..." << endl);
CUserSock* pUserSock = pUser->GetUserSock();
if (pUserSock) {
pUserSock->PutStatus("Attempting to connect to [" + pServer->GetName() + ":" + CString::ToString(pServer->GetPort()) + "] ...");
}
pUser->PutStatus("Attempting to connect to [" + pServer->GetName() + ":" + CString::ToString(pServer->GetPort()) + "] ...");
pIRCSock = new CIRCSock(pUser);
pIRCSock->SetPass(pServer->GetPass());
@@ -166,10 +157,7 @@ int CZNC::Loop() {
#endif
if (!m_Manager.Connect(pServer->GetName(), pServer->GetPort(), sSockName, 20, bSSL, pUser->GetVHost(), pIRCSock)) {
ReleaseISpoof();
if (pUserSock) {
pUserSock->PutStatus("Unable to connect. (Bad host?)");
}
pUser->PutStatus("Unable to connect. (Bad host?)");
}
}
}