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