ddae94ceb9f8bf693927549a3469caa738620727
[public/netxms.git] / src / server / core / config.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2016 Victor Kirhenshtein
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: config.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24 #include <nxconfig.h>
25
26 /**
27 * Externals
28 */
29 extern char g_szCodePage[];
30 extern TCHAR *g_moduleLoadList;
31 extern TCHAR *g_pdsLoadList;
32
33 /**
34 * database connection parameters
35 */
36 TCHAR g_szDbDriver[MAX_PATH] = _T("");
37 TCHAR g_szDbDrvParams[MAX_PATH] = _T("");
38 TCHAR g_szDbServer[MAX_PATH] = _T("127.0.0.1");
39 TCHAR g_szDbLogin[MAX_DB_LOGIN] = _T("netxms");
40 TCHAR g_szDbPassword[MAX_PASSWORD] = _T("");
41 TCHAR g_szDbName[MAX_DB_NAME] = _T("netxms_db");
42 TCHAR g_szDbSchema[MAX_DB_NAME] = _T("");
43
44 /**
45 * Debug level from config
46 */
47 static UINT32 s_debugLevel = (UINT32)NXCONFIG_UNINITIALIZED_VALUE;
48
49 /**
50 * Config file template
51 */
52 static NX_CFG_TEMPLATE m_cfgTemplate[] =
53 {
54 { _T("BackgroundLogWriter"), CT_BOOLEAN64, 0, 0, AF_BACKGROUND_LOG_WRITER, 0, &g_flags, NULL },
55 { _T("CodePage"), CT_MB_STRING, 0, 0, 256, 0, g_szCodePage, NULL },
56 { _T("CreateCrashDumps"), CT_BOOLEAN64, 0, 0, AF_CATCH_EXCEPTIONS, 0, &g_flags, NULL },
57 { _T("DailyLogFileSuffix"), CT_STRING, 0, 0, 64, 0, g_szDailyLogFileSuffix, NULL },
58 { _T("DataDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, g_netxmsdDataDir, NULL },
59 { _T("DBDriver"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDbDriver, NULL },
60 { _T("DBDrvParams"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDbDrvParams, NULL },
61 { _T("DBLogin"), CT_STRING, 0, 0, MAX_DB_LOGIN, 0, g_szDbLogin, NULL },
62 { _T("DBName"), CT_STRING, 0, 0, MAX_DB_NAME, 0, g_szDbName, NULL },
63 { _T("DBPassword"), CT_STRING, 0, 0, MAX_PASSWORD, 0, g_szDbPassword, NULL },
64 { _T("DBEncryptedPassword"), CT_STRING, 0, 0, MAX_PASSWORD, 0, g_szDbPassword, NULL },
65 { _T("DBSchema"), CT_STRING, 0, 0, MAX_DB_NAME, 0, g_szDbSchema, NULL },
66 { _T("DBServer"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDbServer, NULL },
67 { _T("DebugLevel"), CT_LONG, 0, 0, 0, 0, &s_debugLevel, &s_debugLevel },
68 { _T("DumpDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, g_szDumpDir, NULL },
69 { _T("FullCrashDumps"), CT_BOOLEAN64, 0, 0, AF_WRITE_FULL_DUMP, 0, &g_flags, NULL },
70 { _T("LibraryDirectory"), CT_STRING, 0, 0, MAX_PATH, 0, g_netxmsdLibDir, NULL },
71 { _T("ListenAddress"), CT_STRING, 0, 0, MAX_PATH, 0, g_szListenAddress, NULL },
72 { _T("LogFailedSQLQueries"), CT_BOOLEAN64, 0, 0, AF_LOG_SQL_ERRORS, 0, &g_flags, NULL },
73 { _T("LogFile"), CT_STRING, 0, 0, MAX_PATH, 0, g_szLogFile, NULL },
74 { _T("LogHistorySize"), CT_LONG, 0, 0, 0, 0, &g_dwLogHistorySize, NULL },
75 { _T("LogRotationMode"), CT_LONG, 0, 0, 0, 0, &g_dwLogRotationMode, NULL },
76 { _T("MaxLogSize"), CT_LONG, 0, 0, 0, 0, &g_dwMaxLogSize, NULL },
77 { _T("Module"), CT_STRING_LIST, '\n', 0, 0, 0, &g_moduleLoadList, NULL },
78 { _T("PerfDataStorageDriver"), CT_STRING_LIST, '\n', 0, 0, 0, &g_pdsLoadList, NULL },
79 { _T("ProcessAffinityMask"), CT_LONG, 0, 0, 0, 0, &g_processAffinityMask, NULL },
80 { _T(""), CT_END_OF_LIST, 0, 0, 0, 0, NULL, NULL }
81 };
82
83 /**
84 * Loaded server config
85 */
86 Config g_serverConfig;
87
88 /**
89 * Load and parse configuration file
90 * Returns TRUE on success and FALSE on failure
91 */
92 bool NXCORE_EXPORTABLE LoadConfig(int *debugLevel)
93 {
94 bool bSuccess = false;
95
96 if (!_tcscmp(g_szConfigFile, _T("{search}")))
97 {
98 #ifdef _WIN32
99 TCHAR path[MAX_PATH];
100 GetNetXMSDirectory(nxDirEtc, path);
101 _tcscat(path, _T("\\netxmsd.conf"));
102 if (_taccess(path, 4) == 0)
103 {
104 _tcscpy(g_szConfigFile, path);
105 }
106 else
107 {
108 _tcscpy(g_szConfigFile, _T("C:\\netxmsd.conf"));
109 }
110 #else
111 const TCHAR *homeDir = _tgetenv(_T("NETXMS_HOME"));
112 if ((homeDir != NULL) && (*homeDir != 0))
113 {
114 TCHAR config[MAX_PATH];
115 _sntprintf(config, MAX_PATH, _T("%s/etc/netxmsd.conf"), homeDir);
116 if (_taccess(config, 4) == 0)
117 {
118 _tcscpy(g_szConfigFile, config);
119 goto stop_search;
120 }
121 }
122 if (_taccess(PREFIX _T("/etc/netxmsd.conf"), 4) == 0)
123 {
124 _tcscpy(g_szConfigFile, PREFIX _T("/etc/netxmsd.conf"));
125 }
126 else if (_taccess(_T("/usr/etc/netxmsd.conf"), 4) == 0)
127 {
128 _tcscpy(g_szConfigFile, _T("/usr/etc/netxmsd.conf"));
129 }
130 else
131 {
132 _tcscpy(g_szConfigFile, _T("/etc/netxmsd.conf"));
133 }
134 stop_search:
135 ;
136 #endif
137 }
138
139 if (IsStandalone())
140 _tprintf(_T("Using configuration file \"%s\"\n"), g_szConfigFile);
141
142 if (g_serverConfig.loadConfig(g_szConfigFile, _T("server")) && g_serverConfig.parseTemplate(_T("server"), m_cfgTemplate))
143 {
144 if ((!_tcsicmp(g_szLogFile, _T("{EventLog}"))) ||
145 (!_tcsicmp(g_szLogFile, _T("{syslog}"))))
146 {
147 g_flags |= AF_USE_SYSLOG;
148 }
149 else
150 {
151 g_flags &= ~AF_USE_SYSLOG;
152 }
153 bSuccess = true;
154 }
155
156 if (*debugLevel == NXCONFIG_UNINITIALIZED_VALUE)
157 *debugLevel = (int)s_debugLevel;
158
159 // Decrypt password
160 DecryptPassword(g_szDbLogin, g_szDbPassword, g_szDbPassword, MAX_PASSWORD);
161 return bSuccess;
162 }
163
164 /**
165 * Read string value from metadata table
166 */
167 bool NXCORE_EXPORTABLE MetaDataReadStr(const TCHAR *szVar, TCHAR *szBuffer, int iBufSize, const TCHAR *szDefault)
168 {
169 DB_RESULT hResult;
170 bool bSuccess = false;
171
172 nx_strncpy(szBuffer, szDefault, iBufSize);
173 if (_tcslen(szVar) > 127)
174 return false;
175
176 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
177 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM metadata WHERE var_name=?"));
178 if (hStmt != NULL)
179 {
180 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, szVar, DB_BIND_STATIC);
181 hResult = DBSelectPrepared(hStmt);
182 if (hResult != NULL)
183 {
184 if (DBGetNumRows(hResult) > 0)
185 {
186 DBGetField(hResult, 0, 0, szBuffer, iBufSize);
187 bSuccess = true;
188 }
189 DBFreeResult(hResult);
190 }
191 DBFreeStatement(hStmt);
192 }
193 DBConnectionPoolReleaseConnection(hdb);
194 return bSuccess;
195 }
196
197 /**
198 * Read integer value from metadata table
199 */
200 INT32 NXCORE_EXPORTABLE MetaDataReadInt(const TCHAR *var, UINT32 defaultValue)
201 {
202 TCHAR buffer[256];
203 if (MetaDataReadStr(var, buffer, 256, _T("")))
204 {
205 TCHAR *eptr;
206 INT32 value = _tcstol(buffer, &eptr, 0);
207 return (*eptr == 0) ? value : defaultValue;
208 }
209 else
210 {
211 return defaultValue;
212 }
213 }
214
215 /**
216 * Write string value to metadata table
217 */
218 bool NXCORE_EXPORTABLE MetaDataWriteStr(const TCHAR *varName, const TCHAR *value)
219 {
220 if (_tcslen(varName) > 63)
221 return false;
222
223 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
224
225 // Check for variable existence
226 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM metadata WHERE var_name=?"));
227 if (hStmt == NULL)
228 {
229 DBConnectionPoolReleaseConnection(hdb);
230 return false;
231 }
232 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
233 DB_RESULT hResult = DBSelectPrepared(hStmt);
234 bool bVarExist = false;
235 if (hResult != NULL)
236 {
237 if (DBGetNumRows(hResult) > 0)
238 bVarExist = true;
239 DBFreeResult(hResult);
240 }
241 DBFreeStatement(hStmt);
242
243 // Create or update variable value
244 if (bVarExist)
245 {
246 hStmt = DBPrepare(hdb, _T("UPDATE metadata SET var_value=? WHERE var_name=?"));
247 if (hStmt == NULL)
248 {
249 DBConnectionPoolReleaseConnection(hdb);
250 return false;
251 }
252 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
253 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
254 }
255 else
256 {
257 hStmt = DBPrepare(hdb, _T("INSERT INTO metadata (var_name,var_value) VALUES (?,?)"));
258 if (hStmt == NULL)
259 {
260 DBConnectionPoolReleaseConnection(hdb);
261 return false;
262 }
263 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
264 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
265 }
266 bool success = DBExecute(hStmt);
267 DBFreeStatement(hStmt);
268 DBConnectionPoolReleaseConnection(hdb);
269 return success;
270 }
271
272 /**
273 * Config cache
274 */
275 static StringMap s_configCache;
276 static RWLOCK s_configCacheLock = RWLockCreate();
277
278 /**
279 * Callback for configuration variables change
280 */
281 static void OnConfigVariableChange(bool isCLOB, const TCHAR *name, const TCHAR *value)
282 {
283 RWLockWriteLock(s_configCacheLock, INFINITE);
284 s_configCache.set(name, value);
285 RWLockUnlock(s_configCacheLock);
286
287 // Restart syslog parser if configuration was changed
288 if (isCLOB && !_tcscmp(name, _T("SyslogParser")))
289 {
290 ReinitializeSyslogParser();
291 }
292 else if (!_tcsncmp(name, _T("CAS"), 3))
293 {
294 CASReadSettings();
295 }
296 else if (!_tcscmp(name, _T("DefaultDCIPollingInterval")))
297 {
298 DCObject::m_defaultPollingInterval = _tcstol(value, NULL, 0);
299 }
300 else if (!_tcscmp(name, _T("DefaultDCIRetentionTime")))
301 {
302 DCObject::m_defaultRetentionTime = _tcstol(value, NULL, 0);
303 }
304 else if (!_tcscmp(name, _T("StrictAlarmStatusFlow")))
305 {
306 NotifyClientSessions(NX_NOTIFY_ALARM_STATUS_FLOW_CHANGED, _tcstol(value, NULL, 0));
307 }
308 else if (!_tcsncmp(name, _T("Syslog"), 6))
309 {
310 OnSyslogConfigurationChange(name, value);
311 }
312 }
313
314 /**
315 * Read string value from configuration table
316 */
317 bool NXCORE_EXPORTABLE ConfigReadStrEx(DB_HANDLE dbHandle, const TCHAR *szVar, TCHAR *szBuffer, int iBufSize, const TCHAR *szDefault)
318 {
319 nx_strncpy(szBuffer, szDefault, iBufSize);
320 if (_tcslen(szVar) > 127)
321 return false;
322
323 RWLockReadLock(s_configCacheLock, INFINITE);
324 const TCHAR *value = s_configCache.get(szVar);
325 RWLockUnlock(s_configCacheLock);
326 if (value != NULL)
327 {
328 nx_strncpy(szBuffer, value, iBufSize);
329 DbgPrintf(8, _T("ConfigReadStr: (cached) name=%s value=\"%s\""), szVar, szBuffer);
330 return true;
331 }
332
333 bool bSuccess = false;
334 DB_HANDLE hdb = (dbHandle == NULL) ? DBConnectionPoolAcquireConnection() : dbHandle;
335 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=?"));
336 if (hStmt != NULL)
337 {
338 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, szVar, DB_BIND_STATIC);
339 DB_RESULT hResult = DBSelectPrepared(hStmt);
340 if (hResult != NULL)
341 {
342 if (DBGetNumRows(hResult) > 0)
343 {
344 DBGetField(hResult, 0, 0, szBuffer, iBufSize);
345 DbgPrintf(8, _T("ConfigReadStr: name=%s value=\"%s\""), szVar, szBuffer);
346 bSuccess = true;
347 }
348 DBFreeResult(hResult);
349 }
350 DBFreeStatement(hStmt);
351 }
352 if (dbHandle == NULL)
353 DBConnectionPoolReleaseConnection(hdb);
354
355 if (bSuccess)
356 {
357 RWLockWriteLock(s_configCacheLock, INFINITE);
358 s_configCache.set(szVar, szBuffer);
359 RWLockUnlock(s_configCacheLock);
360 }
361
362 return bSuccess;
363 }
364
365 /**
366 * Read string value from configuration table
367 */
368 bool NXCORE_EXPORTABLE ConfigReadStr(const TCHAR *var, TCHAR *buffer, int bufferSize, const TCHAR *defaultValue)
369 {
370 return ConfigReadStrEx(NULL, var, buffer, bufferSize, defaultValue);
371 }
372
373 /**
374 * Read multibyte string from configuration table
375 */
376 #ifdef UNICODE
377
378 bool NXCORE_EXPORTABLE ConfigReadStrA(const WCHAR *szVar, char *szBuffer, int iBufSize, const char *szDefault)
379 {
380 WCHAR *wcBuffer = (WCHAR *)malloc(iBufSize * sizeof(WCHAR));
381 bool rc = ConfigReadStr(szVar, wcBuffer, iBufSize, _T(""));
382 if (rc)
383 {
384 WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR | WC_COMPOSITECHECK, wcBuffer, -1, szBuffer, iBufSize, NULL, NULL);
385 }
386 else
387 {
388 strncpy(szBuffer, szDefault, iBufSize);
389 }
390 szBuffer[iBufSize - 1] = 0;
391 free(wcBuffer);
392 return rc;
393 }
394
395 #endif
396
397 /**
398 * Read string value from configuration table as UTF8 string
399 */
400 bool NXCORE_EXPORTABLE ConfigReadStrUTF8(const TCHAR *szVar, char *szBuffer, int iBufSize, const char *szDefault)
401 {
402 DB_RESULT hResult;
403 bool bSuccess = false;
404
405 strncpy(szBuffer, szDefault, iBufSize);
406 if (_tcslen(szVar) > 127)
407 return false;
408
409 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
410 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=?"));
411 if (hStmt != NULL)
412 {
413 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, szVar, DB_BIND_STATIC);
414 hResult = DBSelectPrepared(hStmt);
415 if (hResult != NULL)
416 {
417 if (DBGetNumRows(hResult) > 0)
418 {
419 DBGetFieldUTF8(hResult, 0, 0, szBuffer, iBufSize);
420 bSuccess = true;
421 }
422 DBFreeResult(hResult);
423 }
424 DBFreeStatement(hStmt);
425 }
426 DBConnectionPoolReleaseConnection(hdb);
427
428 return bSuccess;
429 }
430
431 /**
432 * Read integer value from configuration table
433 */
434 int NXCORE_EXPORTABLE ConfigReadInt(const TCHAR *szVar, int iDefault)
435 {
436 return ConfigReadIntEx(NULL, szVar, iDefault);
437 }
438
439 /**
440 * Read integer value from configuration table
441 */
442 int NXCORE_EXPORTABLE ConfigReadIntEx(DB_HANDLE hdb, const TCHAR *szVar, int iDefault)
443 {
444 TCHAR szBuffer[64];
445
446 if (ConfigReadStrEx(hdb, szVar, szBuffer, 64, _T("")))
447 return _tcstol(szBuffer, NULL, 0);
448 else
449 return iDefault;
450 }
451
452 /**
453 * Read unsigned long value from configuration table
454 */
455 UINT32 NXCORE_EXPORTABLE ConfigReadULong(const TCHAR *szVar, UINT32 dwDefault)
456 {
457 TCHAR szBuffer[64];
458
459 if (ConfigReadStr(szVar, szBuffer, 64, _T("")))
460 return _tcstoul(szBuffer, NULL, 0);
461 else
462 return dwDefault;
463 }
464
465 /**
466 * Read byte array (in hex form) from configuration table into integer array
467 */
468 bool NXCORE_EXPORTABLE ConfigReadByteArray(const TCHAR *pszVar, int *pnArray, int nSize, int nDefault)
469 {
470 TCHAR szBuffer[256];
471 char pbBytes[128];
472 bool bResult;
473 int i, nLen;
474
475 if (ConfigReadStr(pszVar, szBuffer, 256, _T("")))
476 {
477 StrToBin(szBuffer, (BYTE *)pbBytes, 128);
478 nLen = (int)_tcslen(szBuffer) / 2;
479 for(i = 0; (i < nSize) && (i < nLen); i++)
480 pnArray[i] = pbBytes[i];
481 for(; i < nSize; i++)
482 pnArray[i] = nDefault;
483 bResult = true;
484 }
485 else
486 {
487 for(i = 0; i < nSize; i++)
488 pnArray[i] = nDefault;
489 bResult = false;
490 }
491 return bResult;
492 }
493
494 /**
495 * Write string value to configuration table
496 */
497 bool NXCORE_EXPORTABLE ConfigWriteStr(const TCHAR *varName, const TCHAR *value, bool bCreate, bool isVisible, bool needRestart)
498 {
499 if (_tcslen(varName) > 63)
500 return false;
501
502 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
503
504 // Check for variable existence
505 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=?"));
506 if (hStmt == NULL)
507 {
508 DBConnectionPoolReleaseConnection(hdb);
509 return false;
510 }
511 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
512 DB_RESULT hResult = DBSelectPrepared(hStmt);
513 bool bVarExist = false;
514 if (hResult != NULL)
515 {
516 if (DBGetNumRows(hResult) > 0)
517 bVarExist = true;
518 DBFreeResult(hResult);
519 }
520 DBFreeStatement(hStmt);
521
522 // Don't create non-existing variable if creation flag not set
523 if (!bCreate && !bVarExist)
524 {
525 DBConnectionPoolReleaseConnection(hdb);
526 return false;
527 }
528
529 // Create or update variable value
530 if (bVarExist)
531 {
532 hStmt = DBPrepare(hdb, _T("UPDATE config SET var_value=? WHERE var_name=?"));
533 if (hStmt == NULL)
534 {
535 DBConnectionPoolReleaseConnection(hdb);
536 return false;
537 }
538 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
539 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
540 }
541 else
542 {
543 hStmt = DBPrepare(hdb, _T("INSERT INTO config (var_name,var_value,is_visible,need_server_restart) VALUES (?,?,?,?)"));
544 if (hStmt == NULL)
545 {
546 DBConnectionPoolReleaseConnection(hdb);
547 return false;
548 }
549 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
550 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, value, DB_BIND_STATIC);
551 DBBind(hStmt, 3, DB_SQLTYPE_INTEGER, (LONG)(isVisible ? 1 : 0));
552 DBBind(hStmt, 4, DB_SQLTYPE_INTEGER, (LONG)(needRestart ? 1 : 0));
553 }
554 bool success = DBExecute(hStmt);
555 DBFreeStatement(hStmt);
556 DBConnectionPoolReleaseConnection(hdb);
557 if (success)
558 OnConfigVariableChange(false, varName, value);
559 return success;
560 }
561
562 /**
563 * Write integer value to configuration table
564 */
565 bool NXCORE_EXPORTABLE ConfigWriteInt(const TCHAR *szVar, int iValue, bool bCreate, bool isVisible, bool needRestart)
566 {
567 TCHAR szBuffer[64];
568
569 _sntprintf(szBuffer, 64, _T("%d"), iValue);
570 return ConfigWriteStr(szVar, szBuffer, bCreate, isVisible, needRestart);
571 }
572
573 /**
574 * Write unsigned long value to configuration table
575 */
576 bool NXCORE_EXPORTABLE ConfigWriteULong(const TCHAR *szVar, UINT32 dwValue, bool bCreate, bool isVisible, bool needRestart)
577 {
578 TCHAR szBuffer[64];
579
580 _sntprintf(szBuffer, 64, _T("%u"), dwValue);
581 return ConfigWriteStr(szVar, szBuffer, bCreate, isVisible, needRestart);
582 }
583
584 /**
585 * Write integer array to configuration table
586 */
587 bool NXCORE_EXPORTABLE ConfigWriteByteArray(const TCHAR *pszVar, int *pnArray, int nSize, bool bCreate, bool isVisible, bool needRestart)
588 {
589 TCHAR szBuffer[256];
590 int i, j;
591
592 for(i = 0, j = 0; (i < nSize) && (i < 127); i++, j += 2)
593 _sntprintf(&szBuffer[j], 256 - j, _T("%02X"), (char)((pnArray[i] > 127) ? 127 : ((pnArray[i] < -127) ? -127 : pnArray[i])));
594 return ConfigWriteStr(pszVar, szBuffer, bCreate, isVisible, needRestart);
595 }
596
597 /**
598 * Delete configuratrion variable
599 */
600 bool NXCORE_EXPORTABLE ConfigDelete(const TCHAR *name)
601 {
602 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
603
604 TCHAR query[1024];
605 _sntprintf(query, 1024, _T("DELETE FROM config WHERE var_name=%s"), (const TCHAR *)DBPrepareString(hdb, name));
606 bool success = DBQuery(hdb, query) ? true : false;
607
608 DBConnectionPoolReleaseConnection(hdb);
609
610 if (success)
611 {
612 RWLockWriteLock(s_configCacheLock, INFINITE);
613 s_configCache.remove(name);
614 RWLockUnlock(s_configCacheLock);
615 }
616
617 return success;
618 }
619
620 /**
621 * Read large string (clob) value from configuration table
622 */
623 TCHAR NXCORE_EXPORTABLE *ConfigReadCLOB(const TCHAR *var, const TCHAR *defValue)
624 {
625 TCHAR *result = NULL;
626
627 if (_tcslen(var) <= 63)
628 {
629 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
630 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config_clob WHERE var_name=?"));
631 if (hStmt != NULL)
632 {
633 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
634 DB_RESULT hResult = DBSelectPrepared(hStmt);
635 if (hResult != NULL)
636 {
637 if (DBGetNumRows(hResult) > 0)
638 {
639 result = DBGetField(hResult, 0, 0, NULL, 0);
640 }
641 DBFreeResult(hResult);
642 }
643 DBFreeStatement(hStmt);
644 }
645 DBConnectionPoolReleaseConnection(hdb);
646 }
647
648 // Return default value in case of error
649 if ((result == NULL) && (defValue != NULL))
650 result = _tcsdup(defValue);
651
652 return result;
653 }
654
655 /**
656 * Write large string (clob) value to configuration table
657 */
658 bool NXCORE_EXPORTABLE ConfigWriteCLOB(const TCHAR *var, const TCHAR *value, bool bCreate)
659 {
660 if (_tcslen(var) > 63)
661 return false;
662
663 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
664
665 // Check for variable existence
666 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config_clob WHERE var_name=?"));
667 if (hStmt == NULL)
668 {
669 DBConnectionPoolReleaseConnection(hdb);
670 return false;
671 }
672 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
673 DB_RESULT hResult = DBSelectPrepared(hStmt);
674 bool bVarExist = false;
675 if (hResult != NULL)
676 {
677 if (DBGetNumRows(hResult) > 0)
678 bVarExist = true;
679 DBFreeResult(hResult);
680 }
681 DBFreeStatement(hStmt);
682
683 // Don't create non-existing variable if creation flag not set
684 if (!bCreate && !bVarExist)
685 {
686 DBConnectionPoolReleaseConnection(hdb);
687 return false;
688 }
689
690 // Create or update variable value
691 if (bVarExist)
692 {
693 hStmt = DBPrepare(hdb, _T("UPDATE config_clob SET var_value=? WHERE var_name=?"));
694 if (hStmt == NULL)
695 {
696 DBConnectionPoolReleaseConnection(hdb);
697 return false;
698 }
699 DBBind(hStmt, 1, DB_SQLTYPE_TEXT, value, DB_BIND_STATIC);
700 DBBind(hStmt, 2, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
701 }
702 else
703 {
704 hStmt = DBPrepare(hdb, _T("INSERT INTO config_clob (var_name,var_value) VALUES (?,?)"));
705 if (hStmt == NULL)
706 {
707 DBConnectionPoolReleaseConnection(hdb);
708 return false;
709 }
710 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, var, DB_BIND_STATIC);
711 DBBind(hStmt, 2, DB_SQLTYPE_TEXT, value, DB_BIND_STATIC);
712 }
713 bool success = DBExecute(hStmt) ? true : false;
714 DBFreeStatement(hStmt);
715 DBConnectionPoolReleaseConnection(hdb);
716 if (success)
717 OnConfigVariableChange(true, var, value);
718 return success;
719 }