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