diff --git a/include/znc/Buffer.h b/include/znc/Buffer.h index 17f33be1..f1271d26 100644 --- a/include/znc/Buffer.h +++ b/include/znc/Buffer.h @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -29,31 +30,32 @@ class CClient; class CBufLine { public: CBufLine() : CBufLine("") { throw 0; } // shouldn't be called, but is needed for compilation + CBufLine(const CMessage& Format, const CString& sText = ""); CBufLine(const CString& sFormat, const CString& sText = "", const timeval* ts = nullptr, const MCString& mssTags = MCString::EmptyMap); ~CBufLine(); - CString GetLine(const CClient& Client, const MCString& msParams) const; + CMessage ToMessage(const CClient& Client, const MCString& mssParams) const; + /// @deprecated Use ToMessage() instead + CString GetLine(const CClient& Client, const MCString& mssParams) const; void UpdateTime(); // Setters - void SetFormat(const CString& sFormat) { m_sFormat = sFormat; } + void SetFormat(const CString& sFormat) { m_Message.Parse(sFormat); } void SetText(const CString& sText) { m_sText = sText; } - void SetTime(const timeval& ts) { m_time = ts; } - void SetTags(const MCString& mssTags) { m_mssTags = mssTags; } + void SetTime(const timeval& ts) { m_Message.SetTime(ts); } + void SetTags(const MCString& mssTags) { m_Message.SetTags(mssTags); } // !Setters // Getters - const CString& GetFormat() const { return m_sFormat; } + CString GetFormat() const { return m_Message.ToString(CMessage::ExcludeTags); } const CString& GetText() const { return m_sText; } - timeval GetTime() const { return m_time; } - const MCString& GetTags() const { return m_mssTags; } + timeval GetTime() const { return m_Message.GetTime(); } + const MCString& GetTags() const { return m_Message.GetTags(); } // !Getters private: protected: - CString m_sFormat; + CMessage m_Message; CString m_sText; - timeval m_time; - MCString m_mssTags; }; class CBuffer : private std::deque { @@ -61,6 +63,8 @@ public: CBuffer(unsigned int uLineCount = 100); ~CBuffer(); + // TODO: CMessage-based API + size_type AddLine(const CString& sFormat, const CString& sText = "", const timeval* ts = nullptr, const MCString& mssTags = MCString::EmptyMap); /// Same as AddLine, but replaces a line whose format string starts with sMatch if there is one. size_type UpdateLine(const CString& sMatch, const CString& sFormat, const CString& sText = ""); diff --git a/src/Buffer.cpp b/src/Buffer.cpp index f0102fea..6c0ace84 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -19,34 +19,69 @@ #include #include -CBufLine::CBufLine(const CString& sFormat, const CString& sText, const timeval* ts, const MCString& mssTags) : m_sFormat(sFormat), m_sText(sText), m_time(), m_mssTags(mssTags) { +CBufLine::CBufLine(const CMessage& Format, const CString& sText) : m_Message(Format), m_sText(sText) { +} + +CBufLine::CBufLine(const CString& sFormat, const CString& sText, const timeval* ts, const MCString& mssTags) : m_sText(sText) { + m_Message.Parse(sFormat); + m_Message.SetTags(mssTags); + if (ts == nullptr) UpdateTime(); else - m_time = *ts; + m_Message.SetTime(*ts); } CBufLine::~CBufLine() {} void CBufLine::UpdateTime() { - if (0 == gettimeofday(&m_time, nullptr)) { - return; + timeval tv; + if (0 != gettimeofday(&tv, nullptr)) { + tv.tv_sec = time(nullptr); + tv.tv_usec = 0; } - m_time.tv_sec = time(nullptr); - m_time.tv_usec = 0; + m_Message.SetTime(tv); } -CString CBufLine::GetLine(const CClient& Client, const MCString& msParams) const { - MCString msThisParams = msParams; +CMessage CBufLine::ToMessage(const CClient& Client, const MCString& mssParams) const { + CMessage Line = m_Message; + + CString sSender = Line.GetNick().GetNickMask(); + Line.SetNick(CNick(CString::NamedFormat(sSender, mssParams))); + + MCString mssThisParams = mssParams; + if (Client.HasServerTime()) { + mssThisParams["text"] = m_sText; + } else { + mssThisParams["text"] = Client.GetUser()->AddTimestamp(Line.GetTime().tv_sec, m_sText); + } + + // make a copy of params, because the following loop modifies the original + VCString vsParams = Line.GetParams(); + for (unsigned int uIdx = 0; uIdx < vsParams.size(); ++uIdx) { + Line.SetParam(uIdx, CString::NamedFormat(vsParams[uIdx], mssThisParams)); + } + + return Line; +} + +CString CBufLine::GetLine(const CClient& Client, const MCString& mssParams) const { + CMessage Line = ToMessage(Client, mssParams); + + // Note: Discard all tags (except the time tag, conditionally) to + // keep the same behavior as ZNC versions 1.6 and earlier had. See + // CClient::PutClient(CMessage) documentation for more details. + Line.SetTags(MCString::EmptyMap); if (Client.HasServerTime()) { - msThisParams["text"] = m_sText; - CString sStr = CString::NamedFormat(m_sFormat, msThisParams); - return "@time=" + CUtils::FormatServerTime(m_time) + " " + sStr; - } else { - msThisParams["text"] = Client.GetUser()->AddTimestamp(m_time.tv_sec, m_sText); - return CString::NamedFormat(m_sFormat, msThisParams); + CString sTime = m_Message.GetTag("time"); + if (sTime.empty()) { + sTime = CUtils::FormatServerTime(m_Message.GetTime()); + } + Line.SetTag("time", sTime); } + + return Line.ToString(); } CBuffer::CBuffer(unsigned int uLineCount) : m_uLineCount(uLineCount) { diff --git a/src/Chan.cpp b/src/Chan.cpp index 9c024e33..f387e869 100644 --- a/src/Chan.cpp +++ b/src/Chan.cpp @@ -611,12 +611,10 @@ void CChan::SendBuffer(CClient* pClient, const CBuffer& Buffer) { size_t uSize = Buffer.Size(); for (size_t uIdx = 0; uIdx < uSize; uIdx++) { const CBufLine& BufLine = Buffer.GetBufLine(uIdx); - CMessage Message(BufLine.GetLine(*pUseClient, MCString::EmptyMap)); + CMessage Message = BufLine.ToMessage(*pUseClient, MCString::EmptyMap); Message.SetChan(this); Message.SetNetwork(m_pNetwork); Message.SetClient(pClient); - Message.SetTime(BufLine.GetTime()); - Message.SetTags(BufLine.GetTags()); if (bBatch) { Message.SetTag("batch", sBatchName); } diff --git a/src/Query.cpp b/src/Query.cpp index ea500c1b..ca4043d9 100644 --- a/src/Query.cpp +++ b/src/Query.cpp @@ -56,7 +56,7 @@ void CQuery::SendBuffer(CClient* pClient, const CBuffer& Buffer) { size_t uSize = Buffer.Size(); for (size_t uIdx = 0; uIdx < uSize; uIdx++) { const CBufLine& BufLine = Buffer.GetBufLine(uIdx); - CMessage Message(BufLine.GetLine(*pUseClient, msParams)); + CMessage Message = BufLine.ToMessage(*pUseClient, msParams); if (!pUseClient->HasEchoMessage() && !pUseClient->HasSelfMessage()) { if (Message.GetNick().NickEquals(pUseClient->GetNick())) { continue; @@ -64,8 +64,6 @@ void CQuery::SendBuffer(CClient* pClient, const CBuffer& Buffer) { } Message.SetNetwork(m_pNetwork); Message.SetClient(pUseClient); - Message.SetTime(BufLine.GetTime()); - Message.SetTags(BufLine.GetTags()); if (bBatch) { Message.SetTag("batch", sBatchName); }