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