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 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "ConsoleAppender.h"
25 #include "Message.h"
26
27 #ifdef ANDROID
28 #include <android/log.h>
29 #endif
30
31 #define WLOG_CONSOLE_DEFAULT 0
32 #define WLOG_CONSOLE_STDOUT 1
33 #define WLOG_CONSOLE_STDERR 2
34 #define WLOG_CONSOLE_DEBUG 4
35
36 struct _wLogConsoleAppender
37 {
38 WLOG_APPENDER_COMMON();
39
40 int outputStream;
41 };
42 typedef struct _wLogConsoleAppender wLogConsoleAppender;
43
WLog_ConsoleAppender_Open(wLog * log,wLogAppender * appender)44 static BOOL WLog_ConsoleAppender_Open(wLog* log, wLogAppender* appender)
45 {
46 return TRUE;
47 }
48
WLog_ConsoleAppender_Close(wLog * log,wLogAppender * appender)49 static BOOL WLog_ConsoleAppender_Close(wLog* log, wLogAppender* appender)
50 {
51 return TRUE;
52 }
53
WLog_ConsoleAppender_WriteMessage(wLog * log,wLogAppender * appender,wLogMessage * message)54 static BOOL WLog_ConsoleAppender_WriteMessage(wLog* log, wLogAppender* appender,
55 wLogMessage* message)
56 {
57 FILE* fp;
58 char prefix[WLOG_MAX_PREFIX_SIZE];
59 wLogConsoleAppender* consoleAppender;
60 if (!appender)
61 return FALSE;
62
63 consoleAppender = (wLogConsoleAppender*)appender;
64
65 message->PrefixString = prefix;
66 WLog_Layout_GetMessagePrefix(log, appender->Layout, message);
67
68 #ifdef _WIN32
69 if (consoleAppender->outputStream == WLOG_CONSOLE_DEBUG)
70 {
71 char MessageString[4096];
72
73 sprintf_s(MessageString, sizeof(MessageString), "%s%s\n", message->PrefixString,
74 message->TextString);
75
76 OutputDebugStringA(MessageString);
77
78 return TRUE;
79 }
80 #endif
81 #ifdef ANDROID
82 (void)fp;
83 android_LogPriority level;
84 switch (message->Level)
85 {
86 case WLOG_TRACE:
87 level = ANDROID_LOG_VERBOSE;
88 break;
89 case WLOG_DEBUG:
90 level = ANDROID_LOG_DEBUG;
91 break;
92 case WLOG_INFO:
93 level = ANDROID_LOG_INFO;
94 break;
95 case WLOG_WARN:
96 level = ANDROID_LOG_WARN;
97 break;
98 case WLOG_ERROR:
99 level = ANDROID_LOG_ERROR;
100 break;
101 case WLOG_FATAL:
102 level = ANDROID_LOG_FATAL;
103 break;
104 case WLOG_OFF:
105 level = ANDROID_LOG_SILENT;
106 break;
107 default:
108 level = ANDROID_LOG_FATAL;
109 break;
110 }
111
112 if (level != ANDROID_LOG_SILENT)
113 __android_log_print(level, log->Name, "%s%s", message->PrefixString, message->TextString);
114
115 #else
116 switch (consoleAppender->outputStream)
117 {
118 case WLOG_CONSOLE_STDOUT:
119 fp = stdout;
120 break;
121 case WLOG_CONSOLE_STDERR:
122 fp = stderr;
123 break;
124 default:
125 switch (message->Level)
126 {
127 case WLOG_TRACE:
128 case WLOG_DEBUG:
129 case WLOG_INFO:
130 fp = stdout;
131 break;
132 default:
133 fp = stderr;
134 break;
135 }
136 break;
137 }
138
139 if (message->Level != WLOG_OFF)
140 fprintf(fp, "%s%s\n", message->PrefixString, message->TextString);
141 #endif
142 return TRUE;
143 }
144
145 static int g_DataId = 0;
146
WLog_ConsoleAppender_WriteDataMessage(wLog * log,wLogAppender * appender,wLogMessage * message)147 static BOOL WLog_ConsoleAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
148 wLogMessage* message)
149 {
150 #if defined(ANDROID)
151 return FALSE;
152 #else
153 int DataId;
154 char* FullFileName;
155
156 DataId = g_DataId++;
157 FullFileName = WLog_Message_GetOutputFileName(DataId, "dat");
158
159 WLog_DataMessage_Write(FullFileName, message->Data, message->Length);
160
161 free(FullFileName);
162
163 return TRUE;
164 #endif
165 }
166
167 static int g_ImageId = 0;
168
WLog_ConsoleAppender_WriteImageMessage(wLog * log,wLogAppender * appender,wLogMessage * message)169 static BOOL WLog_ConsoleAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
170 wLogMessage* message)
171 {
172 #if defined(ANDROID)
173 return FALSE;
174 #else
175 int ImageId;
176 char* FullFileName;
177
178 ImageId = g_ImageId++;
179 FullFileName = WLog_Message_GetOutputFileName(ImageId, "bmp");
180
181 WLog_ImageMessage_Write(FullFileName, message->ImageData, message->ImageWidth,
182 message->ImageHeight, message->ImageBpp);
183
184 free(FullFileName);
185
186 return TRUE;
187 #endif
188 }
189
190 static int g_PacketId = 0;
191
WLog_ConsoleAppender_WritePacketMessage(wLog * log,wLogAppender * appender,wLogMessage * message)192 static BOOL WLog_ConsoleAppender_WritePacketMessage(wLog* log, wLogAppender* appender,
193 wLogMessage* message)
194 {
195 #if defined(ANDROID)
196 return FALSE;
197 #else
198 char* FullFileName;
199
200 g_PacketId++;
201
202 if (!appender->PacketMessageContext)
203 {
204 FullFileName = WLog_Message_GetOutputFileName(-1, "pcap");
205 appender->PacketMessageContext = (void*)Pcap_Open(FullFileName, TRUE);
206 free(FullFileName);
207 }
208
209 if (appender->PacketMessageContext)
210 return WLog_PacketMessage_Write((wPcap*)appender->PacketMessageContext, message->PacketData,
211 message->PacketLength, message->PacketFlags);
212
213 return TRUE;
214 #endif
215 }
WLog_ConsoleAppender_Set(wLogAppender * appender,const char * setting,void * value)216 static BOOL WLog_ConsoleAppender_Set(wLogAppender* appender, const char* setting, void* value)
217 {
218 wLogConsoleAppender* consoleAppender = (wLogConsoleAppender*)appender;
219
220 /* Just check the value string is not empty */
221 if (!value || (strnlen(value, 2) == 0))
222 return FALSE;
223
224 if (strcmp("outputstream", setting))
225 return FALSE;
226
227 if (!strcmp("stdout", value))
228 consoleAppender->outputStream = WLOG_CONSOLE_STDOUT;
229 else if (!strcmp("stderr", value))
230 consoleAppender->outputStream = WLOG_CONSOLE_STDERR;
231 else if (!strcmp("default", value))
232 consoleAppender->outputStream = WLOG_CONSOLE_DEFAULT;
233 else if (!strcmp("debug", value))
234 consoleAppender->outputStream = WLOG_CONSOLE_DEBUG;
235 else
236 return FALSE;
237
238 return TRUE;
239 }
240
WLog_ConsoleAppender_Free(wLogAppender * appender)241 static void WLog_ConsoleAppender_Free(wLogAppender* appender)
242 {
243 if (appender)
244 {
245 if (appender->PacketMessageContext)
246 {
247 Pcap_Close((wPcap*)appender->PacketMessageContext);
248 }
249
250 free(appender);
251 }
252 }
253
WLog_ConsoleAppender_New(wLog * log)254 wLogAppender* WLog_ConsoleAppender_New(wLog* log)
255 {
256 wLogConsoleAppender* ConsoleAppender;
257
258 ConsoleAppender = (wLogConsoleAppender*)calloc(1, sizeof(wLogConsoleAppender));
259
260 if (!ConsoleAppender)
261 return NULL;
262
263 ConsoleAppender->Type = WLOG_APPENDER_CONSOLE;
264
265 ConsoleAppender->Open = WLog_ConsoleAppender_Open;
266 ConsoleAppender->Close = WLog_ConsoleAppender_Close;
267 ConsoleAppender->WriteMessage = WLog_ConsoleAppender_WriteMessage;
268 ConsoleAppender->WriteDataMessage = WLog_ConsoleAppender_WriteDataMessage;
269 ConsoleAppender->WriteImageMessage = WLog_ConsoleAppender_WriteImageMessage;
270 ConsoleAppender->WritePacketMessage = WLog_ConsoleAppender_WritePacketMessage;
271 ConsoleAppender->Set = WLog_ConsoleAppender_Set;
272 ConsoleAppender->Free = WLog_ConsoleAppender_Free;
273
274 ConsoleAppender->outputStream = WLOG_CONSOLE_DEFAULT;
275
276 #ifdef _WIN32
277 if (IsDebuggerPresent())
278 ConsoleAppender->outputStream = WLOG_CONSOLE_DEBUG;
279 #endif
280
281 return (wLogAppender*)ConsoleAppender;
282 }
283