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