Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions cycle.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,13 @@ function cycle_graphs() {
$width = get_request_var('width');
$height = get_request_var('height');

if (empty($tree_id)) $tree_id = db_fetch_cell('SELECT id FROM graph_tree ORDER BY name LIMIT 1');
if (empty($tree_id)) {
$tree_id = db_fetch_cell_prepared('SELECT id
FROM graph_tree
ORDER BY name
LIMIT 1',
array());
}
if (empty($id)) $id = -1;

/* get the start and end times for the graph */
Expand Down Expand Up @@ -165,10 +171,11 @@ function cycle() {
$height = get_request_var('height');

if (empty($tree_id)) {
$tree_id = db_fetch_cell('SELECT id
$tree_id = db_fetch_cell_prepared('SELECT id
FROM graph_tree
ORDER BY name
LIMIT 1');
LIMIT 1',
array());
}

if (empty($id)) {
Expand Down Expand Up @@ -401,4 +408,3 @@ function cycle() {

bottom_footer();
}

35 changes: 25 additions & 10 deletions setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ function cycle_check_upgrade () {

$info = plugin_cycle_version();
$current = $info['version'];
$old = db_fetch_row("SELECT * FROM plugin_config WHERE directory='cycle'");
$old = db_fetch_row_prepared('SELECT *
FROM plugin_config
WHERE directory = ?',
array('cycle'));

if (cacti_sizeof($old) && $current != $old['version']) {
/* if the plugin is installed and/or active */
Expand All @@ -78,22 +81,34 @@ function cycle_check_upgrade () {
api_plugin_register_realm('cycle', 'cycle.php,cycle_ajax.php', 'Plugin -> Cycle Graphs', 1);

/* get the realm id's and change from old to new */
$user = db_fetch_cell("SELECT id FROM plugin_realms WHERE file='cycle.php'")+100;
$users = db_fetch_assoc('SELECT user_id FROM user_auth_realm WHERE realm_id=42');
$user = db_fetch_cell_prepared('SELECT id
FROM plugin_realms
WHERE file = ?',
array('cycle.php')) + 100;
$legacy_realm_id = 42;
$users = db_fetch_assoc_prepared('SELECT user_id
FROM user_auth_realm
WHERE realm_id = ?',
array($legacy_realm_id));
if (sizeof($users)) {
foreach($users as $u) {
db_execute('INSERT INTO user_auth_realm
(realm_id, user_id) VALUES (' . $user . ', ' . $u['user_id'] . ')
ON DUPLICATE KEY UPDATE realm_id=VALUES(realm_id)');
db_execute('DELETE FROM user_auth_realm
WHERE user_id=' . $u['user_id'] . '
AND realm_id=' . $user);
db_execute_prepared('INSERT INTO user_auth_realm
(realm_id, user_id) VALUES (?, ?)
ON DUPLICATE KEY UPDATE realm_id=VALUES(realm_id)',
array($user, $u['user_id']));
db_execute_prepared('DELETE FROM user_auth_realm
WHERE user_id = ?
AND realm_id = ?',
array($u['user_id'], $legacy_realm_id));
}
}
}

/* update the plugin information */
$id = db_fetch_cell("SELECT id FROM plugin_config WHERE directory='cycle'");
$id = db_fetch_cell_prepared('SELECT id
FROM plugin_config
WHERE directory = ?',
array('cycle'));

/* remove legacy hook */
db_execute('DELETE FROM plugin_hooks WHERE name="cycle" AND hook="config_form"');
Expand Down
78 changes: 78 additions & 0 deletions tests/test_prepared_statements.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2026 The Cacti Group |
| |
| Regression checks for prepared DB helper migration in cycle plugin |
| |
| Run: php tests/test_prepared_statements.php |
+-------------------------------------------------------------------------+
*/

$pass = 0;
$fail = 0;

function assert_true($label, $value) {
global $pass, $fail;

if ($value) {
echo "PASS $label\n";
$pass++;
} else {
echo "FAIL $label\n";
$fail++;
}
}

$cycle_file = __DIR__ . '/../cycle.php';
$setup_file = __DIR__ . '/../setup.php';

$cycle_contents = file_get_contents($cycle_file);
$setup_contents = file_get_contents($setup_file);

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in ecb390d: added explicit readability checks and safe fallbacks before regex assertions.

assert_true('cycle.php is readable', $cycle_contents !== false);
assert_true('setup.php is readable', $setup_contents !== false);

$cycle_contents = ($cycle_contents === false ? '' : $cycle_contents);
$setup_contents = ($setup_contents === false ? '' : $setup_contents);

assert_true(
'cycle.php uses prepared tree-id lookup',
preg_match_all('/db_fetch_cell_prepared\s*\(\s*\'SELECT id\s+FROM graph_tree/s', $cycle_contents, $cycle_matches) >= 2
);
assert_true(
'cycle.php no longer uses raw tree-id db_fetch_cell lookup',
preg_match('/db_fetch_cell\s*\(\s*[\'"]SELECT\s+id\s+FROM\s+graph_tree\s+ORDER\s+BY\s+name\s+LIMIT\s+1[\'"]/i', $cycle_contents) === 0
);
assert_true(
'setup.php uses prepared plugin_config row lookup',
preg_match('/db_fetch_row_prepared\s*\(\s*\'SELECT \*\s+FROM plugin_config/s', $setup_contents) === 1
);
assert_true(
'setup.php uses prepared plugin_realm lookup',
preg_match('/db_fetch_cell_prepared\s*\(\s*\'SELECT id\s+FROM plugin_realms/s', $setup_contents) === 1
);
assert_true(
'setup.php uses prepared user realm list lookup',
preg_match('/db_fetch_assoc_prepared\s*\(\s*\'SELECT user_id\s+FROM user_auth_realm/s', $setup_contents) === 1
);
assert_true(
'setup.php uses prepared realm insert/delete updates',
preg_match_all('/db_execute_prepared\s*\(/', $setup_contents, $setup_execute_matches) >= 3
);
assert_true(
'setup.php preserves legacy realm migration semantics',
preg_match('/\$legacy_realm_id\s*=\s*42\s*;/', $setup_contents) === 1
&& preg_match('/INSERT INTO user_auth_realm\s*\(realm_id,\s*user_id\)\s*VALUES\s*\(\?,\s*\?\)/s', $setup_contents) === 1
&& preg_match('/DELETE FROM user_auth_realm[\s\S]*WHERE user_id = \?[\s\S]*AND realm_id = \?/s', $setup_contents) === 1
&& preg_match('/array\(\$u\[\'user_id\'\],\s*\$legacy_realm_id\)/', $setup_contents) === 1
);
assert_true(
'setup.php no longer concatenates user_id in SQL strings',
strpos($setup_contents, "WHERE user_id=' . \$u['user_id'] . '") === false
);

echo "\n";
echo "Results: $pass passed, $fail failed\n";

exit($fail > 0 ? 1 : 0);