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 "FileAppender.h"
25 #include "Message.h"
26
27 #include <winpr/crt.h>
28 #include <winpr/environment.h>
29 #include <winpr/file.h>
30 #include <winpr/path.h>
31
32 struct _wLogFileAppender
33 {
34 WLOG_APPENDER_COMMON();
35
36 char* FileName;
37 char* FilePath;
38 char* FullFileName;
39 FILE* FileDescriptor;
40 };
41 typedef struct _wLogFileAppender wLogFileAppender;
42
WLog_FileAppender_SetOutputFileName(wLogFileAppender * appender,const char * filename)43 static BOOL WLog_FileAppender_SetOutputFileName(wLogFileAppender* appender, const char* filename)
44 {
45 appender->FileName = _strdup(filename);
46
47 if (!appender->FileName)
48 return FALSE;
49
50 return TRUE;
51 }
52
WLog_FileAppender_SetOutputFilePath(wLogFileAppender * appender,const char * filepath)53 static BOOL WLog_FileAppender_SetOutputFilePath(wLogFileAppender* appender, const char* filepath)
54 {
55 appender->FilePath = _strdup(filepath);
56
57 if (!appender->FilePath)
58 return FALSE;
59
60 return TRUE;
61 }
62
WLog_FileAppender_Open(wLog * log,wLogAppender * appender)63 static BOOL WLog_FileAppender_Open(wLog* log, wLogAppender* appender)
64 {
65 wLogFileAppender* fileAppender;
66
67 if (!log || !appender)
68 return FALSE;
69
70 fileAppender = (wLogFileAppender*)appender;
71
72 if (!fileAppender->FilePath)
73 {
74 fileAppender->FilePath = GetKnownSubPath(KNOWN_PATH_TEMP, "wlog");
75
76 if (!fileAppender->FilePath)
77 return FALSE;
78 }
79
80 if (!fileAppender->FileName)
81 {
82 fileAppender->FileName = (char*)malloc(MAX_PATH);
83
84 if (!fileAppender->FileName)
85 return FALSE;
86
87 sprintf_s(fileAppender->FileName, MAX_PATH, "%" PRIu32 ".log", GetCurrentProcessId());
88 }
89
90 if (!fileAppender->FullFileName)
91 {
92 fileAppender->FullFileName =
93 GetCombinedPath(fileAppender->FilePath, fileAppender->FileName);
94
95 if (!fileAppender->FullFileName)
96 return FALSE;
97 }
98
99 if (!winpr_PathFileExists(fileAppender->FilePath))
100 {
101 if (!winpr_PathMakePath(fileAppender->FilePath, 0))
102 return FALSE;
103
104 UnixChangeFileMode(fileAppender->FilePath, 0xFFFF);
105 }
106
107 fileAppender->FileDescriptor = winpr_fopen(fileAppender->FullFileName, "a+");
108
109 if (!fileAppender->FileDescriptor)
110 return FALSE;
111
112 return TRUE;
113 }
114
WLog_FileAppender_Close(wLog * log,wLogAppender * appender)115 static BOOL WLog_FileAppender_Close(wLog* log, wLogAppender* appender)
116 {
117 wLogFileAppender* fileAppender;
118
119 if (!log || !appender)
120 return FALSE;
121
122 fileAppender = (wLogFileAppender*)appender;
123
124 if (!fileAppender->FileDescriptor)
125 return TRUE;
126
127 fclose(fileAppender->FileDescriptor);
128 fileAppender->FileDescriptor = NULL;
129 return TRUE;
130 }
131
WLog_FileAppender_WriteMessage(wLog * log,wLogAppender * appender,wLogMessage * message)132 static BOOL WLog_FileAppender_WriteMessage(wLog* log, wLogAppender* appender, wLogMessage* message)
133 {
134 FILE* fp;
135 char prefix[WLOG_MAX_PREFIX_SIZE];
136 wLogFileAppender* fileAppender;
137
138 if (!log || !appender || !message)
139 return FALSE;
140
141 fileAppender = (wLogFileAppender*)appender;
142 fp = fileAppender->FileDescriptor;
143
144 if (!fp)
145 return FALSE;
146
147 message->PrefixString = prefix;
148 WLog_Layout_GetMessagePrefix(log, appender->Layout, message);
149 fprintf(fp, "%s%s\n", message->PrefixString, message->TextString);
150 fflush(fp); /* slow! */
151 return TRUE;
152 }
153
154 static int g_DataId = 0;
155
WLog_FileAppender_WriteDataMessage(wLog * log,wLogAppender * appender,wLogMessage * message)156 static BOOL WLog_FileAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
157 wLogMessage* message)
158 {
159 int DataId;
160 char* FullFileName;
161
162 if (!log || !appender || !message)
163 return FALSE;
164
165 DataId = g_DataId++;
166 FullFileName = WLog_Message_GetOutputFileName(DataId, "dat");
167 WLog_DataMessage_Write(FullFileName, message->Data, message->Length);
168 free(FullFileName);
169 return TRUE;
170 }
171
172 static int g_ImageId = 0;
173
WLog_FileAppender_WriteImageMessage(wLog * log,wLogAppender * appender,wLogMessage * message)174 static BOOL WLog_FileAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
175 wLogMessage* message)
176 {
177 int ImageId;
178 char* FullFileName;
179
180 if (!log || !appender || !message)
181 return FALSE;
182
183 ImageId = g_ImageId++;
184 FullFileName = WLog_Message_GetOutputFileName(ImageId, "bmp");
185 WLog_ImageMessage_Write(FullFileName, message->ImageData, message->ImageWidth,
186 message->ImageHeight, message->ImageBpp);
187 free(FullFileName);
188 return TRUE;
189 }
190
WLog_FileAppender_Set(wLogAppender * appender,const char * setting,void * value)191 static BOOL WLog_FileAppender_Set(wLogAppender* appender, const char* setting, void* value)
192 {
193 wLogFileAppender* fileAppender = (wLogFileAppender*)appender;
194
195 /* Just check the value string is not empty */
196 if (!value || (strnlen(value, 2) == 0))
197 return FALSE;
198
199 if (!strcmp("outputfilename", setting))
200 return WLog_FileAppender_SetOutputFileName(fileAppender, (const char*)value);
201 else if (!strcmp("outputfilepath", setting))
202 return WLog_FileAppender_SetOutputFilePath(fileAppender, (const char*)value);
203 else
204 return FALSE;
205
206 return TRUE;
207 }
208
WLog_FileAppender_Free(wLogAppender * appender)209 static void WLog_FileAppender_Free(wLogAppender* appender)
210 {
211 wLogFileAppender* fileAppender = NULL;
212
213 if (appender)
214 {
215 fileAppender = (wLogFileAppender*)appender;
216 free(fileAppender->FileName);
217 free(fileAppender->FilePath);
218 free(fileAppender->FullFileName);
219 free(fileAppender);
220 }
221 }
222
WLog_FileAppender_New(wLog * log)223 wLogAppender* WLog_FileAppender_New(wLog* log)
224 {
225 LPSTR env;
226 LPCSTR name;
227 DWORD nSize;
228 wLogFileAppender* FileAppender;
229 FileAppender = (wLogFileAppender*)calloc(1, sizeof(wLogFileAppender));
230
231 if (!FileAppender)
232 return NULL;
233
234 FileAppender->Type = WLOG_APPENDER_FILE;
235 FileAppender->Open = WLog_FileAppender_Open;
236 FileAppender->Close = WLog_FileAppender_Close;
237 FileAppender->WriteMessage = WLog_FileAppender_WriteMessage;
238 FileAppender->WriteDataMessage = WLog_FileAppender_WriteDataMessage;
239 FileAppender->WriteImageMessage = WLog_FileAppender_WriteImageMessage;
240 FileAppender->Free = WLog_FileAppender_Free;
241 FileAppender->Set = WLog_FileAppender_Set;
242 name = "WLOG_FILEAPPENDER_OUTPUT_FILE_PATH";
243 nSize = GetEnvironmentVariableA(name, NULL, 0);
244
245 if (nSize)
246 {
247 BOOL status;
248 env = (LPSTR)malloc(nSize);
249
250 if (!env)
251 goto error_free;
252
253 if (GetEnvironmentVariableA(name, env, nSize) != nSize - 1)
254 {
255 free(env);
256 goto error_free;
257 }
258
259 status = WLog_FileAppender_SetOutputFilePath(FileAppender, env);
260 free(env);
261
262 if (!status)
263 goto error_free;
264 }
265
266 name = "WLOG_FILEAPPENDER_OUTPUT_FILE_NAME";
267 nSize = GetEnvironmentVariableA(name, NULL, 0);
268
269 if (nSize)
270 {
271 BOOL status = FALSE;
272 env = (LPSTR)malloc(nSize);
273
274 if (!env)
275 goto error_output_file_name;
276
277 if (GetEnvironmentVariableA(name, env, nSize) == nSize - 1)
278 status = WLog_FileAppender_SetOutputFileName(FileAppender, env);
279 free(env);
280
281 if (!status)
282 goto error_output_file_name;
283 }
284
285 return (wLogAppender*)FileAppender;
286 error_output_file_name:
287 free(FileAppender->FilePath);
288 error_free:
289 free(FileAppender);
290 return NULL;
291 }
292