Coverage Report

Created: 2026-07-30 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/winpr/libwinpr/utils/wlog/ConsoleAppender.c
Line
Count
Source
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * WinPR Logger
4
 *
5
 * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
20
#include <winpr/config.h>
21
22
#include "ConsoleAppender.h"
23
#include "Message.h"
24
25
#ifdef ANDROID
26
#include <android/log.h>
27
#endif
28
29
1
#define WLOG_CONSOLE_DEFAULT 0
30
0
#define WLOG_CONSOLE_STDOUT 1
31
0
#define WLOG_CONSOLE_STDERR 2
32
0
#define WLOG_CONSOLE_DEBUG 4
33
34
typedef struct
35
{
36
  wLogAppender common;
37
38
  int outputStream;
39
} wLogConsoleAppender;
40
41
static BOOL WLog_ConsoleAppender_Open(WINPR_ATTR_UNUSED wLog* log,
42
                                      WINPR_ATTR_UNUSED wLogAppender* appender)
43
1
{
44
1
  return TRUE;
45
1
}
46
47
static BOOL WLog_ConsoleAppender_Close(WINPR_ATTR_UNUSED wLog* log,
48
                                       WINPR_ATTR_UNUSED wLogAppender* appender)
49
0
{
50
0
  return TRUE;
51
0
}
52
53
static BOOL WLog_ConsoleAppender_WriteMessage(wLog* log, wLogAppender* appender,
54
                                              const wLogMessage* cmessage)
55
2.81M
{
56
2.81M
  if (!appender)
57
0
    return FALSE;
58
59
2.81M
  wLogConsoleAppender* consoleAppender = (wLogConsoleAppender*)appender;
60
61
2.81M
  char prefix[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
62
2.81M
  WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
63
64
#ifdef _WIN32
65
  if (consoleAppender->outputStream == WLOG_CONSOLE_DEBUG)
66
  {
67
    OutputDebugStringA(prefix);
68
    OutputDebugStringA(cmessage->TextString);
69
    OutputDebugStringA("\n");
70
71
    return TRUE;
72
  }
73
#endif
74
#ifdef ANDROID
75
  android_LogPriority level;
76
  switch (cmessage->Level)
77
  {
78
    case WLOG_TRACE:
79
      level = ANDROID_LOG_VERBOSE;
80
      break;
81
    case WLOG_DEBUG:
82
      level = ANDROID_LOG_DEBUG;
83
      break;
84
    case WLOG_INFO:
85
      level = ANDROID_LOG_INFO;
86
      break;
87
    case WLOG_WARN:
88
      level = ANDROID_LOG_WARN;
89
      break;
90
    case WLOG_ERROR:
91
      level = ANDROID_LOG_ERROR;
92
      break;
93
    case WLOG_FATAL:
94
      level = ANDROID_LOG_FATAL;
95
      break;
96
    case WLOG_OFF:
97
      level = ANDROID_LOG_SILENT;
98
      break;
99
    default:
100
      level = ANDROID_LOG_FATAL;
101
      break;
102
  }
103
104
  if (level != ANDROID_LOG_SILENT)
105
    __android_log_print(level, log->Name, "%s%s", prefix, cmessage->TextString);
106
107
#else
108
2.81M
  FILE* fp = nullptr;
109
2.81M
  switch (consoleAppender->outputStream)
110
2.81M
  {
111
0
    case WLOG_CONSOLE_STDOUT:
112
0
      fp = stdout;
113
0
      break;
114
0
    case WLOG_CONSOLE_STDERR:
115
0
      fp = stderr;
116
0
      break;
117
2.81M
    default:
118
2.81M
      switch (cmessage->Level)
119
2.81M
      {
120
0
        case WLOG_TRACE:
121
0
        case WLOG_DEBUG:
122
0
        case WLOG_INFO:
123
0
          fp = stdout;
124
0
          break;
125
2.81M
        default:
126
2.81M
          fp = stderr;
127
2.81M
          break;
128
2.81M
      }
129
2.81M
      break;
130
2.81M
  }
131
132
2.81M
  if (cmessage->Level != WLOG_OFF)
133
2.81M
    (void)fprintf(fp, "%s%s\n", prefix, cmessage->TextString);
134
2.81M
#endif
135
2.81M
  return TRUE;
136
2.81M
}
137
138
static int g_DataId = 0;
139
140
static BOOL WLog_ConsoleAppender_WriteDataMessage(WINPR_ATTR_UNUSED wLog* log,
141
                                                  WINPR_ATTR_UNUSED wLogAppender* appender,
142
                                                  const wLogMessage* message)
143
0
{
144
#if defined(ANDROID)
145
  return FALSE;
146
#else
147
0
  const int DataId = g_DataId++;
148
0
  char* FullFileName = WLog_Message_GetOutputFileName(DataId, "dat");
149
150
0
  WLog_DataMessage_Write(FullFileName, message->Data, message->Length);
151
152
0
  free(FullFileName);
153
154
0
  return TRUE;
155
0
#endif
156
0
}
157
158
static int g_ImageId = 0;
159
160
static BOOL WLog_ConsoleAppender_WriteImageMessage(WINPR_ATTR_UNUSED wLog* log,
161
                                                   WINPR_ATTR_UNUSED wLogAppender* appender,
162
                                                   const wLogMessage* message)
163
0
{
164
#if defined(ANDROID)
165
  return FALSE;
166
#else
167
0
  const int ImageId = g_ImageId++;
168
0
  char* FullFileName = WLog_Message_GetOutputFileName(ImageId, "bmp");
169
170
0
  WLog_ImageMessage_Write(FullFileName, message->ImageData, message->ImageWidth,
171
0
                          message->ImageHeight, message->ImageBpp);
172
173
0
  free(FullFileName);
174
175
0
  return TRUE;
176
0
#endif
177
0
}
178
179
static int g_PacketId = 0;
180
181
static BOOL WLog_ConsoleAppender_WritePacketMessage(WINPR_ATTR_UNUSED wLog* log,
182
                                                    wLogAppender* appender,
183
                                                    const wLogMessage* message)
184
0
{
185
#if defined(ANDROID)
186
  return FALSE;
187
#else
188
0
  g_PacketId++;
189
190
0
  if (!appender->PacketMessageContext)
191
0
  {
192
0
    char* FullFileName = WLog_Message_GetOutputFileName(-1, "pcap");
193
0
    appender->PacketMessageContext = (void*)Pcap_Open(FullFileName, TRUE);
194
0
    free(FullFileName);
195
0
  }
196
197
0
  if (appender->PacketMessageContext)
198
0
    return WLog_PacketMessage_Write((wPcap*)appender->PacketMessageContext, message->PacketData,
199
0
                                    message->PacketLength, message->PacketFlags);
200
201
0
  return TRUE;
202
0
#endif
203
0
}
204
static BOOL WLog_ConsoleAppender_Set(wLogAppender* appender, const char* setting, void* value)
205
0
{
206
0
  wLogConsoleAppender* consoleAppender = (wLogConsoleAppender*)appender;
207
208
  /* Just check the value string is not empty */
209
0
  if (!value || (strnlen(value, 2) == 0))
210
0
    return FALSE;
211
212
0
  if (strcmp("outputstream", setting) != 0)
213
0
    return FALSE;
214
215
0
  if (!strcmp("stdout", value))
216
0
    consoleAppender->outputStream = WLOG_CONSOLE_STDOUT;
217
0
  else if (!strcmp("stderr", value))
218
0
    consoleAppender->outputStream = WLOG_CONSOLE_STDERR;
219
0
  else if (!strcmp("default", value))
220
0
    consoleAppender->outputStream = WLOG_CONSOLE_DEFAULT;
221
0
  else if (!strcmp("debug", value))
222
0
    consoleAppender->outputStream = WLOG_CONSOLE_DEBUG;
223
0
  else
224
0
    return FALSE;
225
226
0
  return TRUE;
227
0
}
228
229
static void WLog_ConsoleAppender_Free(wLogAppender* appender)
230
1
{
231
1
  if (appender)
232
1
  {
233
1
    if (appender->PacketMessageContext)
234
0
    {
235
0
      Pcap_Close((wPcap*)appender->PacketMessageContext);
236
0
    }
237
238
1
    free(appender);
239
1
  }
240
1
}
241
242
wLogAppender* WLog_ConsoleAppender_New(WINPR_ATTR_UNUSED wLog* log)
243
1
{
244
1
  wLogConsoleAppender* ConsoleAppender =
245
1
      (wLogConsoleAppender*)calloc(1, sizeof(wLogConsoleAppender));
246
247
1
  if (!ConsoleAppender)
248
0
    return nullptr;
249
250
1
  ConsoleAppender->common.Type = WLOG_APPENDER_CONSOLE;
251
1
  ConsoleAppender->common.Open = WLog_ConsoleAppender_Open;
252
1
  ConsoleAppender->common.Close = WLog_ConsoleAppender_Close;
253
1
  ConsoleAppender->common.WriteMessage = WLog_ConsoleAppender_WriteMessage;
254
1
  ConsoleAppender->common.WriteDataMessage = WLog_ConsoleAppender_WriteDataMessage;
255
1
  ConsoleAppender->common.WriteImageMessage = WLog_ConsoleAppender_WriteImageMessage;
256
1
  ConsoleAppender->common.WritePacketMessage = WLog_ConsoleAppender_WritePacketMessage;
257
1
  ConsoleAppender->common.Set = WLog_ConsoleAppender_Set;
258
1
  ConsoleAppender->common.Free = WLog_ConsoleAppender_Free;
259
260
1
  ConsoleAppender->outputStream = WLOG_CONSOLE_DEFAULT;
261
262
#ifdef _WIN32
263
  if (IsDebuggerPresent())
264
    ConsoleAppender->outputStream = WLOG_CONSOLE_DEBUG;
265
#endif
266
267
1
  return &ConsoleAppender->common;
268
1
}