diff --git a/Chan.cpp b/Chan.cpp index 9d677c0b..797eaa80 100644 --- a/Chan.cpp +++ b/Chan.cpp @@ -71,7 +71,7 @@ bool CChan::WriteConfig(CFile& File) { void CChan::Clone(CChan& chan) { // We assume that m_sName and m_pUser are equal - SetBufferCount(chan.GetBufferCount()); + SetBufferCount(chan.GetBufferCount(), true); SetKeepBuffer(chan.KeepBuffer()); SetKey(chan.GetKey()); SetDefaultModes(chan.GetDefaultModes()); @@ -91,6 +91,13 @@ void CChan::Clone(CChan& chan) { } } +bool CChan::SetBufferCount(unsigned int u, bool bForce) { + if (!bForce && u > CZNC::Get().GetMaxBufferSize()) + return false; + m_uBufferCount = u; + return true; +} + void CChan::Cycle() const { m_pUser->PutIRC("PART " + GetName() + "\r\nJOIN " + GetName() + " " + GetKey()); } diff --git a/Chan.h b/Chan.h index 7d8747d8..14a17a3b 100644 --- a/Chan.h +++ b/Chan.h @@ -104,7 +104,7 @@ public: void SetTopicOwner(const CString& s) { m_sTopicOwner = s; } void SetTopicDate(unsigned long u) { m_ulTopicDate = u; } void SetDefaultModes(const CString& s) { m_sDefaultModes = s; } - void SetBufferCount(unsigned int u) { m_uBufferCount = u; } + bool SetBufferCount(unsigned int u, bool bForce = false); void SetKeepBuffer(bool b) { m_bKeepBuffer = b; } void SetDetached(bool b = true) { m_bDetached = b; } void SetInConfig(bool b) { m_bInConfig = b; } diff --git a/ClientCommand.cpp b/ClientCommand.cpp index 8b2b8a7e..37acbf99 100644 --- a/ClientCommand.cpp +++ b/ClientCommand.cpp @@ -927,14 +927,12 @@ void CClient::UserCommand(CString& sLine) { unsigned int uLineCount = sLine.Token(2).ToUInt(); - if (uLineCount > 500) { - PutStatus("Max linecount is 500."); - return; + if (pChan->SetBufferCount(uLineCount)) { + PutStatus("BufferCount for [" + sChan + "] set to [" + CString(pChan->GetBufferCount()) + "]"); + } else { + PutStatus("Setting the buffer count failed, max buffer count is " + + CString(CZNC::Get().GetMaxBufferSize())); } - - pChan->SetBufferCount(uLineCount); - - PutStatus("BufferCount for [" + sChan + "] set to [" + CString(pChan->GetBufferCount()) + "]"); } else if (m_pUser->IsAdmin() && sCommand.Equals("TRAFFIC")) { CZNC::TrafficStatsPair Users, ZNC, Total; CZNC::TrafficStatsMap traffic = CZNC::Get().GetTrafficStats(Users, ZNC, Total); diff --git a/User.cpp b/User.cpp index c45a352f..0d5239a4 100644 --- a/User.cpp +++ b/User.cpp @@ -354,7 +354,7 @@ bool CUser::Clone(const CUser& User, CString& sErrorRet, bool bCloneChans) { SetQuitMsg(User.GetQuitMsg()); SetSkinName(User.GetSkinName()); SetDefaultChanModes(User.GetDefaultChanModes()); - SetBufferCount(User.GetBufferCount()); + SetBufferCount(User.GetBufferCount(), true); SetJoinTries(User.JoinTries()); SetMaxJoins(User.MaxJoins()); @@ -1168,11 +1168,16 @@ void CUser::SetDenySetVHost(bool b) { m_bDenySetVHost = 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::SetBufferCount(unsigned int u) { m_uBufferCount = u; } void CUser::SetKeepBuffer(bool b) { m_bKeepBuffer = b; } -void CUser::CheckIRCConnect() -{ +bool CUser::SetBufferCount(unsigned int u, bool bForce) { + if (!bForce && u > CZNC::Get().GetMaxBufferSize()) + return false; + m_uBufferCount = u; + return true; +} + +void CUser::CheckIRCConnect() { // Do we want to connect? if (m_bIRCConnectEnabled && GetIRCSock() == NULL) CZNC::Get().EnableConnectUser(); diff --git a/User.h b/User.h index 91562dc8..fe1628d4 100644 --- a/User.h +++ b/User.h @@ -155,7 +155,7 @@ public: void SetIRCServer(const CString& s); void SetQuitMsg(const CString& s); bool AddCTCPReply(const CString& sCTCP, const CString& sReply); - void SetBufferCount(unsigned int u); + bool SetBufferCount(unsigned int u, bool bForce = false); void SetKeepBuffer(bool b); void SetChanPrefixes(const CString& s) { m_sChanPrefixes = s; } void SetBeingDeleted(bool b) { m_bBeingDeleted = b; } diff --git a/modules/admin.cpp b/modules/admin.cpp index fbc9b58b..8a186e63 100644 --- a/modules/admin.cpp +++ b/modules/admin.cpp @@ -279,8 +279,13 @@ class CAdminMod : public CModule { } else if (sVar == "buffercount") { unsigned int i = sValue.ToUInt(); - pUser->SetBufferCount(i); - PutModule("BufferCount = " + sValue); + // Admins don't have to honour the buffer limit + if (pUser->SetBufferCount(i), m_pUser->IsAdmin()) { + PutModule("BufferCount = " + sValue); + } else { + PutModule("Setting failed, limit is " + + CString(CZNC::Get().GetMaxBufferSize())); + } } else if (sVar == "keepbuffer") { bool b = sValue.ToBool(); @@ -408,8 +413,13 @@ class CAdminMod : public CModule { PutModule("DefModes = " + sValue); } else if (sVar == "buffer") { unsigned int i = sValue.ToUInt(); - pChan->SetBufferCount(i); - PutModule("Buffer = " + CString(i)); + // Admins don't have to honour the buffer limit + if (pChan->SetBufferCount(i), m_pUser->IsAdmin()) { + PutModule("Buffer = " + sValue); + } else { + PutModule("Setting failed, limit is " + + CString(CZNC::Get().GetMaxBufferSize())); + } } else if (sVar == "inconfig") { bool b = sValue.ToBool(); pChan->SetInConfig(b); diff --git a/modules/webadmin.cpp b/modules/webadmin.cpp index a6c6f24b..d9b04571 100644 --- a/modules/webadmin.cpp +++ b/modules/webadmin.cpp @@ -208,8 +208,11 @@ public: pNewUser->SetVHost(pUser->GetVHost()); } - pNewUser->SetSkinName(WebSock.GetParam("skin")); + // First apply the old limit in case the new one is too high + if (pUser) + pNewUser->SetBufferCount(pUser->GetBufferCount(), true); pNewUser->SetBufferCount(WebSock.GetParam("bufsize").ToUInt()); + pNewUser->SetSkinName(WebSock.GetParam("skin")); pNewUser->SetKeepBuffer(WebSock.GetParam("keepbuffer").ToBool()); pNewUser->SetMultiClients(WebSock.GetParam("multiclients").ToBool()); pNewUser->SetBounceDCCs(WebSock.GetParam("bouncedccs").ToBool()); @@ -510,8 +513,8 @@ public: pUser->AddChan(pChan); } - pChan->SetDefaultModes(WebSock.GetParam("defmodes")); pChan->SetBufferCount(WebSock.GetParam("buffercount").ToUInt()); + pChan->SetDefaultModes(WebSock.GetParam("defmodes")); pChan->SetInConfig(WebSock.GetParam("save").ToBool()); pChan->SetKeepBuffer(WebSock.GetParam("keepbuffer").ToBool()); diff --git a/znc.cpp b/znc.cpp index 1f156ac5..813ba8ba 100644 --- a/znc.cpp +++ b/znc.cpp @@ -39,6 +39,7 @@ CZNC::CZNC() { SetISpoofFormat(""); // Set ISpoofFormat to default m_uBytesRead = 0; m_uBytesWritten = 0; + m_uiMaxBufferSize = 500; m_pConnectUserTimer = NULL; m_eConfigState = ECONFIG_NOTHING; m_TimeStarted = time(NULL); @@ -1266,7 +1267,7 @@ bool CZNC::DoRehash(CString& sError) if (pUser) { if (pChan) { if (sName.Equals("Buffer")) { - pChan->SetBufferCount(sValue.ToUInt()); + pChan->SetBufferCount(sValue.ToUInt(), true); continue; } else if (sName.Equals("KeepBuffer")) { pChan->SetKeepBuffer(sValue.Equals("true")); @@ -1288,7 +1289,7 @@ bool CZNC::DoRehash(CString& sError) } } else { if (sName.Equals("Buffer")) { - pUser->SetBufferCount(sValue.ToUInt()); + pUser->SetBufferCount(sValue.ToUInt(), true); continue; } else if (sName.Equals("KeepBuffer")) { pUser->SetKeepBuffer(sValue.Equals("true")); @@ -1626,6 +1627,9 @@ bool CZNC::DoRehash(CString& sError) } else if (sName.Equals("AnonIPLimit")) { m_uiAnonIPLimit = sValue.ToUInt(); continue; + } else if (sName.Equals("MaxBufferSize")) { + m_uiMaxBufferSize = sValue.ToUInt(); + continue; } } diff --git a/znc.h b/znc.h index 087ad960..4bf00d89 100644 --- a/znc.h +++ b/znc.h @@ -84,6 +84,7 @@ public: void SetStatusPrefix(const CString& s) { m_sStatusPrefix = (s.empty()) ? "*" : s; } void SetISpoofFile(const CString& s) { m_sISpoofFile = s; } void SetISpoofFormat(const CString& s) { m_sISpoofFormat = (s.empty()) ? "global { reply \"%\" }" : s; } + void SetMaxBufferSize(unsigned int i) { m_uiMaxBufferSize = i; } // !Setters // Getters @@ -108,6 +109,7 @@ public: const VCString& GetVHosts() const { return m_vsVHosts; } const vector& GetListeners() const { return m_vpListeners; } time_t TimeStarted() const { return m_TimeStarted; } + unsigned int GetMaxBufferSize() const { return m_uiMaxBufferSize; } // !Getters // Static allocator @@ -172,6 +174,7 @@ protected: CFile* m_pISpoofLockFile; unsigned int m_uiConnectDelay; unsigned int m_uiAnonIPLimit; + unsigned int m_uiMaxBufferSize; CGlobalModules* m_pModules; unsigned long long m_uBytesRead; unsigned long long m_uBytesWritten;