fixed incorrect export records for events
[public/netxms.git] / src / server / core / events.cpp
CommitLineData
5039dede
AK
1/*
2** NetXMS - Network Management System
50963ced 3** Copyright (C) 2003-2016 Victor Kirhenshtein
5039dede
AK
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** File: events.cpp
20**
21**/
22
23#include "nxcore.h"
24
a6cc48cc
VK
25/**
26 * Global variables
27 */
5039dede
AK
28Queue *g_pEventQueue = NULL;
29EventPolicy *g_pEventPolicy = NULL;
5039dede 30
a6cc48cc
VK
31/**
32 * Static data
33 */
50963ced 34static RefCountHashMap<UINT32, EventTemplate> m_eventTemplates(true);
5039dede
AK
35static RWLOCK m_rwlockTemplateAccess;
36
50963ced
VK
37/**
38 * Create event template from DB record
39 */
40EventTemplate::EventTemplate(DB_RESULT hResult, int row)
41{
42 m_code = DBGetFieldULong(hResult, row, 0);
43 m_severity = DBGetFieldLong(hResult, row, 1);
44 m_flags = DBGetFieldLong(hResult, row, 2);
45 m_messageTemplate = DBGetField(hResult, row, 3, NULL, 0);
46 m_description = DBGetField(hResult, row, 4, NULL, 0);
47 DBGetField(hResult, row, 5, m_name, MAX_EVENT_NAME);
48}
49
50/**
51 * Event template destructor
52 */
53EventTemplate::~EventTemplate()
54{
55 free(m_messageTemplate);
56 free(m_description);
57}
58
a6cc48cc
VK
59/**
60 * Default constructor for event
61 */
5039dede
AK
62Event::Event()
63{
65ce7452 64 m_id = 0;
c42b4551 65 m_name[0] = 0;
65ce7452
VK
66 m_rootId = 0;
67 m_code = 0;
ad13c0e2 68 m_severity = SEVERITY_NORMAL;
65ce7452
VK
69 m_sourceId = 0;
70 m_dciId = 0;
71 m_flags = 0;
72 m_messageText = NULL;
73 m_messageTemplate = NULL;
74 m_timeStamp = 0;
75 m_userTag = NULL;
76 m_customMessage = NULL;
ed806a1a 77 m_parameters.setOwner(true);
5039dede
AK
78}
79
816852b2
VK
80/**
81 * Copy constructor for event
82 */
65ce7452 83Event::Event(const Event *src)
816852b2 84{
65ce7452 85 m_id = src->m_id;
c42b4551 86 _tcscpy(m_name, src->m_name);
65ce7452
VK
87 m_rootId = src->m_rootId;
88 m_code = src->m_code;
ad13c0e2 89 m_severity = src->m_severity;
65ce7452
VK
90 m_sourceId = src->m_sourceId;
91 m_dciId = src->m_dciId;
92 m_flags = src->m_flags;
93 m_messageText = _tcsdup_ex(src->m_messageText);
94 m_messageTemplate = _tcsdup_ex(src->m_messageTemplate);
95 m_timeStamp = src->m_timeStamp;
96 m_userTag = _tcsdup_ex(src->m_userTag);
97 m_customMessage = _tcsdup_ex(src->m_customMessage);
816852b2
VK
98 m_parameters.setOwner(true);
99 for(int i = 0; i < src->m_parameters.size(); i++)
100 {
101 m_parameters.add(_tcsdup_ex((TCHAR *)src->m_parameters.get(i)));
102 }
103 m_parameterNames.addAll(&src->m_parameterNames);
104}
105
b9c2e1e1
VK
106/**
107 * Construct event from template
108 */
50963ced 109Event::Event(const EventTemplate *eventTemplate, UINT32 sourceId, UINT32 dciId, const TCHAR *userTag, const char *szFormat, const TCHAR **names, va_list args)
5039dede 110{
50963ced 111 _tcscpy(m_name, eventTemplate->getName());
65ce7452
VK
112 m_timeStamp = time(NULL);
113 m_id = CreateUniqueEventId();
114 m_rootId = 0;
50963ced
VK
115 m_code = eventTemplate->getCode();
116 m_severity = eventTemplate->getSeverity();
117 m_flags = eventTemplate->getFlags();
65ce7452
VK
118 m_sourceId = sourceId;
119 m_dciId = dciId;
120 m_messageText = NULL;
121 m_userTag = _tcsdup_ex(userTag);
122 if ((m_userTag != NULL) && (_tcslen(m_userTag) >= MAX_USERTAG_LENGTH))
123 m_userTag[MAX_USERTAG_LENGTH - 1] = 0;
124 m_customMessage = NULL;
ed806a1a 125 m_parameters.setOwner(true);
5039dede
AK
126
127 // Create parameters
128 if (szFormat != NULL)
129 {
ed806a1a
VK
130 int count = (int)strlen(szFormat);
131 TCHAR *buffer;
5039dede 132
ed806a1a 133 for(int i = 0; i < count; i++)
5039dede
AK
134 {
135 switch(szFormat[i])
136 {
137 case 's':
d999988d
VK
138 {
139 const TCHAR *s = va_arg(args, const TCHAR *);
140 m_parameters.add(_tcsdup_ex(s));
141 }
5039dede 142 break;
e86f3432 143 case 'm': // multibyte string
d999988d
VK
144 {
145 const char *s = va_arg(args, const char *);
e86f3432 146#ifdef UNICODE
d999988d 147 m_parameters.add((s != NULL) ? WideStringFromMBString(s) : _tcsdup(_T("")));
e86f3432 148#else
d999988d 149 m_parameters.add(strdup(CHECK_NULL_EX(s)));
e86f3432 150#endif
d999988d 151 }
e86f3432
VK
152 break;
153 case 'u': // UNICODE string
d999988d
VK
154 {
155 const WCHAR *s = va_arg(args, const WCHAR *);
e86f3432 156#ifdef UNICODE
d999988d 157 m_parameters.add(wcsdup(CHECK_NULL_EX(s)));
e86f3432 158#else
d999988d 159 m_parameters.add((s != NULL) ? MBStringFromWideString(s) : strdup(""));
e86f3432 160#endif
d999988d 161 }
e86f3432 162 break;
5039dede 163 case 'd':
ed806a1a
VK
164 buffer = (TCHAR *)malloc(16 * sizeof(TCHAR));
165 _sntprintf(buffer, 16, _T("%d"), va_arg(args, LONG));
166 m_parameters.add(buffer);
5039dede
AK
167 break;
168 case 'D':
ed806a1a
VK
169 buffer = (TCHAR *)malloc(32 * sizeof(TCHAR));
170 _sntprintf(buffer, 32, INT64_FMT, va_arg(args, INT64));
171 m_parameters.add(buffer);
5039dede 172 break;
d5cf7cda
VK
173 case 't':
174 buffer = (TCHAR *)malloc(32 * sizeof(TCHAR));
175 _sntprintf(buffer, 32, INT64_FMT, (INT64)va_arg(args, time_t));
176 m_parameters.add(buffer);
177 break;
5039dede
AK
178 case 'x':
179 case 'i':
ed806a1a 180 buffer = (TCHAR *)malloc(16 * sizeof(TCHAR));
967893bb 181 _sntprintf(buffer, 16, _T("0x%08X"), va_arg(args, UINT32));
ed806a1a 182 m_parameters.add(buffer);
5039dede 183 break;
c75e9ee4 184 case 'a': // IPv4 address
ed806a1a 185 buffer = (TCHAR *)malloc(16 * sizeof(TCHAR));
967893bb 186 IpToStr(va_arg(args, UINT32), buffer);
ed806a1a 187 m_parameters.add(buffer);
5039dede 188 break;
c75e9ee4
VK
189 case 'A': // InetAddress object
190 buffer = (TCHAR *)malloc(64 * sizeof(TCHAR));
191 va_arg(args, InetAddress *)->toString(buffer);
192 m_parameters.add(buffer);
193 break;
035745fc
VK
194 case 'h':
195 buffer = (TCHAR *)malloc(32 * sizeof(TCHAR));
196 MACToStr(va_arg(args, BYTE *), buffer);
197 m_parameters.add(buffer);
198 break;
5039dede 199 default:
ed806a1a 200 buffer = (TCHAR *)malloc(64 * sizeof(TCHAR));
967893bb 201 _sntprintf(buffer, 64, _T("BAD FORMAT \"%c\" [value = 0x%08X]"), szFormat[i], va_arg(args, UINT32));
ed806a1a 202 m_parameters.add(buffer);
5039dede
AK
203 break;
204 }
ed806a1a 205 m_parameterNames.add(((names != NULL) && (names[i] != NULL)) ? names[i] : _T(""));
5039dede
AK
206 }
207 }
5039dede 208
50963ced 209 m_messageTemplate = _tcsdup(eventTemplate->getMessageTemplate());
5039dede
AK
210}
211
b9c2e1e1
VK
212/**
213 * Destructor for event
214 */
5039dede
AK
215Event::~Event()
216{
65ce7452
VK
217 safe_free(m_messageText);
218 safe_free(m_messageTemplate);
219 safe_free(m_userTag);
220 safe_free(m_customMessage);
5039dede
AK
221}
222
b9c2e1e1
VK
223/**
224 * Create message text from template
225 */
fb986055 226void Event::expandMessageText()
5039dede 227{
65ce7452 228 if (m_messageTemplate != NULL)
5039dede 229 {
65ce7452 230 if (m_messageText != NULL)
5039dede 231 {
65ce7452
VK
232 free(m_messageText);
233 m_messageText = NULL;
5039dede 234 }
65ce7452
VK
235 m_messageText = expandText(m_messageTemplate);
236 free(m_messageTemplate);
237 m_messageTemplate = NULL;
5039dede
AK
238 }
239}
240
b9c2e1e1
VK
241/**
242 * Substitute % macros in given text with actual values
243 */
ca0e18d2 244TCHAR *Event::expandText(const TCHAR *textTemplate, const TCHAR *alarmMsg, const TCHAR *alarmKey)
6c984ccc 245{
65ce7452 246 return Event::expandText(this, m_sourceId, textTemplate, alarmMsg, alarmKey);
6c984ccc
VK
247}
248
b9c2e1e1
VK
249/**
250 * Substitute % macros in given text with actual values
251 */
ca0e18d2 252TCHAR *Event::expandText(Event *event, UINT32 sourceObject, const TCHAR *textTemplate, const TCHAR *alarmMsg, const TCHAR *alarmKey)
5039dede 253{
fb986055 254 const TCHAR *pCurr;
967893bb
VK
255 UINT32 dwPos, dwSize, dwParam;
256 UINT32 sourceId = (event != NULL) ? event->getSourceId() : sourceObject;
5039dede
AK
257 NetObj *pObject;
258 struct tm *lt;
fb986055 259 TCHAR *pText, szBuffer[4], scriptName[256];
5039dede
AK
260 int i;
261
ca0e18d2
VK
262 DbgPrintf(8, _T("Event::expandText(event=%p sourceObject=%d template='%s' alarmMsg='%s' alarmKey='%s')"),
263 event, (int)sourceObject, CHECK_NULL(textTemplate), CHECK_NULL(alarmMsg), CHECK_NULL(alarmKey));
c0b3992a 264
6c984ccc
VK
265 pObject = FindObjectById(sourceId);
266 if (pObject == NULL)
5039dede 267 {
6c984ccc
VK
268 pObject = FindObjectById(g_dwMgmtNode);
269 if (pObject == NULL)
270 pObject = g_pEntireNet;
5039dede 271 }
ca0e18d2 272 dwSize = (UINT32)_tcslen(textTemplate) + 1;
fb986055 273 pText = (TCHAR *)malloc(dwSize * sizeof(TCHAR));
ca0e18d2 274 for(pCurr = textTemplate, dwPos = 0; *pCurr != 0; pCurr++)
5039dede
AK
275 {
276 switch(*pCurr)
277 {
278 case '%': // Metacharacter
279 pCurr++;
280 if (*pCurr == 0)
281 {
282 pCurr--;
283 break; // Abnormal loop termination
284 }
285 switch(*pCurr)
286 {
287 case '%':
288 pText[dwPos++] = '%';
289 break;
5039dede 290 case 'a': // IP address of event source
c75e9ee4 291 dwSize += 64;
35f836fe 292 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
c30c0c0f 293 GetObjectIpAddress(pObject).toString(&pText[dwPos]);
967893bb 294 dwPos = (UINT32)_tcslen(pText);
5039dede 295 break;
df1aac85
VK
296 case 'A': // Associated alarm message
297 if (alarmMsg != NULL)
298 {
299 dwSize += (UINT32)_tcslen(alarmMsg);
300 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
301 _tcscpy(&pText[dwPos], alarmMsg);
302 dwPos += (UINT32)_tcslen(alarmMsg);
303 }
304 break;
305 case 'c': // Event code
306 dwSize += 16;
307 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
65ce7452 308 _sntprintf(&pText[dwPos], 16, _T("%u"), (unsigned int)((event != NULL) ? event->m_code : 0));
df1aac85
VK
309 dwPos = (UINT32)_tcslen(pText);
310 break;
f47b856a
VK
311 case 'g': // Source object's GUID
312 dwSize += 36;
313 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
de4af576 314 pObject->getGuid().toString(&pText[dwPos]);
967893bb 315 dwPos = (UINT32)_tcslen(pText);
f47b856a
VK
316 break;
317 case 'i': // Source object identifier in form 0xhhhhhhhh
5039dede 318 dwSize += 10;
35f836fe 319 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
6c984ccc 320 _sntprintf(&pText[dwPos], 11, _T("0x%08X"), sourceId);
967893bb 321 dwPos = (UINT32)_tcslen(pText);
5039dede 322 break;
f47b856a
VK
323 case 'I': // Source object identifier in decimal form
324 dwSize += 10;
325 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
326 _sntprintf(&pText[dwPos], 11, _T("%u"), (unsigned int)sourceId);
967893bb 327 dwPos = (UINT32)_tcslen(pText);
f47b856a 328 break;
df1aac85
VK
329 case 'K': // Associated alarm key
330 if (alarmKey != NULL)
331 {
332 dwSize += (UINT32)_tcslen(alarmKey);
333 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
334 _tcscpy(&pText[dwPos], alarmKey);
335 dwPos += (UINT32)_tcslen(alarmKey);
336 }
5039dede 337 break;
df1aac85 338 case 'm':
65ce7452 339 if ((event != NULL) && (event->m_messageText != NULL))
df1aac85 340 {
65ce7452 341 dwSize += (UINT32)_tcslen(event->m_messageText);
df1aac85 342 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
65ce7452
VK
343 _tcscpy(&pText[dwPos], event->m_messageText);
344 dwPos += (UINT32)_tcslen(event->m_messageText);
df1aac85 345 }
5039dede 346 break;
df1aac85 347 case 'M': // Custom message (usually set by matching script in EPP)
65ce7452 348 if ((event != NULL) && (event->m_customMessage != NULL))
df1aac85 349 {
65ce7452 350 dwSize += (UINT32)_tcslen(event->m_customMessage);
df1aac85 351 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
65ce7452
VK
352 _tcscpy(&pText[dwPos], event->m_customMessage);
353 dwPos += (UINT32)_tcslen(event->m_customMessage);
df1aac85
VK
354 }
355 break;
356 case 'n': // Name of event source
357 dwSize += (UINT32)_tcslen(pObject->getName());
35f836fe 358 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
df1aac85
VK
359 _tcscpy(&pText[dwPos], pObject->getName());
360 dwPos += (UINT32)_tcslen(pObject->getName());
5039dede 361 break;
b4fe4886 362 case 'N': // Event name
6c984ccc
VK
363 if (event != NULL)
364 {
c42b4551 365 dwSize += (UINT32)_tcslen(event->m_name);
6c984ccc 366 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
c42b4551
VK
367 _tcscpy(&pText[dwPos], event->m_name);
368 dwPos += (UINT32)_tcslen(event->m_name);
6c984ccc 369 }
b4fe4886 370 break;
5039dede 371 case 's': // Severity code
6c984ccc
VK
372 if (event != NULL)
373 {
374 dwSize += 3;
375 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
ad13c0e2 376 _sntprintf(&pText[dwPos], 4, _T("%d"), (int)event->m_severity);
967893bb 377 dwPos = (UINT32)_tcslen(pText);
6c984ccc 378 }
5039dede
AK
379 break;
380 case 'S': // Severity text
6c984ccc
VK
381 if (event != NULL)
382 {
ad13c0e2 383 const TCHAR *statusText = GetStatusAsText(event->m_severity, false);
6fec127d 384 dwSize += (UINT32)_tcslen(statusText);
6c984ccc 385 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
6fec127d
VK
386 _tcscpy(&pText[dwPos], statusText);
387 dwPos += (UINT32)_tcslen(statusText);
6c984ccc 388 }
5039dede 389 break;
df1aac85
VK
390 case 't': // Event's timestamp
391 dwSize += 32;
35f836fe 392 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
df1aac85
VK
393 if (event != NULL)
394 {
65ce7452 395 lt = localtime(&event->m_timeStamp);
df1aac85
VK
396 }
397 else
398 {
399 time_t t = time(NULL);
400 lt = localtime(&t);
401 }
402 _tcsftime(&pText[dwPos], 32, _T("%d-%b-%Y %H:%M:%S"), lt);
403 dwPos = (UINT32)_tcslen(pText);
ca0e18d2 404 break;
df1aac85
VK
405 case 'T': // Event's timestamp as number of seconds since epoch
406 dwSize += 16;
407 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
65ce7452 408 _sntprintf(&pText[dwPos], 16, _T("%lu"), (unsigned long)((event != NULL) ? event->m_timeStamp : time(NULL)));
df1aac85 409 dwPos = (UINT32)_tcslen(pText);
5039dede
AK
410 break;
411 case 'u': // User tag
65ce7452 412 if ((event != NULL) && (event->m_userTag != NULL))
5039dede 413 {
65ce7452 414 dwSize += (UINT32)_tcslen(event->m_userTag);
35f836fe 415 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
65ce7452
VK
416 _tcscpy(&pText[dwPos], event->m_userTag);
417 dwPos += (UINT32)_tcslen(event->m_userTag);
5039dede
AK
418 }
419 break;
df1aac85
VK
420 case 'v': // NetXMS server version
421 dwSize += (UINT32)_tcslen(NETXMS_VERSION_STRING);
422 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
423 _tcscpy(&pText[dwPos], NETXMS_VERSION_STRING);
424 dwPos += (UINT32)_tcslen(NETXMS_VERSION_STRING);
425 break;
5039dede
AK
426 case '0':
427 case '1':
428 case '2':
429 case '3':
430 case '4':
431 case '5':
432 case '6':
433 case '7':
434 case '8':
435 case '9':
6c984ccc
VK
436 if (event != NULL)
437 {
438 szBuffer[0] = *pCurr;
439 if (isdigit(*(pCurr + 1)))
440 {
441 pCurr++;
442 szBuffer[1] = *pCurr;
443 szBuffer[2] = 0;
444 }
445 else
446 {
447 szBuffer[1] = 0;
448 }
449 dwParam = _tcstoul(szBuffer, NULL, 10);
967893bb 450 if ((dwParam > 0) && (dwParam <= (UINT32)event->m_parameters.size()))
6c984ccc
VK
451 {
452 const TCHAR *value = (TCHAR *)event->m_parameters.get(dwParam - 1);
46ee6286
VK
453 if (value == NULL)
454 value = _T("");
967893bb 455 dwSize += (UINT32)_tcslen(value);
6c984ccc
VK
456 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
457 _tcscpy(&pText[dwPos], value);
967893bb 458 dwPos += (UINT32)_tcslen(value);
6c984ccc
VK
459 }
460 }
5039dede
AK
461 break;
462 case '[': // Script
463 for(i = 0, pCurr++; (*pCurr != ']') && (*pCurr != 0) && (i < 255); pCurr++)
464 {
465 scriptName[i++] = *pCurr;
466 }
467 if (*pCurr == 0) // no terminating ]
468 {
469 pCurr--;
470 }
471 else
472 {
5039dede 473 scriptName[i] = 0;
cf9af7b1
VK
474
475 // Entry point can be given in form script/entry_point
476 TCHAR *entryPoint = _tcschr(scriptName, _T('/'));
477 if (entryPoint != NULL)
478 {
479 *entryPoint = 0;
480 entryPoint++;
481 StrStrip(entryPoint);
482 }
5039dede
AK
483 StrStrip(scriptName);
484
6b29839d
VK
485 NXSL_VM *vm = g_pScriptLibrary->createVM(scriptName, new NXSL_ServerEnv);
486 if (vm != NULL)
5039dede 487 {
c42b4551 488 if (pObject->getObjectClass() == OBJECT_NODE)
6b29839d
VK
489 vm->setGlobalVariable(_T("$node"), new NXSL_Value(new NXSL_Object(&g_nxslNodeClass, pObject)));
490 vm->setGlobalVariable(_T("$event"), (event != NULL) ? new NXSL_Value(new NXSL_Object(&g_nxslEventClass, event)) : new NXSL_Value);
ca0e18d2 491 if (alarmMsg != NULL)
6b29839d 492 vm->setGlobalVariable(_T("$alarmMessage"), new NXSL_Value(alarmMsg));
ca0e18d2 493 if (alarmKey != NULL)
6b29839d 494 vm->setGlobalVariable(_T("$alarmKey"), new NXSL_Value(alarmKey));
5039dede 495
6b29839d 496 if (vm->run(0, NULL, NULL, NULL, NULL, entryPoint))
5039dede 497 {
6b29839d 498 NXSL_Value *result = vm->getResult();
17a9c342
VK
499 if (result != NULL)
500 {
bb5365ed 501 const TCHAR *temp = result->getValueAsCString();
17a9c342
VK
502 if (temp != NULL)
503 {
967893bb 504 dwSize += (UINT32)_tcslen(temp);
35f836fe 505 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
17a9c342 506 _tcscpy(&pText[dwPos], temp);
967893bb 507 dwPos += (UINT32)_tcslen(temp);
35f836fe 508 DbgPrintf(4, _T("Event::ExpandText(%d, \"%s\"): Script %s executed successfully"),
65ce7452 509 (int)((event != NULL) ? event->m_code : 0), textTemplate, scriptName);
17a9c342
VK
510 }
511 }
5039dede
AK
512 }
513 else
514 {
35f836fe 515 DbgPrintf(4, _T("Event::ExpandText(%d, \"%s\"): Script %s execution error: %s"),
65ce7452 516 (int)((event != NULL) ? event->m_code : 0), textTemplate, scriptName, vm->getErrorText());
6b29839d 517 PostEvent(EVENT_SCRIPT_ERROR, g_dwMgmtNode, "ssd", scriptName, vm->getErrorText(), 0);
5039dede
AK
518 }
519 }
520 else
521 {
6c984ccc 522 DbgPrintf(4, _T("Event::ExpandText(%d, \"%s\"): Cannot find script %s"),
65ce7452 523 (int)((event != NULL) ? event->m_code : 0), textTemplate, scriptName);
5039dede 524 }
5039dede
AK
525 }
526 break;
527 case '{': // Custom attribute
528 for(i = 0, pCurr++; (*pCurr != '}') && (*pCurr != 0) && (i < 255); pCurr++)
529 {
530 scriptName[i++] = *pCurr;
531 }
532 if (*pCurr == 0) // no terminating }
533 {
534 pCurr--;
535 }
536 else
537 {
538 scriptName[i] = 0;
539 StrStrip(scriptName);
84a815cd 540 const TCHAR *temp = pObject->getCustomAttribute(scriptName);
5039dede
AK
541 if (temp != NULL)
542 {
967893bb 543 dwSize += (UINT32)_tcslen(temp);
35f836fe 544 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
5039dede 545 _tcscpy(&pText[dwPos], temp);
967893bb 546 dwPos += (UINT32)_tcslen(temp);
5039dede
AK
547 }
548 }
549 break;
df1aac85
VK
550 case '(': // input field - scan for closing ) for compatibility
551 for(i = 0, pCurr++; (*pCurr != ')') && (*pCurr != 0) && (i < 255); pCurr++)
552 {
553 }
554 if (*pCurr == 0) // no terminating }
555 {
556 pCurr--;
557 }
558 break;
ed806a1a 559 case '<': // Named parameter
6c984ccc 560 if (event != NULL)
ed806a1a 561 {
6c984ccc
VK
562 for(i = 0, pCurr++; (*pCurr != '>') && (*pCurr != 0) && (i < 255); pCurr++)
563 {
564 scriptName[i++] = *pCurr;
565 }
566 if (*pCurr == 0) // no terminating >
567 {
568 pCurr--;
569 }
570 else
ed806a1a 571 {
6c984ccc
VK
572 scriptName[i] = 0;
573 StrStrip(scriptName);
a6312bd6 574 int index = event->m_parameterNames.indexOfIgnoreCase(scriptName);
6c984ccc 575 if (index != -1)
ed806a1a 576 {
6c984ccc
VK
577 const TCHAR *temp = (TCHAR *)event->m_parameters.get(index);
578 if (temp != NULL)
579 {
967893bb 580 dwSize += (UINT32)_tcslen(temp);
6c984ccc
VK
581 pText = (TCHAR *)realloc(pText, dwSize * sizeof(TCHAR));
582 _tcscpy(&pText[dwPos], temp);
967893bb 583 dwPos += (UINT32)_tcslen(temp);
6c984ccc 584 }
ed806a1a
VK
585 }
586 }
587 }
588 break;
5039dede
AK
589 default: // All other characters are invalid, ignore
590 break;
591 }
592 break;
593 case '\\': // Escape character
594 pCurr++;
595 if (*pCurr == 0)
596 {
597 pCurr--;
598 break; // Abnormal loop termination
599 }
600 switch(*pCurr)
601 {
602 case 't':
603 pText[dwPos++] = '\t';
604 break;
605 case 'n':
606 pText[dwPos++] = 0x0D;
607 pText[dwPos++] = 0x0A;
608 break;
609 default:
610 pText[dwPos++] = *pCurr;
611 break;
612 }
613 break;
614 default:
615 pText[dwPos++] = *pCurr;
616 break;
617 }
618 }
619 pText[dwPos] = 0;
620 return pText;
621}
622
035745fc
VK
623/**
624 * Add new parameter to event
625 */
ed806a1a
VK
626void Event::addParameter(const TCHAR *name, const TCHAR *value)
627{
628 m_parameters.add(_tcsdup(value));
629 m_parameterNames.add(name);
630}
631
035745fc
VK
632/**
633 * Set value of named parameter
634 */
24dc5346
VK
635void Event::setNamedParameter(const TCHAR *name, const TCHAR *value)
636{
a6312bd6 637 int index = m_parameterNames.indexOfIgnoreCase(name);
24dc5346
VK
638 if (index != -1)
639 {
640 m_parameters.replace(index, _tcsdup(value));
641 m_parameterNames.replace(index, name);
642 }
643 else
644 {
645 m_parameters.add(_tcsdup(value));
646 m_parameterNames.add(name);
647 }
648}
649
d5cf7cda
VK
650/**
651 * Set value (and optionally name) of parameter at given index.
652 *
653 * @param index 0-based parameter index
654 * @param name parameter name (can be NULL)
655 * @param value new value
656 */
657void Event::setParameter(int index, const TCHAR *name, const TCHAR *value)
658{
659 if (index < 0)
660 return;
661
662 int addup = index - m_parameters.size();
663 for(int i = 0; i < addup; i++)
664 {
665 m_parameters.add(_tcsdup(_T("")));
666 m_parameterNames.add(_T(""));
667 }
668 if (index < m_parameters.size())
669 {
670 m_parameters.replace(index, _tcsdup(value));
671 m_parameterNames.replace(index, CHECK_NULL_EX(name));
672 }
673 else
674 {
675 m_parameters.add(_tcsdup(value));
676 m_parameterNames.add(CHECK_NULL_EX(name));
677 }
678}
679
035745fc
VK
680/**
681 * Fill message with event data
682 */
65ce7452 683void Event::prepareMessage(NXCPMessage *msg) const
5039dede 684{
65ce7452
VK
685 msg->setField(VID_NUM_RECORDS, (UINT32)1);
686 msg->setField(VID_RECORDS_ORDER, (WORD)RECORD_ORDER_NORMAL);
687
688 UINT32 id = VID_EVENTLOG_MSG_BASE;
689 msg->setField(id++, m_id);
690 msg->setField(id++, m_code);
691 msg->setField(id++, (UINT32)m_timeStamp);
692 msg->setField(id++, m_sourceId);
693 msg->setField(id++, (WORD)m_severity);
694 msg->setField(id++, CHECK_NULL_EX(m_messageText));
695 msg->setField(id++, CHECK_NULL_EX(m_userTag));
696 msg->setField(id++, (UINT32)m_parameters.size());
ed806a1a 697 for(int i = 0; i < m_parameters.size(); i++)
65ce7452
VK
698 msg->setField(id++, (TCHAR *)m_parameters.get(i));
699 msg->setField(id++, m_dciId);
5039dede
AK
700}
701
035745fc
VK
702/**
703 * Load event configuration from database
704 */
65ce7452 705static bool LoadEvents()
5039dede 706{
65ce7452 707 bool success = false;
035745fc 708 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
50963ced 709 DB_RESULT hResult = DBSelect(hdb, _T("SELECT event_code,severity,flags,message,description,event_name FROM event_cfg"));
5039dede
AK
710 if (hResult != NULL)
711 {
50963ced
VK
712 int count = DBGetNumRows(hResult);
713 for(int i = 0; i < count; i++)
5039dede 714 {
50963ced
VK
715 EventTemplate *t = new EventTemplate(hResult, i);
716 m_eventTemplates.set(t->getCode(), t);
717 t->decRefCount();
5039dede
AK
718 }
719
720 DBFreeResult(hResult);
65ce7452 721 success = true;
5039dede
AK
722 }
723 else
724 {
725 nxlog_write(MSG_EVENT_LOAD_ERROR, EVENTLOG_ERROR_TYPE, NULL);
726 }
727
035745fc 728 DBConnectionPoolReleaseConnection(hdb);
65ce7452 729 return success;
5039dede
AK
730}
731
0688e29b
VK
732/**
733 * Inilialize event handling subsystem
734 */
ed806a1a 735BOOL InitEventSubsystem()
5039dede
AK
736{
737 BOOL bSuccess;
738
739 // Create template access mutex
740 m_rwlockTemplateAccess = RWLockCreate();
741
742 // Create event queue
743 g_pEventQueue = new Queue;
744
745 // Load events from database
746 bSuccess = LoadEvents();
747
748 // Create and initialize event processing policy
749 if (bSuccess)
750 {
751 g_pEventPolicy = new EventPolicy;
0688e29b 752 if (!g_pEventPolicy->loadFromDB())
5039dede
AK
753 {
754 bSuccess = FALSE;
755 nxlog_write(MSG_EPP_LOAD_FAILED, EVENTLOG_ERROR_TYPE, NULL);
756 delete g_pEventPolicy;
757 }
758 }
759
760 return bSuccess;
761}
762
0688e29b
VK
763/**
764 * Shutdown event subsystem
765 */
ed806a1a 766void ShutdownEventSubsystem()
5039dede
AK
767{
768 delete g_pEventQueue;
769 delete g_pEventPolicy;
5039dede
AK
770 RWLockDestroy(m_rwlockTemplateAccess);
771}
772
035745fc
VK
773/**
774 * Reload event templates from database
775 */
ed806a1a 776void ReloadEvents()
5039dede 777{
5039dede 778 RWLockWriteLock(m_rwlockTemplateAccess, INFINITE);
50963ced 779 m_eventTemplates.clear();
5039dede
AK
780 LoadEvents();
781 RWLockUnlock(m_rwlockTemplateAccess);
782}
783
035745fc
VK
784/**
785 * Delete event template from list
786 */
b8ad978c 787void DeleteEventTemplateFromList(UINT32 eventCode)
5039dede 788{
5039dede 789 RWLockWriteLock(m_rwlockTemplateAccess, INFINITE);
50963ced 790 m_eventTemplates.remove(eventCode);
5039dede
AK
791 RWLockUnlock(m_rwlockTemplateAccess);
792}
793
a0dc14f9 794/**
b8ad978c
VK
795 * Post event to given event queue.
796 *
797 * @param queue event queue to post events to
798 * @param eventCode Event code
799 * @param sourceId Event source object ID
800 * @param userTag event's user tag
801 * @param format Parameter format string, each parameter represented by one character.
a0dc14f9
VK
802 * The following format characters can be used:
803 * s - String
035745fc
VK
804 * m - Multibyte string
805 * u - UNICODE string
a0dc14f9
VK
806 * d - Decimal integer
807 * D - 64-bit decimal integer
808 * x - Hex integer
c75e9ee4
VK
809 * a - IPv4 address
810 * A - InetAddress object
035745fc 811 * h - MAC (hardware) address
a0dc14f9 812 * i - Object ID
b8ad978c
VK
813 * @param names names for parameters (NULL if parameters are unnamed)
814 * @param args event parameters
a0dc14f9 815 */
65ce7452 816static bool RealPostEvent(Queue *queue, UINT64 *eventId, UINT32 eventCode, UINT32 sourceId, UINT32 dciId,
b8ad978c 817 const TCHAR *userTag, const char *format, const TCHAR **names, va_list args)
5039dede 818{
50963ced 819 EventTemplate *eventTemplate = NULL;
65ce7452 820 bool success = false;
5039dede
AK
821
822 RWLockReadLock(m_rwlockTemplateAccess, INFINITE);
823
50963ced
VK
824 eventTemplate = m_eventTemplates.get(eventCode);
825 if (eventTemplate != NULL)
5039dede 826 {
50963ced
VK
827 // Template found, create new event
828 Event *evt = new Event(eventTemplate, sourceId, dciId, userTag, format, names, args);
829 if (eventId != NULL)
830 *eventId = evt->getId();
5039dede 831
50963ced
VK
832 // Add new event to queue
833 queue->put(evt);
5039dede 834
50963ced
VK
835 eventTemplate->decRefCount();
836 success = true;
5039dede
AK
837 }
838
839 RWLockUnlock(m_rwlockTemplateAccess);
85f9e5a7 840
65ce7452 841 if (eventTemplate == NULL)
85f9e5a7
VK
842 {
843 DbgPrintf(3, _T("RealPostEvent: event with code %d not defined"), eventCode);
844 }
65ce7452 845 return success;
5039dede
AK
846}
847
b8ad978c
VK
848/**
849 * Post event to system event queue.
850 *
851 * @param eventCode Event code
852 * @param sourceId Event source object ID
853 * @param format Parameter format string, each parameter represented by one character.
854 * The following format characters can be used:
855 * s - String
856 * m - Multibyte string
857 * u - UNICODE string
858 * d - Decimal integer
859 * D - 64-bit decimal integer
860 * x - Hex integer
c75e9ee4
VK
861 * a - IPv4 address
862 * A - InetAddress object
b8ad978c
VK
863 * h - MAC (hardware) address
864 * i - Object ID
d5cf7cda 865 * t - timestamp (time_t) as raw value (seconds since epoch)
b8ad978c 866 */
65ce7452 867bool NXCORE_EXPORTABLE PostEvent(UINT32 eventCode, UINT32 sourceId, const char *format, ...)
5039dede
AK
868{
869 va_list args;
65ce7452
VK
870 va_start(args, format);
871 bool success = RealPostEvent(g_pEventQueue, NULL, eventCode, sourceId, 0, NULL, format, NULL, args);
872 va_end(args);
873 return success;
874}
5039dede 875
65ce7452
VK
876/**
877 * Post DCI-related event to system event queue.
878 *
879 * @param eventCode Event code
880 * @param sourceId Event source object ID
881 * @param dciId DCI ID
882 * @param format Parameter format string, each parameter represented by one character.
883 * The following format characters can be used:
884 * s - String
885 * m - Multibyte string
886 * u - UNICODE string
887 * d - Decimal integer
888 * D - 64-bit decimal integer
889 * x - Hex integer
890 * a - IPv4 address
891 * A - InetAddress object
892 * h - MAC (hardware) address
893 * i - Object ID
894 * t - timestamp (time_t) as raw value (seconds since epoch)
895 */
896bool NXCORE_EXPORTABLE PostDciEvent(UINT32 eventCode, UINT32 sourceId, UINT32 dciId, const char *format, ...)
897{
898 va_list args;
b8ad978c 899 va_start(args, format);
65ce7452 900 bool success = RealPostEvent(g_pEventQueue, NULL, eventCode, sourceId, dciId, NULL, format, NULL, args);
ed806a1a 901 va_end(args);
65ce7452 902 return success;
ed806a1a
VK
903}
904
7e18667a
VK
905/**
906 * Post event to system event queue and return ID of new event (0 in case of failure).
907 *
908 * @param eventCode Event code
909 * @param sourceId Event source object ID
910 * @param format Parameter format string, each parameter represented by one character.
911 * The following format characters can be used:
912 * s - String
913 * m - Multibyte string
914 * u - UNICODE string
915 * d - Decimal integer
916 * D - 64-bit decimal integer
917 * x - Hex integer
918 * a - IPv4 address
919 * A - InetAddress object
920 * h - MAC (hardware) address
921 * i - Object ID
922 * t - timestamp (time_t) as raw value (seconds since epoch)
923 */
924UINT64 NXCORE_EXPORTABLE PostEvent2(UINT32 eventCode, UINT32 sourceId, const char *format, ...)
925{
926 va_list args;
7e18667a 927 UINT64 eventId;
7e18667a 928 va_start(args, format);
65ce7452 929 bool success = RealPostEvent(g_pEventQueue, &eventId, eventCode, sourceId, 0, NULL, format, NULL, args);
7e18667a 930 va_end(args);
65ce7452 931 return success ? eventId : 0;
7e18667a
VK
932}
933
b8ad978c
VK
934/**
935 * Post event to system event queue.
936 *
937 * @param eventCode Event code
938 * @param sourceId Event source object ID
939 * @param format Parameter format string, each parameter represented by one character.
940 * The following format characters can be used:
941 * s - String
942 * m - Multibyte string
943 * u - UNICODE string
944 * d - Decimal integer
945 * D - 64-bit decimal integer
946 * x - Hex integer
c75e9ee4
VK
947 * a - IPv4 address
948 * A - InetAddress object
b8ad978c
VK
949 * h - MAC (hardware) address
950 * i - Object ID
951 * @param names names for parameters (NULL if parameters are unnamed)
952 */
65ce7452 953bool NXCORE_EXPORTABLE PostEventWithNames(UINT32 eventCode, UINT32 sourceId, const char *format, const TCHAR **names, ...)
ed806a1a
VK
954{
955 va_list args;
65ce7452
VK
956 va_start(args, names);
957 bool success = RealPostEvent(g_pEventQueue, NULL, eventCode, sourceId, 0, NULL, format, names, args);
958 va_end(args);
959 return success;
960}
ed806a1a 961
65ce7452
VK
962/**
963 * Post DCI-related event to system event queue.
964 *
965 * @param eventCode Event code
966 * @param sourceId Event source object ID
967 * @param dciId DCI ID
968 * @param format Parameter format string, each parameter represented by one character.
969 * The following format characters can be used:
970 * s - String
971 * m - Multibyte string
972 * u - UNICODE string
973 * d - Decimal integer
974 * D - 64-bit decimal integer
975 * x - Hex integer
976 * a - IPv4 address
977 * A - InetAddress object
978 * h - MAC (hardware) address
979 * i - Object ID
980 * @param names names for parameters (NULL if parameters are unnamed)
981 */
982bool NXCORE_EXPORTABLE PostDciEventWithNames(UINT32 eventCode, UINT32 sourceId, UINT32 dciId, const char *format, const TCHAR **names, ...)
983{
984 va_list args;
ed806a1a 985 va_start(args, names);
65ce7452 986 bool success = RealPostEvent(g_pEventQueue, NULL, eventCode, sourceId, dciId, NULL, format, names, args);
5039dede 987 va_end(args);
65ce7452 988 return success;
5039dede
AK
989}
990
d999988d
VK
991/**
992 * Post event to system event queue.
993 *
994 * @param eventCode Event code
995 * @param sourceId Event source object ID
996 * @param format Parameter format string, each parameter represented by one character.
997 * The following format characters can be used:
998 * s - String
999 * m - Multibyte string
1000 * u - UNICODE string
1001 * d - Decimal integer
1002 * D - 64-bit decimal integer
1003 * x - Hex integer
c75e9ee4
VK
1004 * a - IPv4 address
1005 * A - InetAddress object
d999988d
VK
1006 * h - MAC (hardware) address
1007 * i - Object ID
1008 * @param names names for parameters (NULL if parameters are unnamed)
1009 */
65ce7452 1010bool NXCORE_EXPORTABLE PostEventWithTagAndNames(UINT32 eventCode, UINT32 sourceId, const TCHAR *userTag, const char *format, const TCHAR **names, ...)
d999988d
VK
1011{
1012 va_list args;
d999988d 1013 va_start(args, names);
65ce7452 1014 bool success = RealPostEvent(g_pEventQueue, NULL, eventCode, sourceId, 0, userTag, format, names, args);
d999988d 1015 va_end(args);
65ce7452 1016 return success;
d999988d
VK
1017}
1018
7806c906
VK
1019/**
1020 * Post event to system event queue.
1021 *
1022 * @param eventCode Event code
1023 * @param sourceId Event source object ID
1024 * @param parameters event parameters list
1025 */
65ce7452 1026bool NXCORE_EXPORTABLE PostEventWithNames(UINT32 eventCode, UINT32 sourceId, StringMap *parameters)
7806c906 1027{
400e55c4 1028 /*
7806c906
VK
1029 int count = parameters->size();
1030 if (count > 1023)
1031 count = 1023;
1032
1033 char format[1024];
1034 memset(format, 's', count);
1035 format[count] = 0;
1036
1037 const TCHAR *names[1024];
1038 const TCHAR *args[1024];
1039 for(int i = 0; i < count; i++)
1040 {
1041 names[i] = parameters->getKeyByIndex(i);
1042 args[i] = parameters->getValueByIndex(i);
1043 }
1044
400e55c4
VK
1045 return RealPostEvent(g_pEventQueue, eventCode, sourceId, NULL, format, names, args);
1046 */
65ce7452
VK
1047 return false;
1048}
1049
1050/**
1051 * Post DCI-related event to system event queue.
1052 *
1053 * @param eventCode Event code
1054 * @param sourceId Event source object ID
1055 * @param dciId DCI ID
1056 * @param parameters event parameters list
1057 */
1058bool NXCORE_EXPORTABLE PostDciEventWithNames(UINT32 eventCode, UINT32 sourceId, UINT32 dciId, StringMap *parameters)
1059{
1060 /*
1061 int count = parameters->size();
1062 if (count > 1023)
1063 count = 1023;
1064
1065 char format[1024];
1066 memset(format, 's', count);
1067 format[count] = 0;
1068
1069 const TCHAR *names[1024];
1070 const TCHAR *args[1024];
1071 for(int i = 0; i < count; i++)
1072 {
1073 names[i] = parameters->getKeyByIndex(i);
1074 args[i] = parameters->getValueByIndex(i);
1075 }
1076
1077 return RealPostEvent(g_pEventQueue, eventCode, sourceId, NULL, format, names, args);
1078 */
1079 return false;
7806c906
VK
1080}
1081
b8ad978c
VK
1082/**
1083 * Post event to system event queue.
1084 *
1085 * @param eventCode Event code
1086 * @param sourceId Event source object ID
1087 * @param userTag event's user tag
1088 * @param format Parameter format string, each parameter represented by one character.
1089 * The following format characters can be used:
1090 * s - String
1091 * m - Multibyte string
1092 * u - UNICODE string
1093 * d - Decimal integer
1094 * D - 64-bit decimal integer
1095 * x - Hex integer
c75e9ee4
VK
1096 * a - IPv4 address
1097 * A - InetAddress object
b8ad978c
VK
1098 * h - MAC (hardware) address
1099 * i - Object ID
1100 * @param names names for parameters (NULL if parameters are unnamed)
1101 * @param args event parameters
1102 */
65ce7452 1103bool NXCORE_EXPORTABLE PostEventWithTag(UINT32 eventCode, UINT32 sourceId, const TCHAR *userTag, const char *format, ...)
5039dede
AK
1104{
1105 va_list args;
b8ad978c 1106 va_start(args, format);
65ce7452 1107 bool success = RealPostEvent(g_pEventQueue, NULL, eventCode, sourceId, 0, userTag, format, NULL, args);
5039dede 1108 va_end(args);
65ce7452 1109 return success;
5039dede
AK
1110}
1111
b8ad978c
VK
1112/**
1113 * Post event to given event queue.
1114 *
1115 * @param queue event queue to post events to
1116 * @param eventCode Event code
1117 * @param sourceId Event source object ID
1118 * @param format Parameter format string, each parameter represented by one character.
1119 * The following format characters can be used:
1120 * s - String
1121 * m - Multibyte string
1122 * u - UNICODE string
1123 * d - Decimal integer
1124 * D - 64-bit decimal integer
1125 * x - Hex integer
c75e9ee4
VK
1126 * a - IPv4 address
1127 * A - InetAddress object
b8ad978c
VK
1128 * h - MAC (hardware) address
1129 * i - Object ID
1130 */
65ce7452 1131bool NXCORE_EXPORTABLE PostEventEx(Queue *queue, UINT32 eventCode, UINT32 sourceId, const char *format, ...)
5039dede
AK
1132{
1133 va_list args;
b8ad978c 1134 va_start(args, format);
65ce7452 1135 bool success = RealPostEvent(queue, NULL, eventCode, sourceId, 0, NULL, format, NULL, args);
5039dede 1136 va_end(args);
65ce7452 1137 return success;
5039dede
AK
1138}
1139
c1482463
VK
1140/**
1141 * Resend events from specific queue to system event queue
1142 */
3ae780c4 1143void NXCORE_EXPORTABLE ResendEvents(Queue *queue)
5039dede 1144{
5039dede
AK
1145 while(1)
1146 {
19dbc8ef 1147 void *pEvent = queue->get();
5039dede
AK
1148 if (pEvent == NULL)
1149 break;
19dbc8ef 1150 g_pEventQueue->put(pEvent);
5039dede
AK
1151 }
1152}
1153
c1482463
VK
1154/**
1155 * Create NXMP record for event
1156 */
b8ad978c 1157void CreateNXMPEventRecord(String &str, UINT32 eventCode)
5039dede 1158{
5039dede
AK
1159 String strText, strDescr;
1160
1161 RWLockReadLock(m_rwlockTemplateAccess, INFINITE);
1162
1163 // Find event template
50963ced
VK
1164 EventTemplate *p = m_eventTemplates.get(eventCode);
1165 if (p != NULL)
5039dede 1166 {
50963ced
VK
1167 str.appendFormattedString(_T("\t\t<event id=\"%d\">\n")
1168 _T("\t\t\t<name>%s</name>\n")
6a41590a 1169 _T("\t\t\t<guid>%s</guid>\n")
50963ced 1170 _T("\t\t\t<code>%d</code>\n")
50963ced
VK
1171 _T("\t\t\t<severity>%d</severity>\n")
1172 _T("\t\t\t<flags>%d</flags>\n")
1173 _T("\t\t\t<message>%s</message>\n")
1174 _T("\t\t\t<description>%s</description>\n")
1175 _T("\t\t</event>\n"),
1176 p->getCode(), (const TCHAR *)EscapeStringForXML2(p->getName()),
1177 (const TCHAR *)p->getGuid().toString(), p->getCode(), p->getSeverity(),
1178 p->getFlags(), (const TCHAR *)EscapeStringForXML2(p->getMessageTemplate()),
1179 (const TCHAR *)EscapeStringForXML2(p->getDescription()));
1180 p->decRefCount();
5039dede
AK
1181 }
1182
1183 RWLockUnlock(m_rwlockTemplateAccess);
1184}
1185
c1482463
VK
1186/**
1187 * Resolve event name
1188 */
50963ced 1189bool EventNameFromCode(UINT32 eventCode, TCHAR *buffer)
5039dede 1190{
50963ced 1191 bool bRet = false;
5039dede
AK
1192
1193 RWLockReadLock(m_rwlockTemplateAccess, INFINITE);
1194
50963ced
VK
1195 EventTemplate *p = m_eventTemplates.get(eventCode);
1196 if (p != NULL)
5039dede 1197 {
50963ced
VK
1198 _tcscpy(buffer, p->getName());
1199 p->decRefCount();
1200 bRet = true;
5039dede
AK
1201 }
1202 else
1203 {
50963ced 1204 _tcscpy(buffer, _T("UNKNOWN_EVENT"));
5039dede
AK
1205 }
1206
1207 RWLockUnlock(m_rwlockTemplateAccess);
1208 return bRet;
1209}
1210
b8ad978c
VK
1211/**
1212 * Find event template by code - suitable for external call
1213 */
50963ced 1214EventTemplate *FindEventTemplateByCode(UINT32 eventCode)
5039dede 1215{
5039dede 1216 RWLockReadLock(m_rwlockTemplateAccess, INFINITE);
50963ced 1217 EventTemplate *p = m_eventTemplates.get(eventCode);
5039dede
AK
1218 RWLockUnlock(m_rwlockTemplateAccess);
1219 return p;
1220}
1221
b8ad978c
VK
1222/**
1223 * Find event template by name - suitable for external call
1224 */
50963ced 1225EventTemplate *FindEventTemplateByName(const TCHAR *name)
5039dede 1226{
50963ced 1227 EventTemplate *result = NULL;
967893bb 1228 UINT32 i;
5039dede
AK
1229
1230 RWLockReadLock(m_rwlockTemplateAccess, INFINITE);
50963ced
VK
1231 Iterator<EventTemplate> *it = m_eventTemplates.iterator();
1232 while(it->hasNext())
5039dede 1233 {
50963ced
VK
1234 EventTemplate *t = it->next();
1235 if (!_tcscmp(t->getName(), name))
5039dede 1236 {
50963ced
VK
1237 result = t;
1238 result->incRefCount();
5039dede
AK
1239 break;
1240 }
1241 }
50963ced 1242 delete it;
5039dede 1243 RWLockUnlock(m_rwlockTemplateAccess);
50963ced 1244 return result;
5039dede 1245}
a65c1819 1246
a6cc48cc
VK
1247/**
1248 * Translate event name to code
1249 * If event with given name does not exist, returns supplied default value
1250 */
6fec127d 1251UINT32 NXCORE_EXPORTABLE EventCodeFromName(const TCHAR *name, UINT32 defaultValue)
a65c1819 1252{
50963ced
VK
1253 EventTemplate *p = FindEventTemplateByName(name);
1254 if (p == NULL)
1255 return defaultValue;
1256 UINT32 code = p->getCode();
1257 p->decRefCount();
1258 return code;
a65c1819 1259}
6fec127d
VK
1260
1261/**
1262 * Get status as text
1263 */
1264const TCHAR NXCORE_EXPORTABLE *GetStatusAsText(int status, bool allCaps)
1265{
1266 static const TCHAR *statusText[] = { _T("NORMAL"), _T("WARNING"), _T("MINOR"), _T("MAJOR"), _T("CRITICAL"), _T("UNKNOWN"), _T("UNMANAGED"), _T("DISABLED"), _T("TESTING") };
1267 static const TCHAR *statusTextSmall[] = { _T("Normal"), _T("Warning"), _T("Minor"), _T("Major"), _T("Critical"), _T("Unknown"), _T("Unmanaged"), _T("Disabled"), _T("Testing") };
1268
1269 if (allCaps)
1270 {
1271 return ((status >= STATUS_NORMAL) && (status <= STATUS_TESTING)) ? statusText[status] : _T("INTERNAL ERROR");
1272 }
1273 else
1274 {
1275 return ((status >= STATUS_NORMAL) && (status <= STATUS_TESTING)) ? statusTextSmall[status] : _T("INTERNAL ERROR");
1276 }
1277}