fixed incorrect sprintf format usage; fixed access to uninitialized memory in DB...
[public/netxms.git] / src / server / tools / nxdbmgr / init.cpp
1 /*
2 ** nxdbmgr - NetXMS database manager
3 ** Copyright (C) 2004-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: init.cpp
20 **
21 **/
22
23 #include "nxdbmgr.h"
24
25 /**
26 * Check if query is empty
27 */
28 static BOOL IsEmptyQuery(const char *pszQuery)
29 {
30 const char *ptr;
31
32 for(ptr = pszQuery; *ptr != 0; ptr++)
33 if ((*ptr != ' ') && (*ptr != '\t') && (*ptr != '\r') && (*ptr != '\n'))
34 return FALSE;
35 return TRUE;
36 }
37
38 /**
39 * Find end of query in batch
40 */
41 static BYTE *FindEndOfQuery(BYTE *pStart, BYTE *pBatchEnd)
42 {
43 BYTE *ptr;
44 int iState;
45 bool proc = false;
46 bool procEnd = false;
47
48 for(ptr = pStart, iState = 0; (ptr < pBatchEnd) && (iState != -1); ptr++)
49 {
50 switch(iState)
51 {
52 case 0:
53 if (*ptr == '\'')
54 {
55 iState = 1;
56 }
57 else if ((*ptr == ';') && !proc && !procEnd)
58 {
59 iState = -1;
60 }
61 else if ((*ptr == '/') && procEnd)
62 {
63 procEnd = false;
64 iState = -1;
65 }
66 else if ((*ptr == 'C') || (*ptr == 'c'))
67 {
68 if (!strnicmp((char *)ptr, "CREATE FUNCTION", 15) ||
69 !strnicmp((char *)ptr, "CREATE OR REPLACE FUNCTION", 26) ||
70 !strnicmp((char *)ptr, "CREATE PROCEDURE", 16) ||
71 !strnicmp((char *)ptr, "CREATE OR REPLACE PROCEDURE", 27))
72 {
73 proc = true;
74 }
75 }
76 else if (proc && ((*ptr == 'E') || (*ptr == 'e')))
77 {
78 if (!strnicmp((char *)ptr, "END", 3))
79 {
80 proc = false;
81 procEnd = true;
82 }
83 }
84 else if ((*ptr == '\r') || (*ptr == '\n'))
85 {
86 // CR/LF should be replaced with spaces, otherwise at least
87 // Oracle will fail on CREATE FUNCTION / CREATE PROCEDURE
88 *ptr = ' ';
89 }
90 break;
91 case 1:
92 if (*ptr == '\'')
93 iState = 0;
94 break;
95 }
96 }
97
98 *(ptr - 1) = 0;
99 return ptr + 1;
100 }
101
102 /**
103 * Execute SQL batch file. If file name contains @dbengine@ macro,
104 * it will be replaced with current database engine name in lowercase
105 */
106 bool ExecSQLBatch(const char *pszFile)
107 {
108 BYTE *pBatch, *pQuery, *pNext;
109 UINT32 dwSize;
110 bool result = false;
111
112 if (strstr(pszFile, "@dbengine@") != NULL)
113 {
114 static const TCHAR *dbengine[] = { _T("mysql"), _T("pgsql"), _T("mssql"), _T("oracle"), _T("sqlite"), _T("db2"), _T("informix") };
115
116 String name;
117 name.appendMBString(pszFile, strlen(pszFile), CP_ACP);
118 name.replace(_T("@dbengine@"), dbengine[g_dbSyntax]);
119 pBatch = LoadFile(name, &dwSize);
120 if (pBatch == NULL)
121 _tprintf(_T("ERROR: Cannot load SQL command file %s\n"), (const TCHAR *)name);
122 }
123 else
124 {
125 pBatch = LoadFileA(pszFile, &dwSize);
126 if (pBatch == NULL)
127 _tprintf(_T("ERROR: Cannot load SQL command file %hs\n"), pszFile);
128 }
129
130 if (pBatch != NULL)
131 {
132 for(pQuery = pBatch; pQuery < pBatch + dwSize; pQuery = pNext)
133 {
134 pNext = FindEndOfQuery(pQuery, pBatch + dwSize);
135 if (!IsEmptyQuery((char *)pQuery))
136 {
137 #ifdef UNICODE
138 WCHAR *wcQuery = WideStringFromMBString((char *)pQuery);
139 result = SQLQuery(wcQuery);
140 free(wcQuery);
141 #else
142 result = SQLQuery((char *)pQuery);
143 #endif
144 if (!result)
145 pNext = pBatch + dwSize;
146 }
147 }
148 free(pBatch);
149 }
150 return result;
151 }
152
153 /**
154 * Initialize database
155 */
156 void InitDatabase(const char *pszInitFile)
157 {
158 uuid_t guid;
159 TCHAR szQuery[256], szGUID[64];
160
161 _tprintf(_T("Initializing database...\n"));
162 if (!ExecSQLBatch(pszInitFile))
163 goto init_failed;
164
165 // Generate GUID for user "system"
166 _uuid_generate(guid);
167 _sntprintf(szQuery, 256, _T("UPDATE users SET guid='%s' WHERE id=0"),
168 _uuid_to_string(guid, szGUID));
169 if (!SQLQuery(szQuery))
170 goto init_failed;
171
172 // Generate GUID for user "admin"
173 _uuid_generate(guid);
174 _sntprintf(szQuery, 256, _T("UPDATE users SET guid='%s' WHERE id=1"),
175 _uuid_to_string(guid, szGUID));
176 if (!SQLQuery(szQuery))
177 goto init_failed;
178
179 // Generate GUID for "everyone" group
180 _uuid_generate(guid);
181 _sntprintf(szQuery, 256, _T("UPDATE user_groups SET guid='%s' WHERE id=%d"),
182 _uuid_to_string(guid, szGUID), GROUP_EVERYONE);
183 if (!SQLQuery(szQuery))
184 goto init_failed;
185
186 // Generate GUID for "Admins" group
187 _uuid_generate(guid);
188 _sntprintf(szQuery, 256, _T("UPDATE user_groups SET guid='%s' WHERE id=-2147483647"), _uuid_to_string(guid, szGUID));
189 if (!SQLQuery(szQuery))
190 goto init_failed;
191
192 _tprintf(_T("Database initialized successfully\n"));
193 return;
194
195 init_failed:
196 _tprintf(_T("Database initialization failed\n"));
197 }