@@ -126,6 +126,52 @@ function syslog_sendemail($to, $from, $subject, $message, $smsmessage = '') {
126126 }
127127}
128128
129+ function syslog_get_import_xml_payload ($ redirect_url ) {
130+ if (trim (get_nfilter_request_var ('import_text ' )) != '' ) {
131+ /* textbox input */
132+ return get_nfilter_request_var ('import_text ' );
133+ }
134+
135+ if (isset ($ _FILES ['import_file ' ]['tmp_name ' ]) &&
136+ $ _FILES ['import_file ' ]['tmp_name ' ] != 'none ' &&
137+ $ _FILES ['import_file ' ]['tmp_name ' ] != '' ) {
138+ /* file upload */
139+ $ tmp_name = $ _FILES ['import_file ' ]['tmp_name ' ];
140+
141+ if (!isset ($ _FILES ['import_file ' ]['error ' ]) || $ _FILES ['import_file ' ]['error ' ] !== UPLOAD_ERR_OK ) {
142+ header ('Location: ' . $ redirect_url );
143+ exit ;
144+ }
145+
146+ if (!is_uploaded_file ($ tmp_name )) {
147+ header ('Location: ' . $ redirect_url );
148+ exit ;
149+ }
150+
151+ $ fp = fopen ($ tmp_name , 'rb ' );
152+
153+ if ($ fp === false ) {
154+ cacti_log ('SYSLOG ERROR: Failed to open uploaded import file ' , false , 'SYSTEM ' );
155+ header ('Location: ' . $ redirect_url );
156+ exit ;
157+ }
158+
159+ $ xml_data = fread ($ fp , filesize ($ tmp_name ));
160+ fclose ($ fp );
161+
162+ if ($ xml_data === false ) {
163+ cacti_log ('SYSLOG ERROR: Failed to read uploaded import file ' , false , 'SYSTEM ' );
164+ header ('Location: ' . $ redirect_url );
165+ exit ;
166+ }
167+
168+ return $ xml_data ;
169+ }
170+
171+ header ('Location: ' . $ redirect_url );
172+ exit ;
173+ }
174+
129175function syslog_is_partitioned () {
130176 global $ syslogdb_default ;
131177
@@ -187,184 +233,86 @@ function syslog_partition_manage() {
187233}
188234
189235/**
190- * Validate tables that support partition maintenance.
191- *
192- * Any value added to the allowlist MUST match ^[a-z_]+$ so it is safe
193- * for identifier interpolation in DDL statements (MySQL does not support
194- * parameter binding for identifiers).
195- */
196- function syslog_partition_table_allowed ($ table ) {
197- if (!in_array ($ table , array ('syslog ' , 'syslog_removed ' ), true )) {
198- return false ;
199- }
200-
201- /* Defense-in-depth: reject values unsafe for identifier interpolation. */
202- if (!preg_match ('/^[a-z_]+$/ ' , $ table )) {
203- return false ;
204- }
205-
206- return true ;
207- }
208-
209- /**
210- * Create a new partition for the specified table.
211- *
212- * @return bool true on success, false on lock failure or disallowed table.
236+ * This function will create a new partition for the specified table.
213237 */
214238function syslog_partition_create ($ table ) {
215239 global $ syslogdb_default ;
216240
217- if (!syslog_partition_table_allowed ($ table )) {
218- return false ;
219- }
241+ /* determine the format of the table name */
242+ $ time = time ();
243+ $ cformat = 'd ' . date ('Ymd ' , $ time );
244+ $ lnow = date ('Y-m-d ' , $ time +86400 );
220245
221- /* Hash to guarantee the lock name stays within MySQL's 64-byte limit. */
222- $ lock_name = substr (hash ('sha256 ' , $ syslogdb_default . '.syslog_partition_create. ' . $ table ), 0 , 60 );
246+ $ exists = syslog_db_fetch_row ("SELECT *
247+ FROM `information_schema`.`partitions`
248+ WHERE table_schema=' " . $ syslogdb_default . "'
249+ AND partition_name=' " . $ cformat . "'
250+ AND table_name='syslog'
251+ ORDER BY partition_ordinal_position " );
223252
224- /*
225- * 10-second timeout is sufficient: partition maintenance runs once per
226- * poller cycle (typically 5 minutes), so sustained contention is not
227- * expected. A failure is logged so monitoring can detect repeated misses.
228- */
229- $ locked = syslog_db_fetch_cell_prepared ('SELECT GET_LOCK(?, 10) ' , array ($ lock_name ));
253+ if (!cacti_sizeof ($ exists )) {
254+ cacti_log ("SYSLOG: Creating new partition ' $ cformat' " , false , 'SYSTEM ' );
230255
231- if ($ locked === null ) {
232- /* NULL means the GET_LOCK call itself failed, not just contention. */
233- cacti_log ("SYSLOG: GET_LOCK call failed for partition create on ' $ table' " , false , 'SYSTEM ' );
234- return false ;
235- }
256+ syslog_debug ("Creating new partition ' $ cformat' " );
236257
237- if (( int ) $ locked !== 1 ) {
238- cacti_log ( " SYSLOG: Unable to acquire partition create lock for ' $ table ' " , false , ' SYSTEM ' );
239- return false ;
258+ syslog_db_execute ( " ALTER TABLE ` " . $ syslogdb_default . " `.` $ table ` REORGANIZE PARTITION dMaxValue INTO (
259+ PARTITION $ cformat VALUES LESS THAN (TO_DAYS(' $ lnow ')),
260+ PARTITION dMaxValue VALUES LESS THAN MAXVALUE) " ) ;
240261 }
241-
242- try {
243- /* determine the format of the table name */
244- $ time = time ();
245- $ cformat = 'd ' . date ('Ymd ' , $ time );
246- $ lnow = date ('Y-m-d ' , $ time +86400 );
247-
248- $ exists = syslog_db_fetch_row_prepared ("SELECT *
249- FROM `information_schema`.`partitions`
250- WHERE table_schema = ?
251- AND partition_name = ?
252- AND table_name = ?
253- ORDER BY partition_ordinal_position " ,
254- array ($ syslogdb_default , $ cformat , $ table ));
255-
256- if (!cacti_sizeof ($ exists )) {
257- cacti_log ("SYSLOG: Creating new partition ' $ cformat' " , false , 'SYSTEM ' );
258-
259- syslog_debug ("Creating new partition ' $ cformat' " );
260-
261- /*
262- * MySQL does not support parameter binding for DDL identifiers
263- * or partition definitions. $table is safe because it passed
264- * syslog_partition_table_allowed() (two-value allowlist plus
265- * regex guard). $cformat and $lnow derive from date() and
266- * contain only digits, hyphens, and the letter 'd'.
267- */
268- syslog_db_execute ("ALTER TABLE ` " . $ syslogdb_default . "`.` $ table` REORGANIZE PARTITION dMaxValue INTO (
269- PARTITION $ cformat VALUES LESS THAN (TO_DAYS(' $ lnow')),
270- PARTITION dMaxValue VALUES LESS THAN MAXVALUE) " );
271- }
272- } finally {
273- syslog_db_fetch_cell_prepared ('SELECT RELEASE_LOCK(?) ' , array ($ lock_name ));
274- }
275-
276- return true ;
277262}
278263
279264/**
280- * Remove old partitions for the specified table.
265+ * This function will remove all old partitions for the specified table.
281266 */
282267function syslog_partition_remove ($ table ) {
283268 global $ syslogdb_default ;
284269
285- if (!syslog_partition_table_allowed ($ table )) {
286- cacti_log ("SYSLOG: partition_remove called with disallowed table ' $ table' " , false , 'SYSTEM ' );
287- return 0 ;
288- }
289-
290- $ lock_name = substr (hash ('sha256 ' , $ syslogdb_default . '.syslog_partition_remove. ' . $ table ), 0 , 60 );
291-
292- $ locked = syslog_db_fetch_cell_prepared ('SELECT GET_LOCK(?, 10) ' , array ($ lock_name ));
293-
294- if ($ locked === null ) {
295- cacti_log ("SYSLOG: GET_LOCK call failed for partition remove on ' $ table' " , false , 'SYSTEM ' );
296- return 0 ;
297- }
298-
299- if ((int )$ locked !== 1 ) {
300- cacti_log ("SYSLOG: Unable to acquire partition remove lock for ' $ table' " , false , 'SYSTEM ' );
301- return 0 ;
302- }
303-
304270 $ syslog_deleted = 0 ;
271+ $ number_of_partitions = syslog_db_fetch_assoc ("SELECT *
272+ FROM `information_schema`.`partitions`
273+ WHERE table_schema=' " . $ syslogdb_default . "' AND table_name='syslog'
274+ ORDER BY partition_ordinal_position " );
305275
306- try {
307- $ number_of_partitions = syslog_db_fetch_assoc_prepared ("SELECT *
308- FROM `information_schema`.`partitions`
309- WHERE table_schema = ? AND table_name = ?
310- ORDER BY partition_ordinal_position " ,
311- array ($ syslogdb_default , $ table ));
312-
313- $ days = read_config_option ('syslog_retention ' );
276+ $ days = read_config_option ('syslog_retention ' );
314277
315- syslog_debug ("There are currently ' " . sizeof ($ number_of_partitions ) . "' Syslog Partitions, We will keep ' $ days' of them. " );
278+ syslog_debug ("There are currently ' " . sizeof ($ number_of_partitions ) . "' Syslog Partitions, We will keep ' $ days' of them. " );
316279
317- if ($ days > 0 ) {
318- $ user_partitions = sizeof ($ number_of_partitions ) - 1 ;
319- if ($ user_partitions >= $ days ) {
320- $ i = 0 ;
321- while ($ user_partitions > $ days ) {
322- $ oldest = $ number_of_partitions [$ i ];
280+ if ($ days > 0 ) {
281+ $ user_partitions = sizeof ($ number_of_partitions ) - 1 ;
282+ if ($ user_partitions >= $ days ) {
283+ $ i = 0 ;
284+ while ($ user_partitions > $ days ) {
285+ $ oldest = $ number_of_partitions [$ i ];
323286
324- cacti_log ("SYSLOG: Removing old partition ' " . $ oldest ['PARTITION_NAME ' ] . "' " , false , 'SYSTEM ' );
287+ cacti_log ("SYSLOG: Removing old partition ' " . $ oldest ['PARTITION_NAME ' ] . "' " , false , 'SYSTEM ' );
325288
326- syslog_debug ("Removing partition ' " . $ oldest ['PARTITION_NAME ' ] . "' " );
289+ syslog_debug ("Removing partition ' " . $ oldest ['PARTITION_NAME ' ] . "' " );
327290
328- syslog_db_execute ("ALTER TABLE ` " . $ syslogdb_default . "`.` $ table` DROP PARTITION " . $ oldest ['PARTITION_NAME ' ]);
291+ syslog_db_execute ("ALTER TABLE ` " . $ syslogdb_default . "`.` $ table` DROP PARTITION " . $ oldest ['PARTITION_NAME ' ]);
329292
330- $ i ++;
331- $ user_partitions --;
332- $ syslog_deleted ++;
333- }
293+ $ i ++;
294+ $ user_partitions --;
295+ $ syslog_deleted ++;
334296 }
335297 }
336- } finally {
337- syslog_db_fetch_cell_prepared ('SELECT RELEASE_LOCK(?) ' , array ($ lock_name ));
338298 }
339299
340300 return $ syslog_deleted ;
341301}
342302
343- /*
344- * syslog_partition_check is a read-only SELECT against information_schema.
345- * It does not execute DDL, so it does not need the named lock that
346- * syslog_partition_create and syslog_partition_remove acquire. External
347- * serialization is provided by the poller cycle calling
348- * syslog_partition_manage().
349- */
350303function syslog_partition_check ($ table ) {
351304 global $ syslogdb_default ;
352305
353- if (!syslog_partition_table_allowed ($ table )) {
354- return false ;
355- }
356-
357306 if (defined ('SYSLOG_CONFIG ' )) {
358307 include (SYSLOG_CONFIG );
359308 }
360309
361310 /* find date of last partition */
362- $ last_part = syslog_db_fetch_cell_prepared ("SELECT PARTITION_NAME
311+ $ last_part = syslog_db_fetch_cell ("SELECT PARTITION_NAME
363312 FROM `information_schema`.`partitions`
364- WHERE table_schema = ? AND table_name = ?
313+ WHERE table_schema=' " . $ syslogdb_default . " ' AND table_name='syslog'
365314 ORDER BY partition_ordinal_position DESC
366- LIMIT 1,1 " ,
367- array ($ syslogdb_default , $ table ));
315+ LIMIT 1,1; " );
368316
369317 $ lformat = str_replace ('d ' , '' , $ last_part );
370318 $ cformat = date ('Ymd ' );
0 commit comments