1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21 #include "db.h"
22 #include "dbupgrade.h"
23 #include "log.h"
24
25 /*
26 * 4.0 maintenance database patches
27 */
28
29 #ifndef HAVE_SQLITE3
30
31 extern unsigned char program_type;
32
DBpatch_4000000(void)33 static int DBpatch_4000000(void)
34 {
35 return SUCCEED;
36 }
37
38 /******************************************************************************
39 * *
40 * Function: str_rename_macro *
41 * *
42 * Purpose: rename macros in the string *
43 * *
44 * Parameters: in - [IN] the input string *
45 * oldmacro - [IN] the macro to rename *
46 * newmacro - [IN] the new macro name *
47 * out - [IN/OUT] the string with renamed macros *
48 * out_alloc - [IN/OUT] the output buffer size *
49 * *
50 * Return value: SUCCEED - macros were found and renamed *
51 * FAIL - no target macros were found *
52 * *
53 * Comments: If the oldmacro is found in input string then all occurrences of *
54 * it are replaced with the new macro in the output string. *
55 * Otherwise the output string is not changed. *
56 * *
57 ******************************************************************************/
str_rename_macro(const char * in,const char * oldmacro,const char * newmacro,char ** out,size_t * out_alloc)58 static int str_rename_macro(const char *in, const char *oldmacro, const char *newmacro, char **out,
59 size_t *out_alloc)
60 {
61 zbx_token_t token;
62 int pos = 0, ret = FAIL;
63 size_t out_offset = 0, newmacro_len;
64
65 newmacro_len = strlen(newmacro);
66 zbx_strcpy_alloc(out, out_alloc, &out_offset, in);
67 out_offset++;
68
69 for (; SUCCEED == zbx_token_find(*out, pos, &token, ZBX_TOKEN_SEARCH_BASIC); pos++)
70 {
71 switch (token.type)
72 {
73 case ZBX_TOKEN_MACRO:
74 pos = token.loc.r;
75 if (0 == strncmp(*out + token.loc.l, oldmacro, token.loc.r - token.loc.l + 1))
76 {
77 pos += zbx_replace_mem_dyn(out, out_alloc, &out_offset, token.loc.l,
78 token.loc.r - token.loc.l + 1, newmacro, newmacro_len);
79 ret = SUCCEED;
80 }
81 break;
82
83 case ZBX_TOKEN_USER_MACRO:
84 case ZBX_TOKEN_SIMPLE_MACRO:
85 pos = token.loc.r;
86 break;
87 }
88 }
89
90 return ret;
91 }
92
93 /******************************************************************************
94 * *
95 * Function: db_rename_macro *
96 * *
97 * Purpose: rename macro in the specified database fields *
98 * *
99 * Parameters: result - [IN] database query with fields to replace. First *
100 * field is table id field, following with *
101 * the target fields listed in fields parameter *
102 * table - [IN] the target table name *
103 * pkey - [IN] the primary key field name *
104 * fields - [IN] the table fields to check for macros and *
105 * rename if found *
106 * fields_num - [IN] the number of fields to check *
107 * oldmacro - [IN] the macro to rename *
108 * newmacro - [IN] the new macro name *
109 * *
110 * Return value: SUCCEED - macros were renamed successfully *
111 * FAIL - database error occurred *
112 * *
113 ******************************************************************************/
db_rename_macro(DB_RESULT result,const char * table,const char * pkey,const char ** fields,int fields_num,const char * oldmacro,const char * newmacro)114 static int db_rename_macro(DB_RESULT result, const char *table, const char *pkey, const char **fields,
115 int fields_num, const char *oldmacro, const char *newmacro)
116 {
117 DB_ROW row;
118 char *sql = 0, *field = NULL, *field_esc;
119 size_t sql_alloc = 4096, sql_offset = 0, field_alloc = 0, old_offset;
120 int i, ret = SUCCEED;
121
122 sql = zbx_malloc(NULL, sql_alloc);
123
124 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
125
126 while (NULL != (row = DBfetch(result)))
127 {
128 old_offset = sql_offset;
129
130 for (i = 0; i < fields_num; i++)
131 {
132 if (SUCCEED == str_rename_macro(row[i + 1], oldmacro, newmacro, &field, &field_alloc))
133 {
134 if (old_offset == sql_offset)
135 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update %s set ", table);
136 else
137 zbx_chrcpy_alloc(&sql, &sql_alloc, &sql_offset, ',');
138
139 field_esc = DBdyn_escape_string(field);
140 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%s='%s'", fields[i], field_esc);
141 zbx_free(field_esc);
142 }
143 }
144
145 if (old_offset != sql_offset)
146 {
147 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where %s=%s;\n", pkey, row[0]);
148 if (SUCCEED != (ret = DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset)))
149 goto out;
150 }
151 }
152
153 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
154
155 if (16 < sql_offset && ZBX_DB_OK > DBexecute("%s", sql))
156 ret = FAIL;
157 out:
158 zbx_free(field);
159 zbx_free(sql);
160
161 return ret;
162 }
163
DBpatch_4000001(void)164 static int DBpatch_4000001(void)
165 {
166 DB_RESULT result;
167 int ret;
168 const char *fields[] = {"def_shortdata", "def_longdata", "r_shortdata", "r_longdata", "ack_shortdata",
169 "ack_longdata"};
170
171 /* 0 - EVENT_SOURCE_TRIGGERS */
172 result = DBselect("select actionid,def_shortdata,def_longdata,r_shortdata,r_longdata,ack_shortdata,"
173 "ack_longdata from actions where eventsource=0");
174
175 ret = db_rename_macro(result, "actions", "actionid", fields, ARRSIZE(fields), "{TRIGGER.NAME}",
176 "{EVENT.NAME}");
177
178 DBfree_result(result);
179
180 return ret;
181 }
182
DBpatch_4000002(void)183 static int DBpatch_4000002(void)
184 {
185 DB_RESULT result;
186 int ret;
187 const char *fields[] = {"subject", "message"};
188
189 /* 0 - EVENT_SOURCE_TRIGGERS */
190 result = DBselect("select om.operationid,om.subject,om.message"
191 " from opmessage om,operations o,actions a"
192 " where om.operationid=o.operationid"
193 " and o.actionid=a.actionid"
194 " and a.eventsource=0");
195
196 ret = db_rename_macro(result, "opmessage", "operationid", fields, ARRSIZE(fields), "{TRIGGER.NAME}",
197 "{EVENT.NAME}");
198
199 DBfree_result(result);
200
201 return ret;
202 }
203
DBpatch_4000003(void)204 static int DBpatch_4000003(void)
205 {
206 DB_RESULT result;
207 int ret;
208 const char *fields[] = {"command"};
209
210 /* 0 - EVENT_SOURCE_TRIGGERS */
211 result = DBselect("select oc.operationid,oc.command"
212 " from opcommand oc,operations o,actions a"
213 " where oc.operationid=o.operationid"
214 " and o.actionid=a.actionid"
215 " and a.eventsource=0");
216
217 ret = db_rename_macro(result, "opcommand", "operationid", fields, ARRSIZE(fields), "{TRIGGER.NAME}",
218 "{EVENT.NAME}");
219
220 DBfree_result(result);
221
222 return ret;
223 }
224
DBpatch_4000004(void)225 static int DBpatch_4000004(void)
226 {
227 int i;
228 const char *values[] = {
229 "alarm_ok",
230 "no_sound",
231 "alarm_information",
232 "alarm_warning",
233 "alarm_average",
234 "alarm_high",
235 "alarm_disaster"
236 };
237
238 if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER))
239 return SUCCEED;
240
241 for (i = 0; i < (int)ARRSIZE(values); i++)
242 {
243 if (ZBX_DB_OK > DBexecute(
244 "update profiles"
245 " set value_str='%s.mp3'"
246 " where value_str='%s.wav'"
247 " and idx='web.messages'", values[i], values[i]))
248 {
249 return FAIL;
250 }
251 }
252
253 return SUCCEED;
254 }
255
DBpatch_4000005(void)256 static int DBpatch_4000005(void)
257 {
258 DB_RESULT result;
259 DB_ROW row;
260 zbx_uint64_t time_period_id, every;
261 int invalidate = 0;
262 const ZBX_TABLE *timeperiods;
263 const ZBX_FIELD *field;
264
265 if (NULL != (timeperiods = DBget_table("timeperiods")) &&
266 NULL != (field = DBget_field(timeperiods, "every")))
267 {
268 ZBX_STR2UINT64(every, field->default_value);
269 }
270 else
271 {
272 THIS_SHOULD_NEVER_HAPPEN;
273 return FAIL;
274 }
275
276 result = DBselect("select timeperiodid from timeperiods where every=0");
277
278 while (NULL != (row = DBfetch(result)))
279 {
280 ZBX_STR2UINT64(time_period_id, row[0]);
281
282 zabbix_log(LOG_LEVEL_WARNING, "Invalid maintenance time period found: "ZBX_FS_UI64
283 ", changing \"every\" to "ZBX_FS_UI64, time_period_id, every);
284 invalidate = 1;
285 }
286
287 DBfree_result(result);
288
289 if (0 != invalidate &&
290 ZBX_DB_OK > DBexecute("update timeperiods set every=1 where timeperiodid!=0 and every=0"))
291 return FAIL;
292
293 return SUCCEED;
294 }
295
DBpatch_4000006(void)296 static int DBpatch_4000006(void)
297 {
298 if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER))
299 return SUCCEED;
300
301 if (ZBX_DB_OK > DBexecute("delete from profiles where idx='web.screens.graphid'"))
302 return FAIL;
303
304 return SUCCEED;
305 }
306
307 #endif
308
309 DBPATCH_START(4000)
310
311 /* version, duplicates flag, mandatory flag */
312
313 DBPATCH_ADD(4000000, 0, 1)
314 DBPATCH_ADD(4000001, 0, 0)
315 DBPATCH_ADD(4000002, 0, 0)
316 DBPATCH_ADD(4000003, 0, 0)
317 DBPATCH_ADD(4000004, 0, 0)
318 DBPATCH_ADD(4000005, 0, 0)
319 DBPATCH_ADD(4000006, 0, 0)
320
321 DBPATCH_END()
322