diff --git a/include/znc/Buffer.h b/include/znc/Buffer.h index 8c00ed22..e240db6f 100644 --- a/include/znc/Buffer.h +++ b/include/znc/Buffer.h @@ -17,23 +17,15 @@ using std::deque; class CBufLine { public: - CBufLine(const CString& sPre, const CString& sPost, bool bIncNick); + CBufLine(const CString& sFormat); ~CBufLine(); - void GetLine(const CString& sTarget, CString& sRet) const; - - const CString& GetPre() const { return m_sPre; } - const CString& GetPost() const { return m_sPost; } - bool GetIncNick() const { return m_bIncNick; } - - void SetPre(const CString& s) { m_sPre = s; } - void SetPost(const CString& s) { m_sPost = s; } - void SetIncNick(bool b) { m_bIncNick = b; } + const CString& GetFormat() const { return m_sFormat; } + void SetFormat(const CString& sFormat) { m_sFormat = sFormat; } + void GetLine(CString& sRet, const MCString& msParams) const; private: protected: - CString m_sPre; - CString m_sPost; - bool m_bIncNick; + CString m_sFormat; }; class CBuffer : private deque { @@ -41,13 +33,13 @@ public: CBuffer(unsigned int uLineCount = 100); ~CBuffer(); - int AddLine(const CString& sPre, const CString& sPost, bool bIncNick = true); - /// Same as AddLine, but if there is already a line with sPre it is replaced. - int UpdateLine(const CString& sPre, const CString& sPost, bool bIncNick = true); - /// Same as UpdateLine, but does nothing if this exact line already exists - int UpdateExactLine(const CString& sPre, const CString& sPost, bool bIncNick = true); - bool GetNextLine(const CString& sTarget, CString& sRet); - bool GetLine(const CString& sTarget, CString& sRet, unsigned int uIdx) const; + int AddLine(const CString& sFormat); + /// Same as AddLine, but replaces a line that starts with sMatch if there is one. + int UpdateLine(const CString& sMatch, const CString& sFormat); + /// 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 GetLine(unsigned int uIdx, CString& sRet, const MCString& msParams = MCString::EmptyMap) const; bool IsEmpty() const { return empty(); } void Clear() { clear(); } diff --git a/include/znc/IRCNetwork.h b/include/znc/IRCNetwork.h index c4f5245b..7f35c439 100644 --- a/include/znc/IRCNetwork.h +++ b/include/znc/IRCNetwork.h @@ -107,17 +107,17 @@ public: bool PutIRC(const CString& sLine); // Buffers - void AddRawBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_RawBuffer.AddLine(sPre, sPost, bIncNick); } - void UpdateRawBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_RawBuffer.UpdateLine(sPre, sPost, bIncNick); } - void UpdateExactRawBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_RawBuffer.UpdateExactLine(sPre, sPost, bIncNick); } + void AddRawBuffer(const CString& sFormat) { m_RawBuffer.AddLine(sFormat); } + void UpdateRawBuffer(const CString& sMatch, const CString& sFormat) { m_RawBuffer.UpdateLine(sMatch, sFormat); } + void UpdateExactRawBuffer(const CString& sFormat) { m_RawBuffer.UpdateExactLine(sFormat); } void ClearRawBuffer() { m_RawBuffer.Clear(); } - void AddMotdBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_MotdBuffer.AddLine(sPre, sPost, bIncNick); } - void UpdateMotdBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_MotdBuffer.UpdateLine(sPre, sPost, bIncNick); } + void AddMotdBuffer(const CString& sFormat) { m_MotdBuffer.AddLine(sFormat); } + void UpdateMotdBuffer(const CString& sMatch, const CString& sFormat) { m_MotdBuffer.UpdateLine(sMatch, sFormat); } void ClearMotdBuffer() { m_MotdBuffer.Clear(); } - void AddQueryBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_QueryBuffer.AddLine(sPre, sPost, bIncNick); } - void UpdateQueryBuffer(const CString& sPre, const CString& sPost, bool bIncNick = true) { m_QueryBuffer.UpdateLine(sPre, sPost, bIncNick); } + void AddQueryBuffer(const CString& sFormat) { m_QueryBuffer.AddLine(sFormat); } + void UpdateQueryBuffer(const CString& sMatch, const CString& sFormat) { m_QueryBuffer.UpdateLine(sMatch, sFormat); } void ClearQueryBuffer() { m_QueryBuffer.Clear(); } // !Buffers diff --git a/include/znc/ZNCString.h b/include/znc/ZNCString.h index 10262e2f..9e5c87cf 100644 --- a/include/znc/ZNCString.h +++ b/include/znc/ZNCString.h @@ -482,6 +482,9 @@ public: /** Destruct this MCString. */ virtual ~MCString() { clear(); } + /** A static instance of an empty map. */ + static const MCString EmptyMap; + /** Status codes that can be returned by WriteToDisk() and * ReadFromDisk(). */ enum status_t diff --git a/modules/watch.cpp b/modules/watch.cpp index f515ea92..bcea6535 100644 --- a/modules/watch.cpp +++ b/modules/watch.cpp @@ -167,8 +167,11 @@ public: } virtual void OnClientLogin() { + MCString msParams; + msParams["target"] = m_pNetwork->GetCurNick(); + CString sBufLine; - while (m_Buffer.GetNextLine(m_pNetwork->GetCurNick(), sBufLine)) { + while (m_Buffer.GetNextLine(sBufLine, msParams)) { PutUser(sBufLine); } @@ -289,11 +292,9 @@ private: if (WatchEntry.IsMatch(Nick, sMessage, sSource, m_pNetwork)) { if (m_pNetwork->IsUserAttached()) { - m_pNetwork->PutUser(":" + WatchEntry.GetTarget() + "!watch@znc.in PRIVMSG " + - m_pNetwork->GetCurNick() + " :" + sMessage); + m_pNetwork->PutUser(":" + WatchEntry.GetTarget() + "!watch@znc.in PRIVMSG " + m_pNetwork->GetCurNick() + " :" + sMessage); } else { - m_Buffer.AddLine(":" + WatchEntry.GetTarget() + "!watch@znc.in PRIVMSG ", - " :" + m_pUser->AddTimestamp(sMessage)); + m_Buffer.AddLine(":" + _NAMEDFMT(WatchEntry.GetTarget()) + "!watch@znc.in PRIVMSG {target} :" + _NAMEDFMT(m_pUser->AddTimestamp(sMessage))); } } } diff --git a/src/Buffer.cpp b/src/Buffer.cpp index f50afe26..3a28d291 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -8,19 +8,14 @@ #include -CBufLine::CBufLine(const CString& sPre, const CString& sPost, bool bIncNick=true) { - m_sPre = sPre; - m_sPost = sPost; - m_bIncNick = bIncNick; +CBufLine::CBufLine(const CString& sFormat) { + m_sFormat = sFormat; } CBufLine::~CBufLine() {} -void CBufLine::GetLine(const CString& sTarget, CString& sRet) const { - if (m_bIncNick) - sRet = m_sPre + sTarget + m_sPost; - else - sRet = m_sPre + m_sPost; +void CBufLine::GetLine(CString& sRet, const MCString& msParams) const { + sRet = CString::NamedFormat(m_sFormat, msParams); } CBuffer::CBuffer(unsigned int uLineCount) { @@ -29,7 +24,7 @@ CBuffer::CBuffer(unsigned int uLineCount) { CBuffer::~CBuffer() {} -int CBuffer::AddLine(const CString& sPre, const CString& sPost, bool bIncNick) { +int CBuffer::AddLine(const CString& sFormat) { if (!m_uLineCount) { return 0; } @@ -38,48 +33,48 @@ int CBuffer::AddLine(const CString& sPre, const CString& sPost, bool bIncNick) { erase(begin()); } - push_back(CBufLine(sPre, sPost, bIncNick)); + push_back(CBufLine(sFormat)); return size(); } -int CBuffer::UpdateLine(const CString& sPre, const CString& sPost, bool bIncNick) { +int CBuffer::UpdateLine(const CString& sMatch, const CString& sFormat) { for (iterator it = begin(); it != end(); ++it) { - if (it->GetPre() == sPre) { - it->SetPost(sPost); - it->SetIncNick(bIncNick); + if (it->GetFormat().compare(0, sMatch.length(), sMatch) == 0) { + it->SetFormat(sFormat); return size(); } } - return AddLine(sPre, sPost, bIncNick); + return AddLine(sFormat); } -int CBuffer::UpdateExactLine(const CString& sPre, const CString& sPost, bool bIncNick) { +int CBuffer::UpdateExactLine(const CString& sFormat) { for (iterator it = begin(); it != end(); ++it) { - if (it->GetPre() == sPre && it->GetPost() == sPost) + if (it->GetFormat() == sFormat) { return size(); + } } - return AddLine(sPre, sPost, bIncNick); + return AddLine(sFormat); } -bool CBuffer::GetLine(const CString& sTarget, CString& sRet, unsigned int uIdx) const { +bool CBuffer::GetLine(unsigned int uIdx, CString& sRet, const MCString& msParams) const { if (uIdx >= size()) { return false; } - (*this)[uIdx].GetLine(sTarget, sRet); + (*this)[uIdx].GetLine(sRet, msParams); return true; } -bool CBuffer::GetNextLine(const CString& sTarget, CString& sRet) { +bool CBuffer::GetNextLine(CString& sRet, const MCString& msParams) { sRet = ""; if (!size()) { return false; } - begin()->GetLine(sTarget, sRet); + begin()->GetLine(sRet, msParams); erase(begin()); return true; } diff --git a/src/IRCNetwork.cpp b/src/IRCNetwork.cpp index c0b15145..854429f9 100644 --- a/src/IRCNetwork.cpp +++ b/src/IRCNetwork.cpp @@ -344,13 +344,16 @@ void CIRCNetwork::ClientConnected(CClient *pClient) { m_vClients.push_back(pClient); + unsigned int uIdx; + CString sLine; + MCString msParams; + msParams["target"] = GetIRCNick().GetNick(); + 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++)) { + uIdx = 0; + while (m_RawBuffer.GetLine(uIdx++, sLine, msParams)) { pClient->PutClient(sLine); } @@ -359,10 +362,8 @@ void CIRCNetwork::ClientConnected(CClient *pClient) { } // Send the cached MOTD - unsigned int uIdx = 0; - CString sLine; - - while (m_MotdBuffer.GetLine(GetIRCNick().GetNick(), sLine, uIdx++)) { + uIdx = 0; + while (m_MotdBuffer.GetLine(uIdx++, sLine, msParams)) { pClient->PutClient(sLine); } @@ -391,10 +392,9 @@ void CIRCNetwork::ClientConnected(CClient *pClient) { } } - CString sBufLine; - while (m_QueryBuffer.GetNextLine(GetIRCNick().GetNick(), sBufLine)) { - NETWORKMODULECALL(OnPrivBufferPlayLine(*pClient, sBufLine), m_pUser, this, NULL, continue); - pClient->PutClient(sBufLine); + while (m_QueryBuffer.GetNextLine(sLine, msParams)) { + NETWORKMODULECALL(OnPrivBufferPlayLine(*pClient, sLine), m_pUser, this, NULL, continue); + pClient->PutClient(sLine); } // Tell them why they won't connect diff --git a/src/IRCSock.cpp b/src/IRCSock.cpp index 7f535e9e..d694ffe7 100644 --- a/src/IRCSock.cpp +++ b/src/IRCSock.cpp @@ -118,6 +118,7 @@ void CIRCSock::ReadLine(const CString& sData) { unsigned int uRaw = sCmd.ToUInt(); CString sNick = sLine.Token(2); CString sRest = sLine.Token(3, true); + CString sTmp; switch (uRaw) { case 1: { // :irc.server.com 001 nick :Welcome to the Internet Relay Network nick @@ -152,13 +153,13 @@ void CIRCSock::ReadLine(const CString& sData) { IRCSOCKMODULECALL(OnIRCConnected(), NOTHING); m_pNetwork->ClearRawBuffer(); - m_pNetwork->AddRawBuffer(":" + sServer + " " + sCmd + " ", " " + sRest); + m_pNetwork->AddRawBuffer(":" + _NAMEDFMT(sServer) + " " + sCmd + " {target} " + _NAMEDFMT(sRest)); break; } case 5: ParseISupport(sRest); - m_pNetwork->UpdateExactRawBuffer(":" + sServer + " " + sCmd + " ", " " + sRest); + m_pNetwork->UpdateExactRawBuffer(":" + _NAMEDFMT(sServer) + " " + sCmd + " {target} " + _NAMEDFMT(sRest)); break; case 10: { // :irc.server.com 010 nick : CString sHost = sRest.Token(0); @@ -180,7 +181,8 @@ void CIRCSock::ReadLine(const CString& sData) { case 255: // client count case 265: // local users case 266: // global users - m_pNetwork->UpdateRawBuffer(":" + sServer + " " + sCmd + " ", " " + sRest); + sTmp = ":" + _NAMEDFMT(sServer) + " " + sCmd; + m_pNetwork->UpdateRawBuffer(sTmp, sTmp + " {target} " + _NAMEDFMT(sRest)); break; case 305: m_pNetwork->SetIRCAway(false); @@ -331,7 +333,7 @@ void CIRCSock::ReadLine(const CString& sData) { m_pNetwork->ClearMotdBuffer(); case 372: // motd case 376: // end motd - m_pNetwork->AddMotdBuffer(":" + sServer + " " + sCmd + " ", " " + sRest); + m_pNetwork->AddMotdBuffer(":" + _NAMEDFMT(sServer) + " " + sCmd + " {target} " + _NAMEDFMT(sRest)); break; case 437: // :irc.server.net 437 * badnick :Nick/channel is temporarily unavailable @@ -663,7 +665,7 @@ void CIRCSock::ReadLine(const CString& sData) { CString sMsg = sRest.Token(0, true).TrimPrefix_n(); if (!m_pNetwork->IsUserOnline()) { - m_pNetwork->AddQueryBuffer(":" + Nick.GetNickMask() + " WALLOPS ", ":" + m_pNetwork->GetUser()->AddTimestamp(sMsg), false); + m_pNetwork->AddQueryBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " WALLOPS :" + _NAMEDFMT(m_pNetwork->GetUser()->AddTimestamp(sMsg))); } } else if (sCmd.Equals("CAP")) { // CAPs are supported only before authorization. @@ -770,7 +772,7 @@ bool CIRCSock::OnPrivCTCP(CNick& Nick, CString& sMessage) { if (!m_pNetwork->IsUserOnline()) { // If the user is detached, add to the buffer - m_pNetwork->AddQueryBuffer(":" + Nick.GetNickMask() + " PRIVMSG ", " :\001ACTION " + m_pNetwork->GetUser()->AddTimestamp(sMessage) + "\001"); + m_pNetwork->AddQueryBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG {target} :\001ACTION " + _NAMEDFMT(m_pNetwork->GetUser()->AddTimestamp(sMessage)) + "\001"); } sMessage = "ACTION " + sMessage; @@ -825,7 +827,7 @@ bool CIRCSock::OnPrivNotice(CNick& Nick, CString& sMessage) { if (!m_pNetwork->IsUserOnline()) { // If the user is detached, add to the buffer - m_pNetwork->AddQueryBuffer(":" + Nick.GetNickMask() + " NOTICE ", " :" + m_pNetwork->GetUser()->AddTimestamp(sMessage)); + m_pNetwork->AddQueryBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " NOTICE {target} :" + _NAMEDFMT(m_pNetwork->GetUser()->AddTimestamp(sMessage))); } return false; @@ -836,7 +838,7 @@ bool CIRCSock::OnPrivMsg(CNick& Nick, CString& sMessage) { if (!m_pNetwork->IsUserOnline()) { // If the user is detached, add to the buffer - m_pNetwork->AddQueryBuffer(":" + Nick.GetNickMask() + " PRIVMSG ", " :" + m_pNetwork->GetUser()->AddTimestamp(sMessage)); + m_pNetwork->AddQueryBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG {target} :" + _NAMEDFMT(m_pNetwork->GetUser()->AddTimestamp(sMessage))); } return false; diff --git a/src/ZNCString.cpp b/src/ZNCString.cpp index e5bd0ffc..7cd19382 100644 --- a/src/ZNCString.cpp +++ b/src/ZNCString.cpp @@ -1095,6 +1095,8 @@ bool CString::RightChomp(unsigned int uLen) { } //////////////// MCString //////////////// +const MCString MCString::EmptyMap; + MCString::status_t MCString::WriteToDisk(const CString& sPath, mode_t iMode) const { CFile cFile(sPath);