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