Store and format time in CBufLine.

Buflines need to know which part of text to wrap with the timestamp. The
second parameter to `AddLine` (and shorthands) is that text, which after
wrapping is added as the `text` parameter to `NamedFormat`.

Timestamps are formatted at the moment buffers are flushed to the
client. The client parameter to `GetLine` provides access to the User
and the new server-time capability.
This commit is contained in:
Stéphan Kochen
2011-10-16 23:05:42 +02:00
parent c3d677a4d8
commit c36480c8a1
14 changed files with 89 additions and 52 deletions
+25 -8
View File
@@ -15,17 +15,34 @@
using std::deque;
// Forward Declarations
class CClient;
// !Forward Declarations
class CBufLine {
public:
CBufLine(const CString& sFormat);
CBufLine(const CString& sFormat, const CString& sText = "", time_t tm = 0);
~CBufLine();
const CString& GetFormat() const { return m_sFormat; }
CString GetLine(const CClient& Client, const MCString& msParams) const;
void UpdateTime() { time(&m_tm); }
// Setters
void SetFormat(const CString& sFormat) { m_sFormat = sFormat; }
CString GetLine(const MCString& msParams) const;
void SetText(const CString& sText) { m_sText = sText; }
void SetTime(time_t tm) { m_tm = tm; }
// !Setters
// Getters
const CString& GetFormat() const { return m_sFormat; }
const CString& GetText() const { return m_sText; }
time_t GetTime() const { return m_tm; }
// !Getters
private:
protected:
CString m_sFormat;
CString m_sText;
time_t m_tm;
};
class CBuffer : private deque<CBufLine> {
@@ -33,13 +50,13 @@ public:
CBuffer(unsigned int uLineCount = 100);
~CBuffer();
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);
int AddLine(const CString& sFormat, const CString& sText = "", time_t tm = 0);
/// Same as AddLine, but replaces a line whose format string starts with sMatch if there is one.
int UpdateLine(const CString& sMatch, const CString& sFormat, const CString& sText = "");
/// Same as UpdateLine, but does nothing if this exact line already exists.
int UpdateExactLine(const CString& sFormat);
int UpdateExactLine(const CString& sFormat, const CString& sText = "");
const CBufLine& GetBufLine(unsigned int uIdx) const;
CString GetLine(unsigned int uIdx, const MCString& msParams = MCString::EmptyMap) const;
CString GetLine(unsigned int uIdx, const CClient& Client, const MCString& msParams = MCString::EmptyMap) const;
unsigned int Size() const { return size(); }
bool IsEmpty() const { return empty(); }
void Clear() { clear(); }
+1 -1
View File
@@ -91,7 +91,7 @@ public:
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); }
int AddBuffer(const CString& sFormat, const CString& sText = "") { return m_Buffer.AddLine(sFormat, sText); }
void ClearBuffer() { m_Buffer.Clear(); }
void SendBuffer(CClient* pClient);
// !Buffer
+1
View File
@@ -104,6 +104,7 @@ public:
bool HasNamesx() const { return m_bNamesx; }
bool HasUHNames() const { return m_bUHNames; }
bool IsAway() const { return m_bAway; }
bool HasServerTime() const { return m_bServerTime; }
void UserCommand(CString& sLine);
void UserPortCommand(CString& sLine);
+7 -7
View File
@@ -107,17 +107,17 @@ public:
bool PutIRC(const CString& sLine);
// Buffers
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 AddRawBuffer(const CString& sFormat, const CString& sText = "") { m_RawBuffer.AddLine(sFormat, sText); }
void UpdateRawBuffer(const CString& sMatch, const CString& sFormat, const CString& sText = "") { m_RawBuffer.UpdateLine(sMatch, sFormat, sText); }
void UpdateExactRawBuffer(const CString& sFormat, const CString& sText = "") { m_RawBuffer.UpdateExactLine(sFormat, sText); }
void ClearRawBuffer() { m_RawBuffer.Clear(); }
void AddMotdBuffer(const CString& sFormat) { m_MotdBuffer.AddLine(sFormat); }
void UpdateMotdBuffer(const CString& sMatch, const CString& sFormat) { m_MotdBuffer.UpdateLine(sMatch, sFormat); }
void AddMotdBuffer(const CString& sFormat, const CString& sText = "") { m_MotdBuffer.AddLine(sFormat, sText); }
void UpdateMotdBuffer(const CString& sMatch, const CString& sFormat, const CString& sText = "") { m_MotdBuffer.UpdateLine(sMatch, sFormat, sText); }
void ClearMotdBuffer() { m_MotdBuffer.Clear(); }
void AddQueryBuffer(const CString& sFormat) { m_QueryBuffer.AddLine(sFormat); }
void UpdateQueryBuffer(const CString& sMatch, const CString& sFormat) { m_QueryBuffer.UpdateLine(sMatch, sFormat); }
void AddQueryBuffer(const CString& sFormat, const CString& sText = "") { m_QueryBuffer.AddLine(sFormat, sText); }
void UpdateQueryBuffer(const CString& sMatch, const CString& sFormat, const CString& sText = "") { m_QueryBuffer.UpdateLine(sMatch, sFormat, sText); }
void ClearQueryBuffer() { m_QueryBuffer.Clear(); }
// !Buffers
+1 -1
View File
@@ -89,7 +89,7 @@ public:
CString& ExpandString(const CString& sStr, CString& sRet) const;
CString AddTimestamp(const CString& sStr) const;
CString& AddTimestamp(const CString& sStr, CString& sRet) const;
CString AddTimestamp(time_t tm, const CString& sStr) const;
bool Clone(const CUser& User, CString& sErrorRet, bool bCloneChans = true);
void BounceAllClients();
+1 -1
View File
@@ -22,7 +22,7 @@ public:
if (!Channel.KeepBuffer() && m_pNetwork->IsUserOnline())
return;
Channel.AddBuffer(":" + GetModNick() + "!" + GetModName() + "@znc.in PRIVMSG " + _NAMEDFMT(Channel.GetName()) + " :" + _NAMEDFMT(m_pUser->AddTimestamp(sMessage)));
Channel.AddBuffer(":" + GetModNick() + "!" + GetModName() + "@znc.in PRIVMSG " + _NAMEDFMT(Channel.GetName()) + " :{text}", sMessage);
}
virtual void OnRawMode(const CNick& OpNick, CChan& Channel, const CString& sModes, const CString& sArgs) {
+2
View File
@@ -116,6 +116,7 @@ public:
for (it = vsLines.begin(); it != vsLines.end(); ++it) {
CString sLine(*it);
sLine.Trim();
// FIXME: Deserialize other CBufLine attributes.
pChan->AddBuffer(sLine);
}
} else
@@ -151,6 +152,7 @@ public:
unsigned int uSize = Buffer.Size();
for (unsigned int uIdx = 0; uIdx < uSize; uIdx++) {
const CBufLine& Line = Buffer.GetBufLine(uIdx);
// FIXME: Serialize other CBufLine attributes.
sFile += Line.GetFormat() + "\n";
}
+2 -2
View File
@@ -172,7 +172,7 @@ public:
unsigned int uSize = m_Buffer.Size();
for (unsigned int uIdx = 0; uIdx < uSize; uIdx++) {
PutUser(m_Buffer.GetLine(uIdx, msParams));
PutUser(m_Buffer.GetLine(uIdx, *GetClient(), msParams));
}
m_Buffer.Clear();
}
@@ -293,7 +293,7 @@ private:
if (m_pNetwork->IsUserAttached()) {
m_pNetwork->PutUser(":" + WatchEntry.GetTarget() + "!watch@znc.in PRIVMSG " + m_pNetwork->GetCurNick() + " :" + sMessage);
} else {
m_Buffer.AddLine(":" + _NAMEDFMT(WatchEntry.GetTarget()) + "!watch@znc.in PRIVMSG {target} :" + _NAMEDFMT(m_pUser->AddTimestamp(sMessage)));
m_Buffer.AddLine(":" + _NAMEDFMT(WatchEntry.GetTarget()) + "!watch@znc.in PRIVMSG {target} :{text}", sMessage);
}
}
}
+30 -12
View File
@@ -8,15 +8,31 @@
#include <znc/Buffer.h>
#include <znc/znc.h>
#include <znc/Client.h>
#include <znc/User.h>
CBufLine::CBufLine(const CString& sFormat) {
CBufLine::CBufLine(const CString& sFormat, const CString& sText, time_t tm) {
m_sFormat = sFormat;
m_sText = sText;
if (tm == 0)
UpdateTime();
else
m_tm = tm;
}
CBufLine::~CBufLine() {}
CString CBufLine::GetLine(const MCString& msParams) const {
return CString::NamedFormat(m_sFormat, msParams);
CString CBufLine::GetLine(const CClient& Client, const MCString& msParams) const {
MCString msThisParams = msParams;
if (Client.HasServerTime()) {
msThisParams["text"] = m_sText;
CString sStr = CString::NamedFormat(m_sFormat, msThisParams);
return "@" + CString(m_tm) + " " + sStr;
} else {
msThisParams["text"] = Client.GetUser()->AddTimestamp(m_tm, m_sText);
return CString::NamedFormat(m_sFormat, msThisParams);
}
}
CBuffer::CBuffer(unsigned int uLineCount) {
@@ -25,7 +41,7 @@ CBuffer::CBuffer(unsigned int uLineCount) {
CBuffer::~CBuffer() {}
int CBuffer::AddLine(const CString& sFormat) {
int CBuffer::AddLine(const CString& sFormat, const CString& sText, time_t tm) {
if (!m_uLineCount) {
return 0;
}
@@ -34,37 +50,39 @@ int CBuffer::AddLine(const CString& sFormat) {
erase(begin());
}
push_back(CBufLine(sFormat));
push_back(CBufLine(sFormat, sText, tm));
return size();
}
int CBuffer::UpdateLine(const CString& sMatch, const CString& sFormat) {
int CBuffer::UpdateLine(const CString& sMatch, const CString& sFormat, const CString& sText) {
for (iterator it = begin(); it != end(); ++it) {
if (it->GetFormat().compare(0, sMatch.length(), sMatch) == 0) {
it->SetFormat(sFormat);
it->SetText(sText);
it->UpdateTime();
return size();
}
}
return AddLine(sFormat);
return AddLine(sFormat, sText);
}
int CBuffer::UpdateExactLine(const CString& sFormat) {
int CBuffer::UpdateExactLine(const CString& sFormat, const CString& sText) {
for (iterator it = begin(); it != end(); ++it) {
if (it->GetFormat() == sFormat) {
if (it->GetFormat() == sFormat && it->GetText() == sText) {
return size();
}
}
return AddLine(sFormat);
return AddLine(sFormat, sText);
}
const CBufLine& CBuffer::GetBufLine(unsigned int uIdx) const {
return (*this)[uIdx];
}
CString CBuffer::GetLine(unsigned int uIdx, const MCString& msParams) const {
return (*this)[uIdx].GetLine(msParams);
CString CBuffer::GetLine(unsigned int uIdx, const CClient& Client, const MCString& msParams) const {
return (*this)[uIdx].GetLine(Client, msParams);
}
bool CBuffer::SetLineCount(unsigned int u, bool bForce) {
+1 -1
View File
@@ -538,7 +538,7 @@ void CChan::SendBuffer(CClient* pClient) {
unsigned int uSize = m_Buffer.Size();
for (unsigned int uIdx = 0; uIdx < uSize; uIdx++) {
CString sLine = m_Buffer.GetLine(uIdx);
CString sLine = m_Buffer.GetLine(uIdx, *pClient);
NETWORKMODULECALL(OnChanBufferPlayLine(*this, *pUseClient, sLine), m_pNetwork->GetUser(), m_pNetwork, NULL, continue);
m_pNetwork->PutUser(sLine, pUseClient);
}
+3 -3
View File
@@ -239,7 +239,7 @@ void CClient::ReadLine(const CString& sData) {
CChan* pChan = m_pNetwork->FindChan(sTarget);
if ((pChan) && (pChan->KeepBuffer())) {
pChan->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " NOTICE " + _NAMEDFMT(sTarget) + " :" + _NAMEDFMT(m_pUser->AddTimestamp(sMsg)));
pChan->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " NOTICE " + _NAMEDFMT(sTarget) + " :{text}", 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(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :\001ACTION " + _NAMEDFMT(m_pUser->AddTimestamp(sMessage)) + "\001");
pChan->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :\001ACTION {text}\001", sMessage);
}
// 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(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :" + _NAMEDFMT(m_pUser->AddTimestamp(sMsg)));
pChan->AddBuffer(":" + _NAMEDFMT(GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :{text}", sMsg);
}
PutIRC("PRIVMSG " + sTarget + " :" + sMsg);
+3 -3
View File
@@ -353,7 +353,7 @@ void CIRCNetwork::ClientConnected(CClient *pClient) {
} else {
uSize = m_RawBuffer.Size();
for (uIdx = 0; uIdx < uSize; uIdx++) {
pClient->PutClient(m_RawBuffer.GetLine(uIdx, msParams));
pClient->PutClient(m_RawBuffer.GetLine(uIdx, *pClient, msParams));
}
// The assumption is that the client got this nick from the 001 reply
@@ -363,7 +363,7 @@ void CIRCNetwork::ClientConnected(CClient *pClient) {
// Send the cached MOTD
uSize = m_MotdBuffer.Size();
for (uIdx = 0; uIdx < uSize; uIdx++) {
pClient->PutClient(m_MotdBuffer.GetLine(uIdx, msParams));
pClient->PutClient(m_MotdBuffer.GetLine(uIdx, *pClient, msParams));
}
if (GetIRCSock() != NULL) {
@@ -393,7 +393,7 @@ void CIRCNetwork::ClientConnected(CClient *pClient) {
uSize = m_QueryBuffer.Size();
for (uIdx = 0; uIdx < uSize; uIdx++) {
CString sLine = m_QueryBuffer.GetLine(uIdx, msParams);
CString sLine = m_QueryBuffer.GetLine(uIdx, *pClient, msParams);
NETWORKMODULECALL(OnPrivBufferPlayLine(*pClient, sLine), m_pUser, this, NULL, continue);
pClient->PutClient(sLine);
}
+7 -7
View File
@@ -665,7 +665,7 @@ void CIRCSock::ReadLine(const CString& sData) {
CString sMsg = sRest.Token(0, true).TrimPrefix_n();
if (!m_pNetwork->IsUserOnline()) {
m_pNetwork->AddQueryBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " WALLOPS :" + _NAMEDFMT(m_pNetwork->GetUser()->AddTimestamp(sMsg)));
m_pNetwork->AddQueryBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " WALLOPS :{text}", sMsg);
}
} else if (sCmd.Equals("CAP")) {
// CAPs are supported only before authorization.
@@ -772,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(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG {target} :\001ACTION " + _NAMEDFMT(m_pNetwork->GetUser()->AddTimestamp(sMessage)) + "\001");
m_pNetwork->AddQueryBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG {target} :\001ACTION {text}\001", sMessage);
}
sMessage = "ACTION " + sMessage;
@@ -827,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(":" + _NAMEDFMT(Nick.GetNickMask()) + " NOTICE {target} :" + _NAMEDFMT(m_pNetwork->GetUser()->AddTimestamp(sMessage)));
m_pNetwork->AddQueryBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " NOTICE {target} :{text}", sMessage);
}
return false;
@@ -838,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(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG {target} :" + _NAMEDFMT(m_pNetwork->GetUser()->AddTimestamp(sMessage)));
m_pNetwork->AddQueryBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG {target} :{text}", sMessage);
}
return false;
@@ -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(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sChan) + " :\001ACTION " + _NAMEDFMT(m_pNetwork->GetUser()->AddTimestamp(sMessage)) + "\001");
pChan->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sChan) + " :\001ACTION {text}\001", sMessage);
}
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(":" + _NAMEDFMT(Nick.GetNickMask()) + " NOTICE " + _NAMEDFMT(sChan) + " :" + _NAMEDFMT(m_pNetwork->GetUser()->AddTimestamp(sMessage)));
pChan->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " NOTICE " + _NAMEDFMT(sChan) + " :{text}", 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(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sChan) + " :" + _NAMEDFMT(m_pNetwork->GetUser()->AddTimestamp(sMessage)));
pChan->AddBuffer(":" + _NAMEDFMT(Nick.GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sChan) + " :{text}", sMessage);
}
}
+5 -6
View File
@@ -502,17 +502,15 @@ CString& CUser::ExpandString(const CString& sStr, CString& sRet) const {
}
CString CUser::AddTimestamp(const CString& sStr) const {
CString sRet;
return AddTimestamp(sStr, sRet);
time_t tm;
return AddTimestamp(time(&tm), sStr);
}
CString& CUser::AddTimestamp(const CString& sStr, CString& sRet) const {
CString CUser::AddTimestamp(time_t tm, const CString& sStr) const {
char szTimestamp[1024];
time_t tm;
sRet = sStr;
CString sRet = sStr;
if (!GetTimestampFormat().empty() && (m_bAppendTimestamp || m_bPrependTimestamp)) {
time(&tm);
tm += (time_t)(m_fTimezoneOffset * 60 * 60); // offset is in hours
size_t i = strftime(szTimestamp, sizeof(szTimestamp), GetTimestampFormat().c_str(), localtime(&tm));
// If strftime returns 0, an error occured in format, or result is empty
@@ -530,6 +528,7 @@ CString& CUser::AddTimestamp(const CString& sStr, CString& sRet) const {
sRet += szTimestamp;
}
}
return sRet;
}