diff --git a/include/znc/Buffer.h b/include/znc/Buffer.h index e240db6f..c0edea17 100644 --- a/include/znc/Buffer.h +++ b/include/znc/Buffer.h @@ -39,12 +39,13 @@ public: /// Same as UpdateLine, but does nothing if this exact line already exists. int UpdateExactLine(const CString& sFormat); bool GetNextLine(CString& sRet, const MCString& msParams = MCString::EmptyMap); + bool GetLineFormat(unsigned int uIdx, CString& sRet) const; bool GetLine(unsigned int uIdx, CString& sRet, const MCString& msParams = MCString::EmptyMap) const; bool IsEmpty() const { return empty(); } void Clear() { clear(); } // Setters - void SetLineCount(unsigned int u); + bool SetLineCount(unsigned int u, bool bForce = false); // !Setters // Getters diff --git a/include/znc/Chan.h b/include/znc/Chan.h index 4dd27de4..9ba0f17b 100644 --- a/include/znc/Chan.h +++ b/include/znc/Chan.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -87,9 +88,11 @@ public: // !Nicks // Buffer - int AddBuffer(const CString& sLine); - void ClearBuffer(); - void TrimBuffer(const unsigned int uMax); + const CBuffer& GetBuffer() const { return m_Buffer; } + unsigned int GetBufferCount() const { return m_Buffer.GetLineCount(); } + bool SetBufferCount(unsigned int u, bool bForce = false) { return m_Buffer.SetLineCount(u, bForce); }; + int AddBuffer(const CString& sFormat) { return m_Buffer.AddLine(sFormat); } + void ClearBuffer() { m_Buffer.Clear(); } void SendBuffer(CClient* pClient); // !Buffer @@ -108,7 +111,6 @@ 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; } - 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; } @@ -133,10 +135,8 @@ public: const CString& GetTopicOwner() const { return m_sTopicOwner; } unsigned int GetTopicDate() const { return m_ulTopicDate; } const CString& GetDefaultModes() const { return m_sDefaultModes; } - const vector& GetBuffer() const { return m_vsBuffer; } const map& GetNicks() const { return m_msNicks; } unsigned int GetNickCount() const { return m_msNicks.size(); } - unsigned int GetBufferCount() const { return m_uBufferCount; } bool KeepBuffer() const { return m_bKeepBuffer; } bool IsDetached() const { return m_bDetached; } bool InConfig() const { return m_bInConfig; } @@ -162,8 +162,7 @@ protected: unsigned int m_uJoinTries; CString m_sDefaultModes; map m_msNicks; // Todo: make this caseless (irc style) - unsigned int m_uBufferCount; - vector m_vsBuffer; + CBuffer m_Buffer; bool m_bModeKnown; map m_musModes; diff --git a/modules/buffextras.cpp b/modules/buffextras.cpp index 5d992fca..171dc4f5 100644 --- a/modules/buffextras.cpp +++ b/modules/buffextras.cpp @@ -22,9 +22,7 @@ public: if (!Channel.KeepBuffer() && m_pNetwork->IsUserOnline()) return; - CString s = ":" + GetModNick() + "!" + GetModName() + "@znc.in PRIVMSG " - + Channel.GetName() + " :" + m_pUser->AddTimestamp(sMessage); - Channel.AddBuffer(s); + Channel.AddBuffer(":" + GetModNick() + "!" + GetModName() + "@znc.in PRIVMSG " + _NAMEDFMT(Channel.GetName()) + " :" + _NAMEDFMT(m_pUser->AddTimestamp(sMessage))); } virtual void OnRawMode(const CNick& OpNick, CChan& Channel, const CString& sModes, const CString& sArgs) { @@ -32,8 +30,7 @@ public: } virtual void OnKick(const CNick& OpNick, const CString& sKickedNick, CChan& Channel, const CString& sMessage) { - AddBuffer(Channel, OpNick.GetNickMask() + " kicked " + sKickedNick - + " Reason: [" + sMessage + "]"); + AddBuffer(Channel, OpNick.GetNickMask() + " kicked " + sKickedNick + " Reason: [" + sMessage + "]"); } virtual void OnQuit(const CNick& Nick, const CString& sMessage, const vector& vChans) { diff --git a/modules/crypt.cpp b/modules/crypt.cpp index fdaac9b1..68d72145 100644 --- a/modules/crypt.cpp +++ b/modules/crypt.cpp @@ -47,7 +47,7 @@ public: CChan* pChan = m_pNetwork->FindChan(sTarget); if (pChan) { if (pChan->KeepBuffer()) - pChan->AddBuffer(":\244" + m_pNetwork->GetIRCNick().GetNickMask() + " PRIVMSG " + sTarget + " :" + sMessage); + pChan->AddBuffer(":\244" + _NAMEDFMT(m_pNetwork->GetIRCNick().GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :" + _NAMEDFMT(sMessage)); m_pUser->PutUser(":\244" + m_pNetwork->GetIRCNick().GetNickMask() + " PRIVMSG " + sTarget + " :" + sMessage, NULL, m_pClient); } diff --git a/modules/savebuff.cpp b/modules/savebuff.cpp index 122949c2..cc7c6cdb 100644 --- a/modules/savebuff.cpp +++ b/modules/savebuff.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -104,7 +105,7 @@ public: CString sFile; if (DecryptChannel(pChan->GetName(), sFile)) { - if (!pChan->GetBuffer().empty()) + if (!pChan->GetBuffer().IsEmpty()) return(true); // reloaded a module probably in this case, so just verify we can decrypt the file VCString vsLines; @@ -142,13 +143,14 @@ public: continue; } - const vector & vBuffer = vChans[a]->GetBuffer(); + const CBuffer& Buffer = vChans[a]->GetBuffer(); + CString sLine; CString sFile = CRYPT_VERIFICATION_TOKEN; - for (u_int b = 0; b < vBuffer.size(); b++) - { - sFile += vBuffer[b] + "\n"; + unsigned int uIdx = 0; + while (Buffer.GetLineFormat(uIdx++, sLine)) { + sFile += sLine + "\n"; } CBlowfish c(m_sPassword, BF_ENCRYPT); diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 3a28d291..3de94edd 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -7,6 +7,7 @@ */ #include +#include CBufLine::CBufLine(const CString& sFormat) { m_sFormat = sFormat; @@ -58,6 +59,15 @@ int CBuffer::UpdateExactLine(const CString& sFormat) { return AddLine(sFormat); } +bool CBuffer::GetLineFormat(unsigned int uIdx, CString& sRet) const { + if (uIdx >= size()) { + return false; + } + + sRet = (*this)[uIdx].GetFormat(); + return true; +} + bool CBuffer::GetLine(unsigned int uIdx, CString& sRet, const MCString& msParams) const { if (uIdx >= size()) { return false; @@ -79,11 +89,17 @@ bool CBuffer::GetNextLine(CString& sRet, const MCString& msParams) { return true; } -void CBuffer::SetLineCount(unsigned int u) { +bool CBuffer::SetLineCount(unsigned int u, bool bForce) { + if (!bForce && u > CZNC::Get().GetMaxBufferSize()) { + return false; + } + m_uLineCount = u; // We may need to shrink the buffer if the allowed size got smaller while (size() > m_uLineCount) { erase(begin()); } + + return true; } diff --git a/src/Chan.cpp b/src/Chan.cpp index 383e0f99..9065989b 100644 --- a/src/Chan.cpp +++ b/src/Chan.cpp @@ -26,9 +26,9 @@ CChan::CChan(const CString& sName, CIRCNetwork* pNetwork, bool bInConfig, CConfi m_bInConfig = bInConfig; m_Nick.SetNetwork(m_pNetwork); m_bDetached = false; - m_uBufferCount = m_pNetwork->GetUser()->GetBufferCount(); - m_bKeepBuffer = m_pNetwork->GetUser()->KeepBuffer(); m_bDisabled = false; + SetBufferCount(m_pNetwork->GetUser()->GetBufferCount(), true); + SetKeepBuffer(m_pNetwork->GetUser()->KeepBuffer()); Reset(); if (pConfig) { @@ -106,14 +106,6 @@ void CChan::Clone(CChan& chan) { } } -bool CChan::SetBufferCount(unsigned int u, bool bForce) { - if (!bForce && u > CZNC::Get().GetMaxBufferSize()) - return false; - m_uBufferCount = u; - TrimBuffer(m_uBufferCount); - return true; -} - void CChan::Cycle() const { m_pNetwork->PutIRC("PART " + GetName() + "\r\nJOIN " + GetName() + " " + GetKey()); } @@ -516,34 +508,8 @@ CNick* CChan::FindNick(const CString& sNick) { return (it != m_msNicks.end()) ? &it->second : NULL; } -int CChan::AddBuffer(const CString& sLine) { - // Todo: revisit the buffering - if (!m_uBufferCount) { - return 0; - } - - if (m_vsBuffer.size() >= m_uBufferCount) { - m_vsBuffer.erase(m_vsBuffer.begin()); - } - - m_vsBuffer.push_back(sLine); - return m_vsBuffer.size(); -} - -void CChan::ClearBuffer() { - m_vsBuffer.clear(); -} - -void CChan::TrimBuffer(const unsigned int uMax) { - if (m_vsBuffer.size() > uMax) { - m_vsBuffer.erase(m_vsBuffer.begin(), m_vsBuffer.begin() + (m_vsBuffer.size() - uMax)); - } -} - void CChan::SendBuffer(CClient* pClient) { if (m_pNetwork && m_pNetwork->IsUserAttached()) { - const vector& vsBuffer = GetBuffer(); - // in the event that pClient is NULL, need to send this to all clients for the user // I'm presuming here that pClient is listed inside vClients thus vClients at this // point can't be empty. @@ -558,7 +524,7 @@ void CChan::SendBuffer(CClient* pClient) { // if pClient is not NULL, the loops break after the first iteration. // // Rework this if you like ... - if (vsBuffer.size()) { + if (!m_Buffer.IsEmpty()) { const vector & vClients = m_pNetwork->GetClients(); for (size_t uClient = 0; uClient < vClients.size(); ++uClient) { @@ -570,8 +536,9 @@ void CChan::SendBuffer(CClient* pClient) { m_pNetwork->PutUser(":***!znc@znc.in PRIVMSG " + GetName() + " :Buffer Playback...", pUseClient); } - for (unsigned int a = 0; a < vsBuffer.size(); a++) { - CString sLine(vsBuffer[a]); + CString sLine; + unsigned int uIdx = 0; + while (m_Buffer.GetLine(uIdx++, sLine)) { NETWORKMODULECALL(OnChanBufferPlayLine(*this, *pUseClient, sLine), m_pNetwork->GetUser(), m_pNetwork, NULL, continue); m_pNetwork->PutUser(sLine, pUseClient); } diff --git a/src/Client.cpp b/src/Client.cpp index 75c0527f..0401e40f 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -239,7 +239,7 @@ void CClient::ReadLine(const CString& sData) { CChan* pChan = m_pNetwork->FindChan(sTarget); if ((pChan) && (pChan->KeepBuffer())) { - pChan->AddBuffer(":" + GetNickMask() + " NOTICE " + sTarget + " :" + m_pUser->AddTimestamp(sMsg)); + pChan->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " NOTICE " + _NAMEDFMT(sTarget) + " :" + _NAMEDFMT(m_pUser->AddTimestamp(sMsg))); } // Relay to the rest of the clients that may be connected to this user @@ -285,7 +285,7 @@ void CClient::ReadLine(const CString& sData) { sCTCP = "ACTION " + sMessage; if (pChan && pChan->KeepBuffer()) { - pChan->AddBuffer(":" + GetNickMask() + " PRIVMSG " + sTarget + " :\001ACTION " + m_pUser->AddTimestamp(sMessage) + "\001"); + pChan->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :\001ACTION " + _NAMEDFMT(m_pUser->AddTimestamp(sMessage)) + "\001"); } // Relay to the rest of the clients that may be connected to this user @@ -333,7 +333,7 @@ void CClient::ReadLine(const CString& sData) { CChan* pChan = m_pNetwork->FindChan(sTarget); if ((pChan) && (pChan->KeepBuffer())) { - pChan->AddBuffer(":" + GetNickMask() + " PRIVMSG " + sTarget + " :" + m_pUser->AddTimestamp(sMsg)); + pChan->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :" + _NAMEDFMT(m_pUser->AddTimestamp(sMsg))); } PutIRC("PRIVMSG " + sTarget + " :" + sMsg); diff --git a/src/ClientCommand.cpp b/src/ClientCommand.cpp index f26046fa..ca620c2d 100644 --- a/src/ClientCommand.cpp +++ b/src/ClientCommand.cpp @@ -1073,7 +1073,7 @@ void CClient::UserCommand(CString& sLine) { return; } - if (pChan->GetBuffer().empty()) { + if (pChan->GetBuffer().IsEmpty()) { PutStatus("The buffer for [" + sChan + "] is empty"); return; } diff --git a/src/IRCNetwork.cpp b/src/IRCNetwork.cpp index 854429f9..8bfdcfcf 100644 --- a/src/IRCNetwork.cpp +++ b/src/IRCNetwork.cpp @@ -49,9 +49,9 @@ CIRCNetwork::CIRCNetwork(CUser *pUser, const CString& sName) { m_sChanPrefixes = ""; m_bIRCAway = false; - m_RawBuffer.SetLineCount(100); // This should be more than enough raws, especially since we are buffering the MOTD separately - m_MotdBuffer.SetLineCount(200); // This should be more than enough motd lines - m_QueryBuffer.SetLineCount(250); + m_RawBuffer.SetLineCount(100, true); // This should be more than enough raws, especially since we are buffering the MOTD separately + m_MotdBuffer.SetLineCount(200, true); // This should be more than enough motd lines + m_QueryBuffer.SetLineCount(250, true); } CIRCNetwork::CIRCNetwork(CUser *pUser, const CIRCNetwork *pNetwork, bool bCloneChans) { @@ -67,9 +67,9 @@ CIRCNetwork::CIRCNetwork(CUser *pUser, const CIRCNetwork *pNetwork, bool bCloneC m_sChanPrefixes = ""; m_bIRCAway = false; - m_RawBuffer.SetLineCount(100); // This should be more than enough raws, especially since we are buffering the MOTD separately - m_MotdBuffer.SetLineCount(200); // This should be more than enough motd lines - m_QueryBuffer.SetLineCount(250); + m_RawBuffer.SetLineCount(100, true); // This should be more than enough raws, especially since we are buffering the MOTD separately + m_MotdBuffer.SetLineCount(200, true); // This should be more than enough motd lines + m_QueryBuffer.SetLineCount(250, true); // Servers const vector& vServers = pNetwork->GetServers(); diff --git a/src/IRCSock.cpp b/src/IRCSock.cpp index d694ffe7..ca2c0b42 100644 --- a/src/IRCSock.cpp +++ b/src/IRCSock.cpp @@ -853,7 +853,7 @@ bool CIRCSock::OnChanCTCP(CNick& Nick, const CString& sChan, CString& sMessage) if (sMessage.TrimPrefix("ACTION ")) { IRCSOCKMODULECALL(OnChanAction(Nick, *pChan, sMessage), return true); if (pChan->KeepBuffer() || !m_pNetwork->IsUserOnline() || pChan->IsDetached()) { - pChan->AddBuffer(":" + Nick.GetNickMask() + " PRIVMSG " + sChan + " :\001ACTION " + m_pNetwork->GetUser()->AddTimestamp(sMessage) + "\001"); + pChan->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sChan) + " :\001ACTION " + _NAMEDFMT(m_pNetwork->GetUser()->AddTimestamp(sMessage)) + "\001"); } sMessage = "ACTION " + sMessage; } @@ -871,7 +871,7 @@ bool CIRCSock::OnChanNotice(CNick& Nick, const CString& sChan, CString& sMessage IRCSOCKMODULECALL(OnChanNotice(Nick, *pChan, sMessage), return true); if (pChan->KeepBuffer() || !m_pNetwork->IsUserOnline() || pChan->IsDetached()) { - pChan->AddBuffer(":" + Nick.GetNickMask() + " NOTICE " + sChan + " :" + m_pNetwork->GetUser()->AddTimestamp(sMessage)); + pChan->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " NOTICE " + _NAMEDFMT(sChan) + " :" + _NAMEDFMT(m_pNetwork->GetUser()->AddTimestamp(sMessage))); } } @@ -884,7 +884,7 @@ bool CIRCSock::OnChanMsg(CNick& Nick, const CString& sChan, CString& sMessage) { IRCSOCKMODULECALL(OnChanMsg(Nick, *pChan, sMessage), return true); if (pChan->KeepBuffer() || !m_pNetwork->IsUserOnline() || pChan->IsDetached()) { - pChan->AddBuffer(":" + Nick.GetNickMask() + " PRIVMSG " + sChan + " :" + m_pNetwork->GetUser()->AddTimestamp(sMessage)); + pChan->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sChan) + " :" + _NAMEDFMT(m_pNetwork->GetUser()->AddTimestamp(sMessage))); } }