Coverage Report

Created: 2026-08-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dcmtk/oflog/libsrc/log4judp.cc
Line
Count
Source
1
// Module:  Log4CPLUS
2
// File:    log4judpappender.cxx
3
// Created: 7/2012
4
// Author:  Siva Chandran P
5
//
6
//
7
// Copyright 2012 Siva Chandran P
8
//
9
// Licensed under the Apache License, Version 2.0 (the "License");
10
// you may not use this file except in compliance with the License.
11
// You may obtain a copy of the License at
12
//
13
//     http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software
16
// distributed under the License is distributed on an "AS IS" BASIS,
17
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
// See the License for the specific language governing permissions and
19
// limitations under the License.
20
21
#include "dcmtk/oflog/log4judp.h"
22
#include "dcmtk/oflog/layout.h"
23
#include "dcmtk/oflog/streams.h"
24
#include "dcmtk/oflog/logmacro.h"
25
#include "dcmtk/oflog/helpers/loglog.h"
26
#include "dcmtk/oflog/helpers/property.h"
27
#include "dcmtk/oflog/spi/logevent.h"
28
#include "dcmtk/oflog/internal/internal.h"
29
#include "dcmtk/oflog/thread/syncpub.h"
30
#include <iomanip>
31
#include <cstring>
32
#if defined (DCMTK_OFLOG_UNICODE)
33
#include <cwctype>
34
#else
35
#include <cctype>
36
#endif
37
38
39
namespace dcmtk
40
{
41
namespace log4cplus
42
{
43
44
namespace
45
{
46
47
48
static inline bool
49
is_control (tchar ch)
50
0
{
51
#if defined (DCMTK_OFLOG_UNICODE)
52
    return !! STD_NAMESPACE iswcntrl (STD_NAMESPACE char_traits<tchar>::to_int_type (ch));
53
#else
54
0
    return !! STD_NAMESPACE iscntrl (STD_NAMESPACE char_traits<tchar>::to_int_type (ch));
55
0
#endif
56
0
}
57
58
59
//! Outputs str with reserved XML characters escaped.
60
static
61
void
62
output_xml_escaped (tostream & os, tstring const & str)
63
0
{
64
0
    for (tstring::const_iterator it = str.begin (); it != str.end (); ++it)
65
0
    {
66
0
        tchar const & ch = *it;
67
0
        switch (ch)
68
0
        {
69
0
        case DCMTK_LOG4CPLUS_TEXT ('<'):
70
0
            os << DCMTK_LOG4CPLUS_TEXT ("&lt;");
71
0
            break;
72
73
0
        case DCMTK_LOG4CPLUS_TEXT ('>'):
74
0
            os << DCMTK_LOG4CPLUS_TEXT ("&gt;");
75
0
            break;
76
77
0
        case DCMTK_LOG4CPLUS_TEXT ('&'):
78
0
            os << DCMTK_LOG4CPLUS_TEXT ("&amp;");
79
0
            break;
80
81
0
        case DCMTK_LOG4CPLUS_TEXT ('\''):
82
0
            os << DCMTK_LOG4CPLUS_TEXT ("&apos;");
83
0
            break;
84
85
0
        case DCMTK_LOG4CPLUS_TEXT ('"'):
86
0
            os << DCMTK_LOG4CPLUS_TEXT ("&quot;");
87
0
            break;
88
89
0
        default:
90
0
            if (is_control (ch))
91
0
            {
92
0
                tchar const prev_fill = os.fill ();
93
0
                STD_NAMESPACE ios_base::fmtflags const prev_flags = os.flags ();
94
0
                os.flags (STD_NAMESPACE ios_base::hex | STD_NAMESPACE ios_base::right);
95
0
                os.fill (DCMTK_LOG4CPLUS_TEXT ('0'));
96
97
0
                os << STD_NAMESPACE setw (0) << DCMTK_LOG4CPLUS_TEXT ("&#x")
98
0
                    << STD_NAMESPACE setw (2) << STD_NAMESPACE char_traits<tchar>::to_int_type (ch)
99
0
                    << STD_NAMESPACE setw (0) << DCMTK_LOG4CPLUS_TEXT (";");
100
101
0
                os.fill (prev_fill);
102
0
                os.flags (prev_flags);
103
0
            }
104
0
            else
105
0
                os.put (ch);
106
0
        }
107
0
    }
108
0
}
109
110
111
//! Helper manipulator like class for escaped XML output.
112
struct outputXMLEscaped
113
{
114
    outputXMLEscaped (tstring const & s)
115
0
        : str (s)
116
0
    { }
117
118
    tstring const & str;
119
};
120
121
122
//! Overload stream insertion for outputXMLEscaped.
123
static
124
tostream &
125
operator << (tostream & os, outputXMLEscaped const & x)
126
0
{
127
0
    output_xml_escaped (os, x.str);
128
0
    return os;
129
0
}
130
131
132
} // namespace
133
134
135
//////////////////////////////////////////////////////////////////////////////
136
// Log4jUdpAppender ctors and dtor
137
//////////////////////////////////////////////////////////////////////////////
138
139
Log4jUdpAppender::Log4jUdpAppender(const tstring& host_, int port_)
140
0
    : socket()
141
0
    , host(host_)
142
0
    , port(port_)
143
0
{
144
0
    layout.reset (new PatternLayout (DCMTK_LOG4CPLUS_TEXT ("%m")));
145
0
    openSocket();
146
0
}
Unexecuted instantiation: dcmtk::log4cplus::Log4jUdpAppender::Log4jUdpAppender(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int)
Unexecuted instantiation: dcmtk::log4cplus::Log4jUdpAppender::Log4jUdpAppender(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int)
147
148
149
150
Log4jUdpAppender::Log4jUdpAppender(const helpers::Properties & properties)
151
0
    : Appender(properties)
152
0
    , socket()
153
0
    , host()
154
0
    , port(5000)
155
0
{
156
0
    host = properties.getProperty( DCMTK_LOG4CPLUS_TEXT("host"),
157
0
        DCMTK_LOG4CPLUS_TEXT ("localhost") );
158
0
    properties.getInt (port, DCMTK_LOG4CPLUS_TEXT ("port"));
159
160
0
    openSocket();
161
0
}
Unexecuted instantiation: dcmtk::log4cplus::Log4jUdpAppender::Log4jUdpAppender(dcmtk::log4cplus::helpers::Properties const&)
Unexecuted instantiation: dcmtk::log4cplus::Log4jUdpAppender::Log4jUdpAppender(dcmtk::log4cplus::helpers::Properties const&)
162
163
164
165
Log4jUdpAppender::~Log4jUdpAppender()
166
0
{
167
0
    destructorImpl();
168
0
}
169
170
171
172
//////////////////////////////////////////////////////////////////////////////
173
// Log4jUdpAppender public methods
174
//////////////////////////////////////////////////////////////////////////////
175
176
void
177
Log4jUdpAppender::close()
178
0
{
179
0
    helpers::getLogLog().debug(
180
0
        DCMTK_LOG4CPLUS_TEXT("Entering Log4jUdpAppender::close()..."));
181
182
0
    socket.close();
183
0
    closed = true;
184
0
}
185
186
187
188
//////////////////////////////////////////////////////////////////////////////
189
// Log4jUdpAppender protected methods
190
//////////////////////////////////////////////////////////////////////////////
191
192
void
193
Log4jUdpAppender::openSocket()
194
0
{
195
0
    if(!socket.isOpen()) {
196
0
        socket = helpers::Socket(host, OFstatic_cast(unsigned short, port), true);
197
0
    }
198
0
}
199
200
void
201
Log4jUdpAppender::append(const spi::InternalLoggingEvent& event)
202
0
{
203
0
    if(!socket.isOpen()) {
204
0
        openSocket();
205
0
        if(!socket.isOpen()) {
206
0
            helpers::getLogLog().error(
207
0
                DCMTK_LOG4CPLUS_TEXT("Log4jUdpAppender::append()- Cannot connect to server"));
208
0
            return;
209
0
        }
210
0
    }
211
212
0
    tstring & str = formatEvent (event);
213
214
0
    internal::appender_sratch_pad & appender_sp
215
0
        = internal::get_appender_sp ();
216
0
    tostringstream & buffer = appender_sp.oss;
217
0
    detail::clear_tostringstream (buffer);
218
219
0
    buffer << DCMTK_LOG4CPLUS_TEXT("<log4j:event logger=\"")
220
0
           << outputXMLEscaped (event.getLoggerName())
221
0
           << DCMTK_LOG4CPLUS_TEXT("\" level=\"")
222
           // TODO: Some escaping of special characters is needed here.
223
0
           << outputXMLEscaped (getLogLevelManager().toString(event.getLogLevel()))
224
0
           << DCMTK_LOG4CPLUS_TEXT("\" timestamp=\"")
225
0
           << event.getTimestamp().getFormattedTime(DCMTK_LOG4CPLUS_TEXT("%s%q"))
226
0
           << DCMTK_LOG4CPLUS_TEXT("\" thread=\"") << event.getThread()
227
0
           << DCMTK_LOG4CPLUS_TEXT("\">")
228
229
0
           << DCMTK_LOG4CPLUS_TEXT("<log4j:message>")
230
           // TODO: Some escaping of special characters is needed here.
231
0
           << outputXMLEscaped (str)
232
0
           << DCMTK_LOG4CPLUS_TEXT("</log4j:message>")
233
234
0
           << DCMTK_LOG4CPLUS_TEXT("<log4j:NDC>")
235
           // TODO: Some escaping of special characters is needed here.
236
0
           << outputXMLEscaped (event.getNDC())
237
0
           << DCMTK_LOG4CPLUS_TEXT("</log4j:NDC>")
238
239
0
           << DCMTK_LOG4CPLUS_TEXT("<log4j:locationInfo class=\"\" file=\"")
240
           // TODO: Some escaping of special characters is needed here.
241
0
           << outputXMLEscaped (event.getFile())
242
0
           << DCMTK_LOG4CPLUS_TEXT("\" method=\"")
243
0
           << outputXMLEscaped (event.getFunction())
244
0
           << DCMTK_LOG4CPLUS_TEXT("\" line=\"")
245
0
           << event.getLine()
246
0
           << DCMTK_LOG4CPLUS_TEXT("\"/>")
247
0
           << DCMTK_LOG4CPLUS_TEXT("</log4j:event>");
248
249
0
    DCMTK_LOG4CPLUS_TSTRING_TO_STRING (buffer.str ()).swap (appender_sp.chstr);
250
251
0
    bool ret = socket.write(appender_sp.chstr);
252
0
    if (!ret)
253
0
    {
254
0
        helpers::getLogLog().error(
255
0
            DCMTK_LOG4CPLUS_TEXT(
256
0
                "Log4jUdpAppender::append()- Cannot write to server"));
257
0
    }
258
0
}
259
260
} // namespace log4cplus
261
} // end namespace dcmtk