Coverage Report

Created: 2026-01-10 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/znc/src/Buffer.cpp
Line
Count
Source
1
/*
2
 * Copyright (C) 2004-2026 ZNC, see the NOTICE file for details.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#include <znc/Buffer.h>
18
#include <znc/znc.h>
19
#include <znc/User.h>
20
#include <time.h>
21
22
CBufLine::CBufLine(const CMessage& Format, const CString& sText)
23
0
    : m_Message(Format), m_sText(sText) {}
24
25
CBufLine::CBufLine(const CString& sFormat, const CString& sText,
26
                   const timeval* ts, const MCString& mssTags)
27
0
    : m_sText(sText) {
28
0
    m_Message.Parse(sFormat);
29
0
    m_Message.SetTags(mssTags);
30
31
0
    if (ts == nullptr)
32
0
        UpdateTime();
33
0
    else
34
0
        m_Message.SetTime(*ts);
35
0
}
36
37
0
CBufLine::~CBufLine() {}
38
39
0
void CBufLine::UpdateTime() {
40
0
    m_Message.SetTime(CUtils::GetTime());
41
0
}
42
43
CMessage CBufLine::ToMessage(const CClient& Client,
44
0
                             const MCString& mssParams) const {
45
0
    CMessage Line = m_Message;
46
47
0
    CString sSender = Line.GetNick().GetNickMask();
48
0
    Line.SetNick(CNick(CString::NamedFormat(sSender, mssParams)));
49
50
0
    MCString mssThisParams = mssParams;
51
0
    if (Client.HasServerTime()) {
52
0
        mssThisParams["text"] = m_sText;
53
0
    } else {
54
0
        mssThisParams["text"] =
55
0
            Client.GetUser()->AddTimestamp(Line.GetTime(), m_sText);
56
0
    }
57
58
    // make a copy of params, because the following loop modifies the original
59
0
    VCString vsParams = Line.GetParams();
60
0
    for (unsigned int uIdx = 0; uIdx < vsParams.size(); ++uIdx) {
61
0
        Line.SetParam(uIdx,
62
0
                      CString::NamedFormat(vsParams[uIdx], mssThisParams));
63
0
    }
64
65
0
    return Line;
66
0
}
67
68
CString CBufLine::GetLine(const CClient& Client,
69
0
                          const MCString& mssParams) const {
70
0
    CMessage Line = ToMessage(Client, mssParams);
71
72
    // Note: Discard all tags (except the time tag, conditionally) to
73
    // keep the same behavior as ZNC versions 1.6 and earlier had. See
74
    // CClient::PutClient(CMessage) documentation for more details.
75
0
    Line.SetTags(MCString::EmptyMap);
76
77
0
    if (Client.HasServerTime()) {
78
0
        CString sTime = m_Message.GetTag("time");
79
0
        if (sTime.empty()) {
80
0
            sTime = CUtils::FormatServerTime(m_Message.GetTime());
81
0
        }
82
0
        Line.SetTag("time", sTime);
83
0
    }
84
85
0
    return Line.ToString();
86
0
}
87
88
0
CBuffer::CBuffer(unsigned int uLineCount) : m_uLineCount(uLineCount) {}
89
90
0
CBuffer::~CBuffer() {}
91
92
CBuffer::size_type CBuffer::AddLine(const CMessage& Format,
93
0
                                    const CString& sText) {
94
0
    if (!m_uLineCount) {
95
0
        return 0;
96
0
    }
97
98
0
    while (size() >= m_uLineCount) {
99
0
        erase(begin());
100
0
    }
101
102
0
    push_back(CBufLine(Format, sText));
103
0
    return size();
104
0
}
105
106
CBuffer::size_type CBuffer::UpdateLine(const CString& sCommand,
107
                                       const CMessage& Format,
108
0
                                       const CString& sText) {
109
0
    for (CBufLine& Line : *this) {
110
0
        if (Line.GetCommand().Equals(sCommand)) {
111
0
            Line = CBufLine(Format, sText);
112
0
            return size();
113
0
        }
114
0
    }
115
116
0
    return AddLine(Format, sText);
117
0
}
118
119
CBuffer::size_type CBuffer::UpdateExactLine(const CMessage& Format,
120
0
                                            const CString& sText) {
121
0
    for (CBufLine& Line : *this) {
122
0
        if (Line.Equals(Format)) {
123
0
            return size();
124
0
        }
125
0
    }
126
127
0
    return AddLine(Format, sText);
128
0
}
129
130
CBuffer::size_type CBuffer::AddLine(const CString& sFormat,
131
                                    const CString& sText, const timeval* ts,
132
0
                                    const MCString& mssTags) {
133
0
    CMessage Message(sFormat);
134
0
    if (ts) {
135
0
        Message.SetTime(*ts);
136
0
    }
137
0
    Message.SetTags(mssTags);
138
0
    return AddLine(Message, sText);
139
0
}
140
141
CBuffer::size_type CBuffer::UpdateLine(const CString& sMatch,
142
                                       const CString& sFormat,
143
0
                                       const CString& sText) {
144
0
    return UpdateLine(CMessage(sMatch).GetCommand(), CMessage(sFormat), sText);
145
0
}
146
147
CBuffer::size_type CBuffer::UpdateExactLine(const CString& sFormat,
148
0
                                            const CString& sText) {
149
0
    return UpdateExactLine(CMessage(sFormat, sText));
150
0
}
151
152
0
const CBufLine& CBuffer::GetBufLine(unsigned int uIdx) const {
153
0
    return (*this)[uIdx];
154
0
}
155
156
CString CBuffer::GetLine(size_type uIdx, const CClient& Client,
157
0
                         const MCString& msParams) const {
158
0
    return (*this)[uIdx].GetLine(Client, msParams);
159
0
}
160
161
0
bool CBuffer::SetLineCount(unsigned int u, bool bForce) {
162
0
    if (!bForce && u > CZNC::Get().GetMaxBufferSize()) {
163
0
        return false;
164
0
    }
165
166
0
    m_uLineCount = u;
167
168
    // We may need to shrink the buffer if the allowed size got smaller
169
0
    while (size() > m_uLineCount) {
170
0
        erase(begin());
171
0
    }
172
173
0
    return true;
174
0
}