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