refactoring of AgentConnection::getList
[public/netxms.git] / src / server / core / objtools.cpp
CommitLineData
03f4f212 1/*
5039dede 2** NetXMS - Network Management System
9c5ebc32 3** Copyright (C) 2003-2016 Raden Solutions
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: objtools.cpp
20**
21**/
22
23#include "nxcore.h"
5039dede 24#include <netxms-regex.h>
bf6fb6c3 25#include <nxtools.h>
5039dede 26
6f8e39e5 27/**
b576249a
VK
28 * Object tool acl entry
29 */
30typedef struct
31{
32 UINT32 toolId;
33 UINT32 userId;
34} OBJECT_TOOL_ACL;
35
36/**
6f8e39e5
VK
37 * Tool startup info
38 */
5039dede
AK
39struct TOOL_STARTUP_INFO
40{
b576249a 41 UINT32 toolId;
967893bb
VK
42 UINT32 dwRqId;
43 UINT32 dwFlags;
5039dede
AK
44 Node *pNode;
45 ClientSession *pSession;
46 TCHAR *pszToolData;
47};
48
6f8e39e5
VK
49/**
50 * SNMP table enumerator arguments
51 */
5039dede
AK
52struct SNMP_ENUM_ARGS
53{
967893bb 54 UINT32 dwNumCols;
5039dede
AK
55 TCHAR **ppszOidList;
56 LONG *pnFormatList;
967893bb 57 UINT32 dwFlags;
5039dede 58 Node *pNode;
e31c8e60 59 Table *table;
5039dede
AK
60};
61
6f8e39e5 62/**
271e3971 63 * Rollback all querys, release BD connection, free prepared statement if not NULL and return RCC_DB_FAILURE code
2d7ee2e0 64 */
271e3971 65static UINT32 ReturnDBFailure(DB_HANDLE hdb, DB_STATEMENT hStmt)
2d7ee2e0 66{
67 DBRollback(hdb);
271e3971
VK
68 if (hStmt != NULL)
69 DBFreeStatement(hStmt);
2d7ee2e0 70 DBConnectionPoolReleaseConnection(hdb);
2d7ee2e0 71 return RCC_DB_FAILURE;
72}
73
74/**
6f8e39e5
VK
75 * Check if tool with given id exist and is a table tool
76 */
b576249a 77BOOL IsTableTool(UINT32 toolId)
5039dede
AK
78{
79 DB_RESULT hResult;
5039dede
AK
80 LONG nType;
81 BOOL bResult = FALSE;
82
2d7ee2e0 83 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
b576249a
VK
84 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT tool_type FROM object_tools WHERE tool_id=?"));
85 if (hStmt == NULL)
2d7ee2e0 86 {
87 DBConnectionPoolReleaseConnection(hdb);
88 return RCC_DB_FAILURE;
89 }
b576249a 90 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
2d7ee2e0 91
b576249a 92 hResult = DBSelectPrepared(hStmt);
5039dede
AK
93 if (hResult != NULL)
94 {
95 if (DBGetNumRows(hResult) > 0)
96 {
97 nType = DBGetFieldLong(hResult, 0, 0);
98 bResult = ((nType == TOOL_TYPE_TABLE_SNMP) || (nType == TOOL_TYPE_TABLE_AGENT));
99 }
100 DBFreeResult(hResult);
101 }
2d7ee2e0 102 DBConnectionPoolReleaseConnection(hdb);
b576249a 103 DBFreeStatement(hStmt);
5039dede
AK
104 return bResult;
105}
106
2d7ee2e0 107/**
108 * Check if user has access to the tool
109 */
b576249a 110BOOL CheckObjectToolAccess(UINT32 toolId, UINT32 userId)
5039dede
AK
111{
112 DB_RESULT hResult;
5039dede 113 int i, nRows;
967893bb 114 UINT32 dwId;
5039dede
AK
115 BOOL bResult = FALSE;
116
b576249a 117 if (userId == 0)
5039dede
AK
118 return TRUE;
119
2d7ee2e0 120 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
b576249a
VK
121 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT user_id FROM object_tools_acl WHERE tool_id=?"));
122 if (hStmt == NULL)
2d7ee2e0 123 {
124 DBConnectionPoolReleaseConnection(hdb);
125 return RCC_DB_FAILURE;
126 }
b576249a 127 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
2d7ee2e0 128
b576249a 129 hResult = DBSelectPrepared(hStmt);
5039dede
AK
130 if (hResult != NULL)
131 {
132 nRows = DBGetNumRows(hResult);
133 for(i = 0; i < nRows; i++)
134 {
135 dwId = DBGetFieldULong(hResult, i, 0);
b576249a 136 if ((dwId == userId) || (dwId == GROUP_EVERYONE))
5039dede
AK
137 {
138 bResult = TRUE;
139 break;
140 }
141 if (dwId & GROUP_FLAG)
142 {
b576249a 143 if (CheckUserMembership(userId, dwId))
5039dede
AK
144 {
145 bResult = TRUE;
146 break;
147 }
148 }
149 }
150 DBFreeResult(hResult);
151 }
2d7ee2e0 152 DBConnectionPoolReleaseConnection(hdb);
b576249a 153 DBFreeStatement(hStmt);
5039dede
AK
154 return bResult;
155}
156
2d7ee2e0 157/**
158 * Agent table tool execution thread
159 */
5d3459af 160static void GetAgentTable(void *pArg)
5039dede 161{
b368969c 162 NXCPMessage msg;
b576249a 163 TCHAR *pszEnum, *pszRegEx, *pszLine, buffer[256];
5039dede 164 AgentConnection *pConn;
6a777a32 165 UINT32 dwResult, dwLen;
5039dede
AK
166 int *pnSubstrPos, nPos;
167 regex_t preg;
168 regmatch_t *pMatchList;
169 DB_RESULT hResult;
e31c8e60 170 Table table;
5039dede
AK
171
172 // Prepare data message
b368969c
VK
173 msg.setCode(CMD_TABLE_DATA);
174 msg.setId(((TOOL_STARTUP_INFO *)pArg)->dwRqId);
5039dede
AK
175
176 // Parse tool data. For agent table, it should have the following format:
177 // table_title<separator>enum<separator>matching_regexp
178 // where <separator> is a character with code 0x7F
179 pszEnum = _tcschr(((TOOL_STARTUP_INFO *)pArg)->pszToolData, _T('\x7F'));
180 if (pszEnum != NULL)
181 {
182 *pszEnum = 0;
183 pszEnum++;
184 pszRegEx = _tcschr(pszEnum, _T('\x7F'));
185 if (pszRegEx != NULL)
186 {
187 *pszRegEx = 0;
188 pszRegEx++;
189 }
190 }
e31c8e60 191 table.setTitle(((TOOL_STARTUP_INFO *)pArg)->pszToolData);
5039dede
AK
192
193 if ((pszEnum != NULL) && (pszRegEx != NULL))
194 {
195 // Load column information
2d7ee2e0 196 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
b576249a 197 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT col_name,col_format,col_substr FROM object_tools_table_columns WHERE tool_id=? ORDER BY col_number"));
1978e2c7 198 if (hStmt != NULL)
2d7ee2e0 199 {
1978e2c7 200 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, ((TOOL_STARTUP_INFO *)pArg)->toolId);
2d7ee2e0 201
1978e2c7
VK
202 hResult = DBSelectPrepared(hStmt);
203 if (hResult != NULL)
5039dede 204 {
6a777a32
VK
205 int numCols = DBGetNumRows(hResult);
206 if (numCols > 0)
5039dede 207 {
6a777a32
VK
208 pnSubstrPos = (int *)malloc(sizeof(int) * numCols);
209 for(int i = 0; i < numCols; i++)
1978e2c7
VK
210 {
211 DBGetField(hResult, i, 0, buffer, 256);
212 table.addColumn(buffer, DBGetFieldULong(hResult, i, 1));
213 pnSubstrPos[i] = DBGetFieldLong(hResult, i, 2);
214 }
215 if (_tregcomp(&preg, pszRegEx, REG_EXTENDED | REG_ICASE) == 0)
5039dede 216 {
1978e2c7
VK
217 pConn = ((TOOL_STARTUP_INFO *)pArg)->pNode->createAgentConnection();
218 if (pConn != NULL)
5039dede 219 {
6a777a32
VK
220 StringList *values;
221 dwResult = pConn->getList(pszEnum, &values);
1978e2c7 222 if (dwResult == ERR_SUCCESS)
5039dede 223 {
6a777a32
VK
224 pMatchList = (regmatch_t *)malloc(sizeof(regmatch_t) * (numCols + 1));
225 for(int i = 0; i < values->size(); i++)
5039dede 226 {
6a777a32
VK
227 const TCHAR *line = values->get(i);
228 if (_tregexec(&preg, pszLine, numCols + 1, pMatchList, 0) == 0)
5039dede 229 {
1978e2c7
VK
230 table.addRow();
231
232 // Write data for current row into message
6a777a32 233 for(int j = 0; j < numCols; j++)
1978e2c7
VK
234 {
235 nPos = pnSubstrPos[j];
236 dwLen = pMatchList[nPos].rm_eo - pMatchList[nPos].rm_so;
237 memcpy(buffer, &pszLine[pMatchList[nPos].rm_so], dwLen * sizeof(TCHAR));
238 buffer[dwLen] = 0;
239 table.set(j, buffer);
240 }
5039dede 241 }
5039dede 242 }
1978e2c7 243 free(pMatchList);
6a777a32 244 delete values;
5039dede 245
1978e2c7
VK
246 msg.setField(VID_RCC, RCC_SUCCESS);
247 table.fillMessage(msg, 0, -1);
248 }
249 else
250 {
251 msg.setField(VID_RCC, (dwResult == ERR_UNKNOWN_PARAMETER) ? RCC_UNKNOWN_PARAMETER : RCC_COMM_FAILURE);
252 }
253 pConn->decRefCount();
5039dede
AK
254 }
255 else
256 {
1978e2c7 257 msg.setField(VID_RCC, RCC_COMM_FAILURE);
5039dede 258 }
1978e2c7 259 regfree(&preg);
5039dede 260 }
1978e2c7 261 else // Regexp compilation failed
5039dede 262 {
1978e2c7 263 msg.setField(VID_RCC, RCC_BAD_REGEXP);
5039dede 264 }
1978e2c7 265 free(pnSubstrPos);
5039dede 266 }
1978e2c7 267 else // No columns defined
5039dede 268 {
1978e2c7 269 msg.setField(VID_RCC, RCC_INTERNAL_ERROR);
5039dede 270 }
1978e2c7 271 DBFreeResult(hResult);
5039dede 272 }
1978e2c7 273 else // Cannot load column info from DB
5039dede 274 {
1978e2c7 275 msg.setField(VID_RCC, RCC_DB_FAILURE);
5039dede 276 }
1978e2c7 277 DBFreeStatement(hStmt);
5039dede 278 }
1978e2c7 279 else
5039dede 280 {
b368969c 281 msg.setField(VID_RCC, RCC_DB_FAILURE);
5039dede 282 }
2d7ee2e0 283 DBConnectionPoolReleaseConnection(hdb);
1978e2c7 284 }
5039dede
AK
285 else
286 {
b368969c 287 msg.setField(VID_RCC, RCC_INTERNAL_ERROR);
5039dede
AK
288 }
289
1978e2c7 290 // Send response to client
e05b1945
VK
291 ((TOOL_STARTUP_INFO *)pArg)->pSession->sendMessage(&msg);
292 ((TOOL_STARTUP_INFO *)pArg)->pSession->decRefCount();
6a777a32 293 free(((TOOL_STARTUP_INFO *)pArg)->pszToolData);
5039dede 294 free(pArg);
5039dede
AK
295}
296
2d7ee2e0 297/**
298 * Add SNMP variable value to results list
299 */
5d3459af 300static void AddSNMPResult(Table *table, int column, SNMP_Variable *pVar, LONG nFmt, Node *pNode)
5039dede 301{
b576249a 302 TCHAR buffer[4096];
5039dede 303 Interface *pInterface;
967893bb 304 UINT32 dwIndex;
4f131f2f 305 bool convert;
5039dede
AK
306
307 if (pVar != NULL)
308 {
309 switch(nFmt)
310 {
311 case CFMT_MAC_ADDR:
b576249a 312 pVar->getValueAsMACAddr(buffer);
5039dede
AK
313 break;
314 case CFMT_IP_ADDR:
b576249a 315 pVar->getValueAsIPAddr(buffer);
5039dede
AK
316 break;
317 case CFMT_IFINDEX: // Column is an interface index, convert to interface name
e0471fad 318 dwIndex = pVar->getValueAsUInt();
c75e9ee4 319 pInterface = pNode->findInterfaceByIndex(dwIndex);
5039dede
AK
320 if (pInterface != NULL)
321 {
b576249a 322 nx_strncpy(buffer, pInterface->getName(), 4096);
5039dede
AK
323 }
324 else
325 {
326 if (dwIndex == 0) // Many devices uses index 0 for internal MAC, etc.
b576249a 327 _tcscpy(buffer, _T("INTERNAL"));
5039dede 328 else
b576249a 329 _sntprintf(buffer, 64, _T("%d"), dwIndex);
5039dede
AK
330 }
331 break;
332 default:
4f131f2f 333 convert = true;
b576249a 334 pVar->getValueAsPrintableString(buffer, 4096, &convert);
5039dede
AK
335 break;
336 }
337 }
338 else
339 {
b576249a 340 buffer[0] = 0;
5039dede 341 }
b576249a 342 table->set(column, buffer);
5039dede
AK
343}
344
2d7ee2e0 345/**
346 * Handler for SNMP table enumeration
347 */
9c5ebc32 348static UINT32 TableHandler(SNMP_Variable *pVar, SNMP_Transport *pTransport, void *pArg)
5039dede
AK
349{
350 TCHAR szOid[MAX_OID_LEN * 4], szSuffix[MAX_OID_LEN * 4];
351 SNMP_PDU *pRqPDU, *pRespPDU;
e0471fad
VK
352 UINT32 i, dwResult, pdwVarName[MAX_OID_LEN];
353 size_t nameLen;
5039dede
AK
354
355 // Create index (OID suffix) for columns
356 if (((SNMP_ENUM_ARGS *)pArg)->dwFlags & TF_SNMP_INDEXED_BY_VALUE)
357 {
e0471fad 358 _sntprintf(szSuffix, MAX_OID_LEN * 4, _T(".%u"), pVar->getValueAsUInt());
5039dede
AK
359 }
360 else
361 {
e0471fad 362 nameLen = SNMPParseOID(((SNMP_ENUM_ARGS *)pArg)->ppszOidList[0], pdwVarName, MAX_OID_LEN);
9ceab287
VK
363 const SNMP_ObjectId& oid = pVar->getName();
364 SNMPConvertOIDToText(oid.length() - nameLen, (UINT32 *)&(oid.value())[nameLen], szSuffix, MAX_OID_LEN * 4);
5039dede
AK
365 }
366
367 // Get values for other columns
43832c69 368 if (((SNMP_ENUM_ARGS *)pArg)->dwNumCols > 1)
5039dede 369 {
43832c69
VK
370 pRqPDU = new SNMP_PDU(SNMP_GET_REQUEST, SnmpNewRequestId(), pTransport->getSnmpVersion());
371 for(i = 1; i < ((SNMP_ENUM_ARGS *)pArg)->dwNumCols; i++)
5039dede 372 {
43832c69
VK
373 _tcscpy(szOid, ((SNMP_ENUM_ARGS *)pArg)->ppszOidList[i]);
374 _tcscat(szOid, szSuffix);
375 nameLen = SNMPParseOID(szOid, pdwVarName, MAX_OID_LEN);
376 if (nameLen != 0)
377 {
378 pRqPDU->bindVariable(new SNMP_Variable(pdwVarName, nameLen));
379 }
5039dede 380 }
5039dede 381
43832c69
VK
382 dwResult = pTransport->doRequest(pRqPDU, &pRespPDU, SnmpGetDefaultTimeout(), 3);
383 delete pRqPDU;
384 if (dwResult == SNMP_ERR_SUCCESS)
5039dede 385 {
43832c69
VK
386 if ((pRespPDU->getNumVariables() > 0) &&
387 (pRespPDU->getErrorCode() == SNMP_PDU_ERR_SUCCESS))
388 {
389 ((SNMP_ENUM_ARGS *)pArg)->table->addRow();
5039dede 390
43832c69
VK
391 // Add first column to results
392 AddSNMPResult(((SNMP_ENUM_ARGS *)pArg)->table, 0, pVar,
393 ((SNMP_ENUM_ARGS *)pArg)->pnFormatList[0],
5039dede 394 ((SNMP_ENUM_ARGS *)pArg)->pNode);
43832c69
VK
395
396 for(i = 1; i < ((SNMP_ENUM_ARGS *)pArg)->dwNumCols; i++)
397 AddSNMPResult(((SNMP_ENUM_ARGS *)pArg)->table, i,
398 pRespPDU->getVariable(i - 1),
399 ((SNMP_ENUM_ARGS *)pArg)->pnFormatList[i],
400 ((SNMP_ENUM_ARGS *)pArg)->pNode);
401 }
402 delete pRespPDU;
5039dede 403 }
43832c69
VK
404 }
405 else // single column
406 {
407 ((SNMP_ENUM_ARGS *)pArg)->table->addRow();
408
409 // Add first column to results
410 AddSNMPResult(((SNMP_ENUM_ARGS *)pArg)->table, 0, pVar,
411 ((SNMP_ENUM_ARGS *)pArg)->pnFormatList[0],
412 ((SNMP_ENUM_ARGS *)pArg)->pNode);
413
414 dwResult = SNMP_ERR_SUCCESS;
5039dede
AK
415 }
416 return dwResult;
417}
418
2d7ee2e0 419/**
420 * SNMP table tool execution thread
421 */
5d3459af 422static void GetSNMPTable(void *pArg)
5039dede 423{
b368969c 424 NXCPMessage msg;
967893bb 425 UINT32 i, dwNumCols;
b576249a 426 TCHAR buffer[256];
5039dede 427 SNMP_ENUM_ARGS args;
e31c8e60 428 Table table;
5039dede 429
2d7ee2e0 430 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
431
5039dede 432 // Prepare data message
b368969c
VK
433 msg.setCode(CMD_TABLE_DATA);
434 msg.setId(((TOOL_STARTUP_INFO *)pArg)->dwRqId);
5039dede 435
b576249a 436 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT col_name,col_oid,col_format FROM object_tools_table_columns WHERE tool_id=? ORDER BY col_number"));
1978e2c7 437 if (hStmt != NULL)
2d7ee2e0 438 {
1978e2c7 439 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, ((TOOL_STARTUP_INFO *)pArg)->toolId);
2d7ee2e0 440
1978e2c7
VK
441 DB_RESULT hResult = DBSelectPrepared(hStmt);
442 if (hResult != NULL)
5039dede 443 {
1978e2c7
VK
444 dwNumCols = DBGetNumRows(hResult);
445 if (dwNumCols > 0)
5039dede 446 {
1978e2c7
VK
447 args.dwNumCols = dwNumCols;
448 args.ppszOidList = (TCHAR **)malloc(sizeof(TCHAR *) * dwNumCols);
449 args.pnFormatList = (LONG *)malloc(sizeof(LONG) * dwNumCols);
450 args.dwFlags = ((TOOL_STARTUP_INFO *)pArg)->dwFlags;
451 args.pNode = ((TOOL_STARTUP_INFO *)pArg)->pNode;
452 args.table = &table;
453 for(i = 0; i < dwNumCols; i++)
454 {
455 DBGetField(hResult, i, 0, buffer, 256);
456 args.ppszOidList[i] = DBGetField(hResult, i, 1, NULL, 0);
457 args.pnFormatList[i] = DBGetFieldLong(hResult, i, 2);
458 table.addColumn(buffer, args.pnFormatList[i]);
459 }
5039dede 460
1978e2c7
VK
461 // Enumerate
462 if (((TOOL_STARTUP_INFO *)pArg)->pNode->callSnmpEnumerate(args.ppszOidList[0], TableHandler, &args) == SNMP_ERR_SUCCESS)
463 {
464 // Fill in message with results
465 msg.setField(VID_RCC, RCC_SUCCESS);
466 table.setTitle(((TOOL_STARTUP_INFO *)pArg)->pszToolData);
467 table.fillMessage(msg, 0, -1);
468 }
469 else
470 {
471 msg.setField(VID_RCC, RCC_SNMP_ERROR);
472 }
473
474 // Cleanup
475 for(i = 0; i < dwNumCols; i++)
476 safe_free(args.ppszOidList[i]);
477 free(args.ppszOidList);
478 free(args.pnFormatList);
5039dede
AK
479 }
480 else
481 {
1978e2c7 482 msg.setField(VID_RCC, RCC_INTERNAL_ERROR);
5039dede 483 }
1978e2c7 484 DBFreeResult(hResult);
5039dede
AK
485 }
486 else
487 {
1978e2c7 488 msg.setField(VID_RCC, RCC_DB_FAILURE);
5039dede 489 }
1978e2c7 490 DBFreeStatement(hStmt);
5039dede
AK
491 }
492 else
493 {
b368969c 494 msg.setField(VID_RCC, RCC_DB_FAILURE);
5039dede 495 }
2d7ee2e0 496 DBConnectionPoolReleaseConnection(hdb);
2d7ee2e0 497
1978e2c7 498 // Send response to client
e05b1945
VK
499 ((TOOL_STARTUP_INFO *)pArg)->pSession->sendMessage(&msg);
500 ((TOOL_STARTUP_INFO *)pArg)->pSession->decRefCount();
5039dede
AK
501 safe_free(((TOOL_STARTUP_INFO *)pArg)->pszToolData);
502 free(pArg);
5039dede
AK
503}
504
2d7ee2e0 505/**
506 * Execute table tool
507 */
b576249a 508UINT32 ExecuteTableTool(UINT32 toolId, Node *pNode, UINT32 dwRqId, ClientSession *pSession)
5039dede
AK
509{
510 LONG nType;
967893bb 511 UINT32 dwRet = RCC_SUCCESS;
5039dede 512 TOOL_STARTUP_INFO *pStartup;
5039dede
AK
513 DB_RESULT hResult;
514
2d7ee2e0 515 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
516
b576249a
VK
517 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT tool_type,tool_data,flags FROM object_tools WHERE tool_id=?"));
518 if (hStmt == NULL)
2d7ee2e0 519 {
520 DBConnectionPoolReleaseConnection(hdb);
521 return RCC_DB_FAILURE;
522 }
b576249a
VK
523 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
524 hResult = DBSelectPrepared(hStmt);
5039dede
AK
525 if (hResult != NULL)
526 {
527 if (DBGetNumRows(hResult) > 0)
528 {
529 nType = DBGetFieldLong(hResult, 0, 0);
530 if ((nType == TOOL_TYPE_TABLE_SNMP) || (nType == TOOL_TYPE_TABLE_AGENT))
531 {
e05b1945 532 pSession->incRefCount();
5039dede 533 pStartup = (TOOL_STARTUP_INFO *)malloc(sizeof(TOOL_STARTUP_INFO));
b576249a 534 pStartup->toolId = toolId;
5039dede
AK
535 pStartup->dwRqId = dwRqId;
536 pStartup->pszToolData = DBGetField(hResult, 0, 1, NULL, 0);
5039dede
AK
537 pStartup->dwFlags = DBGetFieldULong(hResult, 0, 2);
538 pStartup->pNode = pNode;
539 pStartup->pSession = pSession;
5d3459af 540 ThreadPoolExecute(g_mainThreadPool, (nType == TOOL_TYPE_TABLE_SNMP) ? GetSNMPTable : GetAgentTable, pStartup);
5039dede
AK
541 }
542 else
543 {
544 dwRet = RCC_INCOMPATIBLE_OPERATION;
545 }
546 }
547 else
548 {
549 dwRet = RCC_INVALID_TOOL_ID;
550 }
551 DBFreeResult(hResult);
552 }
553 else
554 {
555 dwRet = RCC_DB_FAILURE;
556 }
2d7ee2e0 557
558 DBConnectionPoolReleaseConnection(hdb);
b576249a 559 DBFreeStatement(hStmt);
5039dede
AK
560 return dwRet;
561}
562
563
2d7ee2e0 564/**
565 * Delete object tool from database
566 */
b576249a 567UINT32 DeleteObjectToolFromDB(UINT32 toolId)
5039dede 568{
2d7ee2e0 569 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
5039dede 570
2d7ee2e0 571 if (!DBBegin(hdb))
572 {
573 DBConnectionPoolReleaseConnection(hdb);
574 return RCC_DB_FAILURE;
575 }
576
b576249a
VK
577 DB_STATEMENT hStmt = DBPrepare(hdb, _T("DELETE FROM object_tools WHERE tool_id=?"));
578 if (hStmt == NULL)
579 return ReturnDBFailure(hdb, hStmt);
580 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
581 if(!DBExecute(hStmt))
582 return ReturnDBFailure(hdb, hStmt);
583 DBFreeStatement(hStmt);
584
585 hStmt = DBPrepare(hdb, _T("DELETE FROM object_tools_acl WHERE tool_id=?"));
586 if (hStmt == NULL)
587 return ReturnDBFailure(hdb, hStmt);
588 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
589 if(!DBExecute(hStmt))
590 return ReturnDBFailure(hdb, hStmt);
591 DBFreeStatement(hStmt);
592
593 hStmt = DBPrepare(hdb, _T("DELETE FROM object_tools_table_columns WHERE tool_id=?"));
594 if (hStmt == NULL)
595 return ReturnDBFailure(hdb, hStmt);
596 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
597 if(!DBExecute(hStmt))
598 return ReturnDBFailure(hdb, hStmt);
599 DBFreeStatement(hStmt);
600
601 hStmt = DBPrepare(hdb, _T("DELETE FROM object_tools_input_fields WHERE tool_id=?"));
602 if (hStmt == NULL)
603 return ReturnDBFailure(hdb, hStmt);
604 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
605 if(!DBExecute(hStmt))
606 return ReturnDBFailure(hdb, hStmt);
607 DBFreeStatement(hStmt);
2d7ee2e0 608
609 DBCommit(hdb);
610 DBConnectionPoolReleaseConnection(hdb);
b576249a 611 NotifyClientSessions(NX_NOTIFY_OBJTOOL_DELETED, toolId);
5039dede
AK
612 return RCC_SUCCESS;
613}
614
b4c2a628 615/**
03f4f212 616 * Change Object Tool Disable status to opposit
617 */
6f8e39e5 618UINT32 ChangeObjectToolStatus(UINT32 toolId, bool enabled)
03f4f212 619{
6f8e39e5 620 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
03f4f212 621
b576249a
VK
622 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT flags FROM object_tools WHERE tool_id=?"));
623 if (hStmt == NULL)
03f4f212 624 {
6f8e39e5
VK
625 DBConnectionPoolReleaseConnection(hdb);
626 return RCC_DB_FAILURE;
627 }
628
629 UINT32 rcc = RCC_SUCCESS;
630 UINT32 flags = 0;
631
b576249a
VK
632 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
633 DB_RESULT hResult = DBSelectPrepared(hStmt);
6f8e39e5
VK
634 if (hResult != NULL)
635 {
636 flags = DBGetFieldULong(hResult, 0, 0);
637 DBFreeResult(hResult);
03f4f212 638 }
639 else
640 {
6f8e39e5 641 rcc = RCC_DB_FAILURE;
03f4f212 642 }
b576249a 643 DBFreeStatement(hStmt);
03f4f212 644
6f8e39e5
VK
645 if (rcc == RCC_SUCCESS)
646 {
647 if (enabled)
648 {
649 flags &= ~TF_DISABLED;
650 }
651 else
652 {
653 flags |= TF_DISABLED;
654 }
655 rcc = RCC_DB_FAILURE;
b576249a
VK
656 hStmt = DBPrepare(hdb, _T("UPDATE object_tools SET flags=? WHERE tool_id=?"));
657 if (hStmt != NULL)
6f8e39e5 658 {
b576249a
VK
659 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, flags);
660 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, toolId);
661 if (DBExecute(hStmt))
6f8e39e5
VK
662 {
663 NotifyClientSessions(NX_NOTIFY_OBJTOOLS_CHANGED, toolId);
664 rcc = RCC_SUCCESS;
665 }
b576249a 666 DBFreeStatement(hStmt);
6f8e39e5
VK
667 }
668 }
2d7ee2e0 669
670 DBConnectionPoolReleaseConnection(hdb);
6f8e39e5 671 return rcc;
03f4f212 672}
673
674/**
2d7ee2e0 675 * Update/Insert object tool from NXCP message
b4c2a628 676 */
b368969c 677UINT32 UpdateObjectToolFromMessage(NXCPMessage *pMsg)
5039dede 678{
b576249a
VK
679 TCHAR buffer[MAX_DB_STRING];
680 UINT32 i, aclSize, *pdwAcl;
2d7ee2e0 681
682 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
683
684 if (!DBBegin(hdb))
685 {
686 DBConnectionPoolReleaseConnection(hdb);
687 return RCC_DB_FAILURE;
688 }
5039dede 689
5039dede 690 // Insert or update common properties
b368969c 691 int nType = pMsg->getFieldAsUInt16(VID_TOOL_TYPE);
b576249a 692 UINT32 toolId = pMsg->getFieldAsUInt32(VID_TOOL_ID);
271e3971
VK
693 bool newTool = false;
694 DB_STATEMENT hStmt;
b576249a 695 if (IsDatabaseRecordExist(hdb, _T("object_tools"), _T("tool_id"), toolId))
2d7ee2e0 696 {
271e3971 697 hStmt = DBPrepare(hdb, _T("UPDATE object_tools SET tool_name=?,tool_type=?,")
2d7ee2e0 698 _T("tool_data=?,description=?,flags=?,")
4b70cb26 699 _T("tool_filter=?,confirmation_text=?,command_name=?,")
d4ce93a2 700 _T("command_short_name=?,icon=? ")
2d7ee2e0 701 _T("WHERE tool_id=?"));
2d7ee2e0 702 }
5039dede 703 else
2d7ee2e0 704 {
271e3971 705 hStmt = DBPrepare(hdb, _T("INSERT INTO object_tools (tool_name,tool_type,")
4b70cb26 706 _T("tool_data,description,flags,tool_filter,")
d4ce93a2 707 _T("confirmation_text,command_name,command_short_name,")
271e3971
VK
708 _T("icon,tool_id,guid) VALUES ")
709 _T("(?,?,?,?,?,?,?,?,?,?,?,?)"));
710 newTool = true;
2d7ee2e0 711 }
271e3971
VK
712 if (hStmt == NULL)
713 return ReturnDBFailure(hdb, hStmt);
714
715 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, pMsg->getFieldAsString(VID_NAME), DB_BIND_DYNAMIC);
716 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, nType);
717 DBBind(hStmt, 3, DB_SQLTYPE_TEXT, pMsg->getFieldAsString(VID_TOOL_DATA), DB_BIND_DYNAMIC);
718 DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, pMsg->getFieldAsString(VID_DESCRIPTION), DB_BIND_DYNAMIC);
719 DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, pMsg->getFieldAsUInt32(VID_FLAGS));
720 DBBind(hStmt, 6, DB_SQLTYPE_TEXT, pMsg->getFieldAsString(VID_TOOL_FILTER), DB_BIND_DYNAMIC);
721 DBBind(hStmt, 7, DB_SQLTYPE_VARCHAR, pMsg->getFieldAsString(VID_CONFIRMATION_TEXT), DB_BIND_DYNAMIC);
722 DBBind(hStmt, 8, DB_SQLTYPE_VARCHAR, pMsg->getFieldAsString(VID_COMMAND_NAME), DB_BIND_DYNAMIC);
723 DBBind(hStmt, 9, DB_SQLTYPE_VARCHAR, pMsg->getFieldAsString(VID_COMMAND_SHORT_NAME), DB_BIND_DYNAMIC);
ac14e3e6
VK
724
725 size_t size;
ca0a165b 726 const BYTE *imageData = pMsg->getBinaryFieldPtr(VID_IMAGE_DATA, &size);
ac14e3e6
VK
727 if (size > 0)
728 {
03ff6e20 729 TCHAR *imageHexData = (TCHAR *)malloc((size * 2 + 1) * sizeof(TCHAR));
ac14e3e6 730 BinToStr(imageData, size, imageHexData);
271e3971 731 DBBind(hStmt, 10, DB_SQLTYPE_TEXT, imageHexData, DB_BIND_DYNAMIC);
ac14e3e6
VK
732 }
733 else
734 {
271e3971 735 DBBind(hStmt, 10, DB_SQLTYPE_TEXT, _T(""), DB_BIND_STATIC);
ac14e3e6 736 }
2d7ee2e0 737
b576249a 738 DBBind(hStmt, 11, DB_SQLTYPE_INTEGER, toolId);
271e3971
VK
739 if (newTool)
740 {
999945fa 741 DBBind(hStmt, 12, DB_SQLTYPE_VARCHAR, uuid::generate());
271e3971 742 }
2d7ee2e0 743
271e3971
VK
744 if (!DBExecute(hStmt))
745 return ReturnDBFailure(hdb, hStmt);
746 DBFreeStatement(hStmt);
5039dede
AK
747
748 // Update ACL
271e3971
VK
749 hStmt = DBPrepare(hdb, _T("DELETE FROM object_tools_acl WHERE tool_id=?"));
750 if (hStmt == NULL)
751 return ReturnDBFailure(hdb, hStmt);
b576249a 752 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
271e3971
VK
753 if(!DBExecute(hStmt))
754 return ReturnDBFailure(hdb, hStmt);
755 DBFreeStatement(hStmt);
2d7ee2e0 756
b576249a
VK
757 aclSize = pMsg->getFieldAsUInt32(VID_ACL_SIZE);
758 if (aclSize > 0)
5039dede 759 {
b576249a
VK
760 pdwAcl = (UINT32 *)malloc(sizeof(UINT32) * aclSize);
761 pMsg->getFieldAsInt32Array(VID_ACL, aclSize, pdwAcl);
762 for(i = 0; i < aclSize; i++)
5039dede 763 {
271e3971
VK
764 hStmt = DBPrepare(hdb, _T("INSERT INTO object_tools_acl (tool_id,user_id) VALUES (?,?)"));
765 if (hStmt == NULL)
766 return ReturnDBFailure(hdb, hStmt);
b576249a 767 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
271e3971
VK
768 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, pdwAcl[i]);
769 if(!DBExecute(hStmt))
770 return ReturnDBFailure(hdb, hStmt);
771 DBFreeStatement(hStmt);
5039dede
AK
772 }
773 }
774
775 // Update columns configuration
271e3971
VK
776 hStmt = DBPrepare(hdb, _T("DELETE FROM object_tools_table_columns WHERE tool_id=?"));
777 if (hStmt == NULL)
778 return ReturnDBFailure(hdb, hStmt);
b576249a 779 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
2d7ee2e0 780
b576249a 781 if (!DBExecute(hStmt))
271e3971
VK
782 return ReturnDBFailure(hdb, hStmt);
783 DBFreeStatement(hStmt);
2d7ee2e0 784
b576249a 785 if ((nType == TOOL_TYPE_TABLE_SNMP) || (nType == TOOL_TYPE_TABLE_AGENT))
5039dede 786 {
967893bb 787 UINT32 dwId, dwNumColumns;
5039dede 788
b368969c 789 dwNumColumns = pMsg->getFieldAsUInt16(VID_NUM_COLUMNS);
271e3971 790 if (dwNumColumns > 0)
5039dede 791 {
271e3971 792 hStmt = DBPrepare(hdb, _T("INSERT INTO object_tools_table_columns (tool_id,")
2d7ee2e0 793 _T("col_number,col_name,col_oid,col_format,col_substr) ")
794 _T("VALUES (?,?,?,?,?,?)"));
271e3971
VK
795 if (hStmt == NULL)
796 return ReturnDBFailure(hdb, hStmt);
797
798 for(i = 0, dwId = VID_COLUMN_INFO_BASE; i < dwNumColumns; i++)
799 {
b576249a 800 pMsg->getFieldAsString(dwId++, buffer, MAX_DB_STRING);
271e3971 801
b576249a 802 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
271e3971 803 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, i);
b576249a 804 DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, buffer, DB_BIND_STATIC);
271e3971
VK
805 DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, pMsg->getFieldAsString(dwId++), DB_BIND_DYNAMIC);
806 DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, pMsg->getFieldAsUInt16(dwId++));
807 DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, pMsg->getFieldAsUInt16(dwId++));
808
809 if (!DBExecute(hStmt))
810 return ReturnDBFailure(hdb, hStmt);
811 }
812 DBFreeStatement(hStmt);
5039dede
AK
813 }
814 }
815
b576249a
VK
816 hStmt = DBPrepare(hdb, _T("DELETE FROM object_tools_input_fields WHERE tool_id=?"));
817 if (hStmt == NULL)
818 return ReturnDBFailure(hdb, hStmt);
819 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
820
821 if (!DBExecute(hStmt))
822 return ReturnDBFailure(hdb, hStmt);
823 DBFreeStatement(hStmt);
824
825 UINT32 numFields = pMsg->getFieldAsUInt16(VID_NUM_FIELDS);
826 if (numFields > 0)
827 {
203cb23c 828 hStmt = DBPrepare(hdb, _T("INSERT INTO object_tools_input_fields (tool_id,name,input_type,display_name,config,sequence_num) VALUES (?,?,?,?,?,?)"));
b576249a
VK
829 if (hStmt == NULL)
830 return ReturnDBFailure(hdb, hStmt);
831 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
832
833 UINT32 fieldId = VID_FIELD_LIST_BASE;
834 for(i = 0; i < numFields; i++)
835 {
836 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, pMsg->getFieldAsString(fieldId++), DB_BIND_DYNAMIC);
837 DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, pMsg->getFieldAsUInt16(fieldId++));
838 DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, pMsg->getFieldAsString(fieldId++), DB_BIND_DYNAMIC);
839 DBBind(hStmt, 5, DB_SQLTYPE_TEXT, pMsg->getFieldAsString(fieldId++), DB_BIND_DYNAMIC);
203cb23c
VK
840 DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, pMsg->getFieldAsInt16(fieldId++));
841 fieldId += 5;
b576249a
VK
842
843 if (!DBExecute(hStmt))
844 return ReturnDBFailure(hdb, hStmt);
845 }
846 }
847
2d7ee2e0 848 DBCommit(hdb);
849 DBConnectionPoolReleaseConnection(hdb);
b576249a 850 NotifyClientSessions(NX_NOTIFY_OBJTOOLS_CHANGED, toolId);
5039dede
AK
851 return RCC_SUCCESS;
852}
4c3cc965
VK
853
854/**
271e3971
VK
855 * Import failure exit
856 */
c7a9d87c 857static bool ImportFailure(DB_HANDLE hdb, DB_STATEMENT hStmt)
271e3971
VK
858{
859 if (hStmt != NULL)
860 DBFreeStatement(hStmt);
861 DBRollback(hdb);
862 DBConnectionPoolReleaseConnection(hdb);
c7a9d87c 863 DbgPrintf(4, _T("ImportObjectTool: database failure"));
271e3971
VK
864 return false;
865}
866
867/**
868 * Import object tool
869 */
870bool ImportObjectTool(ConfigEntry *config)
871{
872 const TCHAR *guid = config->getSubEntryValue(_T("guid"));
873 if (guid == NULL)
874 {
875 DbgPrintf(4, _T("ImportObjectTool: missing GUID"));
876 return false;
877 }
878
879 uuid_t temp;
999945fa 880 if (_uuid_parse(guid, temp) == -1)
271e3971
VK
881 {
882 DbgPrintf(4, _T("ImportObjectTool: GUID (%s) is invalid"), guid);
883 return false;
884 }
885
886 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
887
888 // Step 1: find existing tool ID by GUID
889 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT tool_id FROM object_tools WHERE guid=?"));
890 if (hStmt == NULL)
891 {
c7a9d87c 892 return ImportFailure(hdb, NULL);
271e3971
VK
893 }
894
895 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, guid, DB_BIND_STATIC);
896 DB_RESULT hResult = DBSelectPrepared(hStmt);
897 if (hResult == NULL)
898 {
c7a9d87c 899 return ImportFailure(hdb, hStmt);
271e3971
VK
900 }
901
902 UINT32 toolId;
903 if (DBGetNumRows(hResult) > 0)
904 {
905 toolId = DBGetFieldULong(hResult, 0, 0);
906 }
907 else
908 {
909 toolId = 0;
910 }
911 DBFreeResult(hResult);
912 DBFreeStatement(hStmt);
913
914 // Step 2: create or update tool record
915 if (!DBBegin(hdb))
916 {
c7a9d87c 917 return ImportFailure(hdb, NULL);
271e3971
VK
918 }
919
920 if (toolId != 0)
921 {
922 hStmt = DBPrepare(hdb, _T("UPDATE object_tools SET tool_name=?,tool_type=?,")
923 _T("tool_data=?,description=?,flags=?,")
924 _T("tool_filter=?,confirmation_text=?,command_name=?,")
925 _T("command_short_name=?,icon=? ")
926 _T("WHERE tool_id=?"));
927 }
928 else
929 {
930 hStmt = DBPrepare(hdb, _T("INSERT INTO object_tools (tool_name,tool_type,")
931 _T("tool_data,description,flags,tool_filter,")
932 _T("confirmation_text,command_name,command_short_name,")
933 _T("icon,tool_id,guid) VALUES ")
934 _T("(?,?,?,?,?,?,?,?,?,?,?,?)"));
935 }
936
937 if (hStmt == NULL)
938 {
c7a9d87c 939 return ImportFailure(hdb, NULL);
271e3971
VK
940 }
941
942 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, config->getSubEntryValue(_T("name")), DB_BIND_STATIC);
943 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, config->getSubEntryValueAsInt(_T("type")));
944 DBBind(hStmt, 3, DB_SQLTYPE_TEXT, config->getSubEntryValue(_T("data")), DB_BIND_STATIC);
945 DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, config->getSubEntryValue(_T("description")), DB_BIND_STATIC);
946 DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, config->getSubEntryValueAsUInt(_T("flags")));
947 DBBind(hStmt, 6, DB_SQLTYPE_TEXT, config->getSubEntryValue(_T("filter")), DB_BIND_STATIC);
948 DBBind(hStmt, 7, DB_SQLTYPE_VARCHAR, config->getSubEntryValue(_T("confirmation")), DB_BIND_STATIC);
949 DBBind(hStmt, 8, DB_SQLTYPE_VARCHAR, config->getSubEntryValue(_T("commandName")), DB_BIND_STATIC);
950 DBBind(hStmt, 9, DB_SQLTYPE_VARCHAR, config->getSubEntryValue(_T("commandShortName")), DB_BIND_STATIC);
951 DBBind(hStmt, 10, DB_SQLTYPE_TEXT, config->getSubEntryValue(_T("image")), DB_BIND_STATIC);
952 if (toolId == 0)
953 {
954 toolId = CreateUniqueId(IDG_OBJECT_TOOL);
955 DBBind(hStmt, 11, DB_SQLTYPE_INTEGER, toolId);
956 DBBind(hStmt, 12, DB_SQLTYPE_VARCHAR, guid, DB_BIND_STATIC);
957 }
958 else
959 {
960 DBBind(hStmt, 11, DB_SQLTYPE_INTEGER, toolId);
961 }
962
963 if (!DBExecute(hStmt))
c7a9d87c 964 return ImportFailure(hdb, hStmt);
271e3971
VK
965 DBFreeStatement(hStmt);
966
967 // Update ACL
968 hStmt = DBPrepare(hdb, _T("DELETE FROM object_tools_acl WHERE tool_id=?"));
969 if (hStmt == NULL)
c7a9d87c 970 return ImportFailure(hdb, hStmt);
271e3971
VK
971 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
972 if (!DBExecute(hStmt))
c7a9d87c 973 return ImportFailure(hdb, hStmt);
271e3971
VK
974 DBFreeStatement(hStmt);
975
976 // Default ACL for imported tools - accessible by everyone
977 hStmt = DBPrepare(hdb, _T("INSERT INTO object_tools_acl (tool_id,user_id) VALUES (?,?)"));
978 if (hStmt == NULL)
c7a9d87c 979 return ImportFailure(hdb, hStmt);
271e3971
VK
980 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
981 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, GROUP_EVERYONE);
982 if (!DBExecute(hStmt))
c7a9d87c 983 return ImportFailure(hdb, hStmt);
271e3971
VK
984 DBFreeStatement(hStmt);
985
986 // Update columns configuration
987 hStmt = DBPrepare(hdb, _T("DELETE FROM object_tools_table_columns WHERE tool_id=?"));
988 if (hStmt == NULL)
c7a9d87c 989 return ImportFailure(hdb, hStmt);
271e3971
VK
990 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
991
992 if (!DBExecute(hStmt))
c7a9d87c 993 return ImportFailure(hdb, hStmt);
271e3971
VK
994 DBFreeStatement(hStmt);
995
996 int toolType = config->getSubEntryValueAsInt(_T("type"));
b576249a 997 if ((toolType == TOOL_TYPE_TABLE_SNMP) || (toolType == TOOL_TYPE_TABLE_AGENT))
271e3971
VK
998 {
999 ConfigEntry *root = config->findEntry(_T("columns"));
1000 if (root != NULL)
1001 {
1002 ObjectArray<ConfigEntry> *columns = root->getOrderedSubEntries(_T("column#*"));
1003 if (columns->size() > 0)
1004 {
1005 hStmt = DBPrepare(hdb, _T("INSERT INTO object_tools_table_columns (tool_id,")
1006 _T("col_number,col_name,col_oid,col_format,col_substr) ")
1007 _T("VALUES (?,?,?,?,?,?)"));
1008 if (hStmt == NULL)
c7a9d87c 1009 return ImportFailure(hdb, hStmt);
271e3971
VK
1010
1011 for(int i = 0; i < columns->size(); i++)
1012 {
1013 ConfigEntry *c = columns->get(i);
1014 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
1015 DBBind(hStmt, 2, DB_SQLTYPE_INTEGER, (INT32)i);
1016 DBBind(hStmt, 3, DB_SQLTYPE_VARCHAR, c->getSubEntryValue(_T("name")), DB_BIND_STATIC);
1017 DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, c->getSubEntryValue(_T("oid")), DB_BIND_STATIC);
1018 DBBind(hStmt, 5, DB_SQLTYPE_INTEGER, (INT32)c->getSubEntryValueAsInt(_T("format")));
1019 DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, (INT32)c->getSubEntryValueAsInt(_T("captureGroup")));
1020
1021 if (!DBExecute(hStmt))
1022 {
1023 delete columns;
c7a9d87c 1024 return ImportFailure(hdb, hStmt);
271e3971
VK
1025 }
1026 }
1027 DBFreeStatement(hStmt);
1028 }
1029 delete columns;
1030 }
1031 }
1032
b576249a
VK
1033 ConfigEntry *inputFieldsRoot = config->findEntry(_T("inputFields"));
1034 if (inputFieldsRoot != NULL)
1035 {
1036 ObjectArray<ConfigEntry> *inputFields = inputFieldsRoot->getOrderedSubEntries(_T("inputField#*"));
1037 if (inputFields->size() > 0)
1038 {
b15db25d 1039 hStmt = DBPrepare(hdb, _T("INSERT INTO object_tools_input_fields (tool_id,name,input_type,display_name,config,sequence_num) VALUES (?,?,?,?,?,?)"));
b576249a
VK
1040 if (hStmt == NULL)
1041 return ImportFailure(hdb, hStmt);
1042
1043 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
1044 for(int i = 0; i < inputFields->size(); i++)
1045 {
1046 ConfigEntry *c = inputFields->get(i);
1047 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, c->getSubEntryValue(_T("name")), DB_BIND_STATIC);
1048 DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, (INT32)c->getSubEntryValueAsInt(_T("type")));
1049 DBBind(hStmt, 4, DB_SQLTYPE_VARCHAR, c->getSubEntryValue(_T("displayName")), DB_BIND_STATIC);
1050 DBBind(hStmt, 5, DB_SQLTYPE_TEXT, c->getSubEntryValue(_T("config")), DB_BIND_STATIC);
b15db25d 1051 DBBind(hStmt, 6, DB_SQLTYPE_INTEGER, (INT32)(i + 1));
b576249a
VK
1052
1053 if (!DBExecute(hStmt))
1054 {
1055 delete inputFields;
1056 return ImportFailure(hdb, hStmt);
1057 }
1058 }
1059 DBFreeStatement(hStmt);
1060 }
1061 delete inputFields;
1062 }
1063
271e3971
VK
1064 DBCommit(hdb);
1065 DBConnectionPoolReleaseConnection(hdb);
1066 NotifyClientSessions(NX_NOTIFY_OBJTOOLS_CHANGED, toolId);
1067 return true;
1068}
1069
1070/**
1071 * Create export records for object tool columns
1072 */
1073static void CreateObjectToolColumnExportRecords(DB_HANDLE hdb, String &xml, UINT32 id)
1074{
1075 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT col_number,col_name,col_oid,col_format,col_substr FROM object_tools_table_columns WHERE tool_id=?"));
1076 if (hStmt == NULL)
1077 return;
1078
1079 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, id);
1080 DB_RESULT hResult = DBSelectPrepared(hStmt);
1081 if (hResult != NULL)
1082 {
1083 int count = DBGetNumRows(hResult);
1084 if (count > 0)
1085 {
1086 xml.append(_T("\t\t\t<columns>\n"));
1087 for(int i = 0; i < count; i++)
1088 {
1089 xml.append(_T("\t\t\t\t<column id=\""));
1090 xml.append(DBGetFieldLong(hResult, i, 0) + 1);
1091 xml.append(_T("\">\n\t\t\t\t\t<name>"));
1092 xml.appendPreallocated(DBGetFieldForXML(hResult, i, 1));
1093 xml.append(_T("</name>\n\t\t\t\t\t<oid>"));
1094 xml.appendPreallocated(DBGetFieldForXML(hResult, i, 2));
1095 xml.append(_T("</oid>\n\t\t\t\t\t<format>"));
1096 xml.append(DBGetFieldLong(hResult, i, 3));
1097 xml.append(_T("</format>\n\t\t\t\t\t<captureGroup>"));
1098 xml.append(DBGetFieldLong(hResult, i, 4));
1099 xml.append(_T("</captureGroup>\n\t\t\t\t</column>\n"));
1100 }
1101 xml.append(_T("\t\t\t</columns>\n"));
1102 }
1103 DBFreeResult(hResult);
1104 }
1105
1106 DBFreeStatement(hStmt);
1107}
1108
1109/**
b576249a
VK
1110 * Create export records for object tool input fields
1111 */
1112static void CreateObjectToolInputFieldExportRecords(DB_HANDLE hdb, String &xml, UINT32 id)
1113{
1114 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT name,input_type,display_name,config FROM object_tools_input_fields WHERE tool_id=?"));
1115 if (hStmt == NULL)
1116 return;
1117
1118 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, id);
1119 DB_RESULT hResult = DBSelectPrepared(hStmt);
1120 if (hResult != NULL)
1121 {
1122 int count = DBGetNumRows(hResult);
1123 if (count > 0)
1124 {
1125 xml.append(_T("\t\t\t<inputFields>\n"));
1126 for(int i = 0; i < count; i++)
1127 {
1128 xml.append(_T("\t\t\t\t<inputField id=\""));
1129 xml.append(i + 1);
1130 xml.append(_T("\">\n\t\t\t\t\t<name>"));
1131 xml.appendPreallocated(DBGetFieldForXML(hResult, i, 0));
1132 xml.append(_T("</name>\n\t\t\t\t\t<type>"));
1133 xml.append(DBGetFieldLong(hResult, i, 1));
1134 xml.append(_T("</type>\n\t\t\t\t\t<displayName>"));
1135 xml.appendPreallocated(DBGetFieldForXML(hResult, i, 2));
1136 xml.append(_T("</displayName>\n\t\t\t\t\t<config>"));
1137 xml.appendPreallocated(DBGetFieldForXML(hResult, i, 3));
1138 xml.append(_T("</config>\n\t\t\t\t</inputField>\n"));
1139 }
1140 xml.append(_T("\t\t\t</inputFields>\n"));
1141 }
1142 DBFreeResult(hResult);
1143 }
1144
1145 DBFreeStatement(hStmt);
1146}
1147
1148/**
4c3cc965
VK
1149 * Cerate export record for given object tool
1150 */
1151void CreateObjectToolExportRecord(String &xml, UINT32 id)
1152{
1153 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
1154
271e3971 1155 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT tool_name,guid,tool_type,tool_data,description,flags,tool_filter,confirmation_text,command_name,command_short_name,icon FROM object_tools WHERE tool_id=?"));
60b9b39c 1156 if (hStmt == NULL)
4c3cc965
VK
1157 {
1158 DBConnectionPoolReleaseConnection(hdb);
1159 return;
1160 }
1161
60b9b39c
VK
1162 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, id);
1163 DB_RESULT hResult = DBSelectPrepared(hStmt);
4c3cc965
VK
1164 if (hResult != NULL)
1165 {
1166 if (DBGetNumRows(hResult) > 0)
1167 {
1168 xml.append(_T("\t\t<objectTool id=\""));
1169 xml.append(id);
1170 xml.append(_T("\">\n\t\t\t<name>"));
60b9b39c 1171 xml.appendPreallocated(DBGetFieldForXML(hResult, 0, 0));
271e3971
VK
1172 xml.append(_T("</name>\n\t\t\t<guid>"));
1173 xml.appendPreallocated(DBGetField(hResult, 0, 1, NULL, 0));
1174 xml.append(_T("</guid>\n\t\t\t<type>"));
1175 xml.append(DBGetFieldLong(hResult, 0, 2));
4c3cc965 1176 xml.append(_T("</type>\n\t\t\t<data>"));
60b9b39c 1177 xml.appendPreallocated(DBGetFieldForXML(hResult, 0, 3));
271e3971
VK
1178 xml.append(_T("</data>\n\t\t\t<description>"));
1179 xml.appendPreallocated(DBGetFieldForXML(hResult, 0, 4));
60b9b39c 1180 xml.append(_T("</description>\n\t\t\t<flags>"));
271e3971 1181 xml.append(DBGetFieldLong(hResult, 0, 5));
60b9b39c 1182 xml.append(_T("</flags>\n\t\t\t<filter>"));
60b9b39c 1183 xml.appendPreallocated(DBGetFieldForXML(hResult, 0, 6));
271e3971 1184 xml.append(_T("</filter>\n\t\t\t<confirmation>"));
60b9b39c 1185 xml.appendPreallocated(DBGetFieldForXML(hResult, 0, 7));
271e3971 1186 xml.append(_T("</confirmation>\n\t\t\t<commandName>"));
60b9b39c 1187 xml.appendPreallocated(DBGetFieldForXML(hResult, 0, 8));
271e3971 1188 xml.append(_T("</commandName>\n\t\t\t<commandShortName>"));
60b9b39c 1189 xml.appendPreallocated(DBGetFieldForXML(hResult, 0, 9));
271e3971
VK
1190 xml.append(_T("</commandShortName>\n\t\t\t<image>"));
1191 xml.appendPreallocated(DBGetFieldForXML(hResult, 0, 10));
1192 xml.append(_T("</image>\n"));
1193 CreateObjectToolColumnExportRecords(hdb, xml, id);
b576249a 1194 CreateObjectToolInputFieldExportRecords(hdb, xml, id);
271e3971 1195 xml.append(_T("\t\t</objectTool>\n"));
4c3cc965
VK
1196 }
1197 DBFreeResult(hResult);
1198 }
1199
60b9b39c 1200 DBFreeStatement(hStmt);
4c3cc965
VK
1201 DBConnectionPoolReleaseConnection(hdb);
1202}
b576249a
VK
1203
1204/**
1205 * Load object tool's input field definitions
1206 */
1207static bool LoadInputFieldDefinitions(UINT32 toolId, DB_HANDLE hdb, NXCPMessage *msg, UINT32 countFieldId, UINT32 baseFieldId)
1208{
203cb23c 1209 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT name,input_type,display_name,config,sequence_num FROM object_tools_input_fields WHERE tool_id=? ORDER BY name"));
b576249a
VK
1210 if (hStmt == NULL)
1211 return false;
1212
1213 bool success = false;
1214
1215 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
1216 DB_RESULT hResult = DBSelectPrepared(hStmt);
1217 if (hResult != NULL)
1218 {
1219 int count = DBGetNumRows(hResult);
1220 msg->setField(countFieldId, (UINT16)count);
1221 UINT32 fieldId = baseFieldId;
1222 for(int i = 0; i < count; i++)
1223 {
1224 TCHAR buffer[128];
1225
1226 DBGetField(hResult, i, 0, buffer, 128);
1227 msg->setField(fieldId++, buffer);
1228
1229 msg->setField(fieldId++, (INT16)DBGetFieldLong(hResult, i, 1));
1230
1231 DBGetField(hResult, i, 2, buffer, 128);
1232 msg->setField(fieldId++, buffer);
1233
1234 TCHAR *cfg = DBGetField(hResult, i, 3, NULL, 0);
1235 msg->setField(fieldId++, cfg);
8571ce27 1236 free(cfg);
b576249a 1237
203cb23c
VK
1238 int seq = DBGetFieldLong(hResult, i, 4);
1239 if (seq == -1)
1240 seq = i;
1241 msg->setField(fieldId++, (INT16)seq);
1242
1243 fieldId += 5;
b576249a
VK
1244 }
1245 DBFreeResult(hResult);
1246 success = true;
1247 }
1248
1249 DBFreeStatement(hStmt);
1250 return success;
1251}
1252
1253/**
1254 * Get all object tools available for given user into NXCP message
1255 */
1256UINT32 GetObjectToolsIntoMessage(NXCPMessage *msg, UINT32 userId, bool fullAccess)
1257{
1258 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
1259 DB_RESULT hResult = DBSelect(hdb, _T("SELECT tool_id,user_id FROM object_tools_acl"));
1260 if (hResult == NULL)
1261 {
1262 DBConnectionPoolReleaseConnection(hdb);
1263 return RCC_DB_FAILURE;
1264 }
1265
1266 int aclSize = DBGetNumRows(hResult);
1267 OBJECT_TOOL_ACL *acl = (OBJECT_TOOL_ACL *)malloc(aclSize * sizeof(OBJECT_TOOL_ACL));
1268 for(int i = 0; i < aclSize; i++)
1269 {
1270 acl[i].toolId = DBGetFieldULong(hResult, i, 0);
1271 acl[i].userId = DBGetFieldULong(hResult, i, 1);
1272 }
1273 DBFreeResult(hResult);
1274
1275 hResult = DBSelect(hdb, _T("SELECT tool_id,tool_name,tool_type,tool_data,flags,description,tool_filter,confirmation_text,command_name,command_short_name,icon FROM object_tools"));
1276 if (hResult == NULL)
1277 {
1278 DBConnectionPoolReleaseConnection(hdb);
1279 free(acl);
1280 return RCC_DB_FAILURE;
1281 }
1282
1283 UINT32 recordCount = 0;
1284 UINT32 fieldId = VID_OBJECT_TOOLS_BASE;
1285 int count = DBGetNumRows(hResult);
1286 for(int i = 0; i < count; i++)
1287 {
1288 UINT32 toolId = DBGetFieldULong(hResult, i, 0);
1289 bool hasAccess = fullAccess;
1290 if (!fullAccess)
1291 {
1292 for(int j = 0; j < aclSize; j++)
1293 {
1294 if (acl[j].toolId == toolId)
1295 {
1296 if ((acl[j].userId == userId) ||
1297 (acl[j].userId == GROUP_EVERYONE) ||
1298 ((acl[j].userId & GROUP_FLAG) && CheckUserMembership(userId, acl[j].userId)))
1299 {
1300 hasAccess = true;
1301 break;
1302 }
1303 }
1304 }
1305 }
1306
1307 if (hasAccess)
1308 {
1309 TCHAR buffer[MAX_DB_STRING];
1310
1311 msg->setField(fieldId, toolId);
1312
1313 // name
1314 DBGetField(hResult, i, 1, buffer, MAX_DB_STRING);
1315 msg->setField(fieldId + 1, buffer);
1316
1317 msg->setField(fieldId + 2, (WORD)DBGetFieldLong(hResult, i, 2));
1318
1319 // data
1320 TCHAR *data = DBGetField(hResult, i, 3, NULL, 0);
1321 msg->setField(fieldId + 3, data);
1322 free(data);
1323
1324 msg->setField(fieldId + 4, DBGetFieldULong(hResult, i, 4));
1325
1326 // description
1327 DBGetField(hResult, i, 5, buffer, MAX_DB_STRING);
1328 msg->setField(fieldId + 5, buffer);
1329
1330 // matching OID
1331 DBGetField(hResult, i, 6, buffer, MAX_DB_STRING);
1332 msg->setField(fieldId + 6, buffer);
1333
1334 // confirmation text
1335 DBGetField(hResult, i, 7, buffer, MAX_DB_STRING);
1336 msg->setField(fieldId + 7, buffer);
1337
1338 // command name
1339 DBGetField(hResult, i, 8, buffer, MAX_DB_STRING);
1340 msg->setField(fieldId + 8, buffer);
1341
1342 // command short name
1343 DBGetField(hResult, i, 9, buffer, MAX_DB_STRING);
1344 msg->setField(fieldId + 9, buffer);
1345
1346 // icon
1347 TCHAR *imageDataHex = DBGetField(hResult, i, 10, NULL, 0);
1348 if (imageDataHex != NULL)
1349 {
1350 size_t size = _tcslen(imageDataHex) / 2;
1351 BYTE *imageData = (BYTE *)malloc(size);
1352 size_t bytes = StrToBin(imageDataHex, imageData, size);
1353 msg->setField(fieldId + 10, imageData, (UINT32)bytes);
1354 free(imageData);
1355 free(imageDataHex);
1356 }
1357 else
1358 {
1359 msg->setField(fieldId + 10, (BYTE *)NULL, 0);
1360 }
1361
1362 LoadInputFieldDefinitions(toolId, hdb, msg, fieldId + 11, fieldId + 20);
1363
1364 recordCount++;
1365 fieldId += 10000;
1366 }
1367 }
1368 msg->setField(VID_NUM_TOOLS, recordCount);
1369
1370 DBFreeResult(hResult);
1371 free(acl);
1372
1373 DBConnectionPoolReleaseConnection(hdb);
1374 return RCC_SUCCESS;
1375}
1376
1377/**
1378 * Get object tool details into NXCP message
1379 */
1380UINT32 GetObjectToolDetailsIntoMessage(UINT32 toolId, NXCPMessage *msg)
1381{
1382 UINT32 rcc = RCC_DB_FAILURE;
1383 DB_RESULT hResult = NULL;
1384 TCHAR buffer[MAX_DB_STRING], *data;
1385 int aclSize, toolType;
1386
1387 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
1388
1389 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT tool_name,tool_type,tool_data,description,flags,tool_filter,confirmation_text,command_name,command_short_name,icon FROM object_tools WHERE tool_id=?"));
1390 if (hStmt == NULL)
1391 goto cleanup;
1392
1393 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
1394
1395 hResult = DBSelectPrepared(hStmt);
1396 if (hResult == NULL)
1397 goto cleanup;
1398
1399 if (DBGetNumRows(hResult) == 0)
1400 {
1401 rcc = RCC_INVALID_TOOL_ID;
1402 goto cleanup;
1403 }
1404
1405 msg->setField(VID_TOOL_ID, toolId);
1406 msg->setField(VID_NAME, DBGetField(hResult, 0, 0, buffer, MAX_DB_STRING));
1407
1408 toolType = DBGetFieldLong(hResult, 0, 1);
1409 msg->setField(VID_TOOL_TYPE, (INT16)toolType);
1410
1411 data = DBGetField(hResult, 0, 2, NULL, 0);
1412 msg->setField(VID_TOOL_DATA, data);
1413 free(data);
1414
1415 msg->setField(VID_DESCRIPTION, DBGetField(hResult, 0, 3, buffer, MAX_DB_STRING));
1416 msg->setField(VID_FLAGS, DBGetFieldULong(hResult, 0, 4));
1417 msg->setField(VID_TOOL_FILTER, DBGetField(hResult, 0, 5, buffer, MAX_DB_STRING));
1418 msg->setField(VID_CONFIRMATION_TEXT, DBGetField(hResult, 0, 6, buffer, MAX_DB_STRING));
1419 msg->setField(VID_COMMAND_NAME, DBGetField(hResult, 0, 7, buffer, MAX_DB_STRING));
1420 msg->setField(VID_COMMAND_SHORT_NAME, DBGetField(hResult, 0, 8, buffer, MAX_DB_STRING));
1421
1422 // icon
1423 data = DBGetField(hResult, 0, 9, NULL, 0);
1424 if (data != NULL)
1425 {
1426 size_t size = _tcslen(data) / 2;
1427 BYTE *imageData = (BYTE *)malloc(size);
1428 size_t bytes = StrToBin(data, imageData, size);
1429 msg->setField(VID_IMAGE_DATA, imageData, (UINT32)bytes);
1430 free(imageData);
1431 free(data);
1432 }
1433 else
1434 {
1435 msg->setField(VID_IMAGE_DATA, (BYTE *)NULL, 0);
1436 }
1437
1438 DBFreeResult(hResult);
1439 hResult = NULL;
1440 DBFreeStatement(hStmt);
1441
1442 // Access list
1443 hStmt = DBPrepare(hdb, _T("SELECT user_id FROM object_tools_acl WHERE tool_id=?"));
1444 if (hStmt == NULL)
1445 goto cleanup;
1446 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
1447
1448 hResult = DBSelectPrepared(hStmt);
1449 if (hResult == NULL)
1450 goto cleanup;
1451
1452 aclSize = DBGetNumRows(hResult);
1453 msg->setField(VID_ACL_SIZE, (UINT32)aclSize);
1454 if (aclSize > 0)
1455 {
1456 UINT32 *acl = (UINT32 *)malloc(sizeof(UINT32) * aclSize);
1457 for(int i = 0; i < aclSize; i++)
1458 acl[i] = DBGetFieldULong(hResult, i, 0);
1459 msg->setFieldFromInt32Array(VID_ACL, aclSize, acl);
1460 free(acl);
1461 }
1462 DBFreeResult(hResult);
1463 hResult = NULL;
1464
1465 // Column information for table tools
1466 if ((toolType == TOOL_TYPE_TABLE_SNMP) || (toolType == TOOL_TYPE_TABLE_AGENT))
1467 {
1468 DBFreeStatement(hStmt);
1469 hStmt = DBPrepare(hdb, _T("SELECT col_name,col_oid,col_format,col_substr ")
1470 _T("FROM object_tools_table_columns WHERE tool_id=? ")
1471 _T("ORDER BY col_number"));
1472 if (hStmt == NULL)
1473 goto cleanup;
1474 DBBind(hStmt, 1, DB_SQLTYPE_INTEGER, toolId);
1475
1476 hResult = DBSelectPrepared(hStmt);
1477 if (hResult == NULL)
1478 goto cleanup;
1479
1480 int count = DBGetNumRows(hResult);
1481 msg->setField(VID_NUM_COLUMNS, (INT16)count);
1482 UINT32 fieldId = VID_COLUMN_INFO_BASE;
1483 for(int i = 0; i < count; i++)
1484 {
1485 DBGetField(hResult, i, 0, buffer, MAX_DB_STRING);
1486 msg->setField(fieldId++, buffer);
1487 msg->setField(fieldId++, DBGetField(hResult, i, 1, buffer, MAX_DB_STRING));
1488 msg->setField(fieldId++, (UINT16)DBGetFieldLong(hResult, i, 2));
1489 msg->setField(fieldId++, (UINT16)DBGetFieldLong(hResult, i, 3));
1490 }
1491 DBFreeResult(hResult);
1492 hResult = NULL;
1493 }
1494
1495 if (!LoadInputFieldDefinitions(toolId, hdb, msg, VID_NUM_FIELDS, VID_FIELD_LIST_BASE))
1496 goto cleanup;
1497
1498 rcc = RCC_SUCCESS;
1499
1500cleanup:
1501 if (hResult != NULL)
1502 DBFreeResult(hResult);
1503 if (hStmt != NULL)
1504 DBFreeStatement(hStmt);
1505 DBConnectionPoolReleaseConnection(hdb);
1506
1507 if (rcc != RCC_SUCCESS)
1508 msg->deleteAllFields();
1509 return rcc;
1510}
234079c4
VK
1511
1512/**
1513 * Command execution data constructor
1514 */
45ac5dd0 1515ServerCommandExec::ServerCommandExec(NXCPMessage *request, ClientSession *session) : CommandExec()
234079c4 1516{
45ac5dd0
EJ
1517 NetObj *object = FindObjectById(request->getFieldAsUInt32(VID_OBJECT_ID));
1518 if (object != NULL)
1519 {
1520 StringMap *inputFields;
1521 int count = request->getFieldAsInt16(VID_NUM_FIELDS);
1522 if (count > 0)
1523 {
1524 inputFields = new StringMap();
1525 UINT32 fieldId = VID_FIELD_LIST_BASE;
1526 for(int i = 0; i < count; i++)
1527 {
1528 TCHAR *name = request->getFieldAsString(fieldId++);
1529 TCHAR *value = request->getFieldAsString(fieldId++);
1530 inputFields->setPreallocated(name, value);
1531 }
1532 }
1533 else
1534 inputFields = NULL;
1535
1536 TCHAR *cmd = request->getFieldAsString(VID_COMMAND);
2649d20b 1537 m_cmd = object->expandText(cmd, NULL, NULL, session->getLoginName(), inputFields);
45ac5dd0
EJ
1538 free(cmd);
1539 delete inputFields;
1540 }
1541
1542 m_sendOutput = request->getFieldAsBoolean(VID_RECEIVE_OUTPUT);
234079c4
VK
1543 if (m_sendOutput)
1544 {
45ac5dd0 1545 m_requestId = request->getId();
234079c4
VK
1546 m_session = session;
1547 m_session->incRefCount();
1548 }
1549 else
1550 {
1551 m_requestId = 0;
1552 m_session = NULL;
1553 }
1554}
1555
1556/**
1557 * Command execution data destructor
1558 */
45ac5dd0 1559ServerCommandExec::~ServerCommandExec()
234079c4
VK
1560{
1561 if (m_session != NULL)
1562 m_session->decRefCount();
234079c4
VK
1563}
1564
1565/**
45ac5dd0 1566 * Send output to console
234079c4 1567 */
45ac5dd0 1568void ServerCommandExec::onOutput(const char *text)
234079c4 1569{
45ac5dd0
EJ
1570 NXCPMessage msg;
1571 msg.setId(m_requestId);
1572 msg.setCode(CMD_COMMAND_OUTPUT);
940813c9 1573#ifdef UNICODE
8d537996 1574 TCHAR *buffer = WideStringFromMBStringSysLocale(text);
45ac5dd0
EJ
1575 msg.setField(VID_MESSAGE, buffer);
1576 m_session->sendMessage(&msg);
1577 free(buffer);
940813c9
EJ
1578#else
1579 msg.setField(VID_MESSAGE, text);
1580 m_session->sendMessage(&msg);
1581#endif
1582
45ac5dd0 1583}
234079c4 1584
45ac5dd0
EJ
1585/**
1586 * Send message to make console stop listening to output
1587 */
1588void ServerCommandExec::endOfOutput()
1589{
1590 NXCPMessage msg;
1591 msg.setId(m_requestId);
1592 msg.setCode(CMD_COMMAND_OUTPUT);
1593 msg.setEndOfSequence();
1594 m_session->sendMessage(&msg);
234079c4 1595}