0) { $exists = db_fetch_cell_prepared('SELECT id FROM graph_tree_items WHERE parent = ? AND graph_tree_id = ? AND host_id = ?', array($pdata['leaf_id'], $tree_id, $data['host'])); if ($exists) { print 'tbranch:' . $exists; return; } } elseif ($data['graph'] > 0) { $exists = db_fetch_cell_prepared('SELECT id FROM graph_tree_items WHERE parent = ? AND graph_tree_id = ? AND local_graph_id = ?', array($pdata['leaf_id'], $tree_id, $data['graph'])); if ($exists) { print 'tbranch:' . $exists; return; } } else { $title = db_fetch_cell_prepared('SELECT title FROM graph_tree_items WHERE id = ?', array($data['leaf_id'])); } $save = array(); $save['parent'] = $pdata['leaf_id']; $save['position'] = $new_position; $save['graph_tree_id'] = $tree_id; $save['local_graph_id'] = $data['graph']; $save['host_id'] = $data['host']; $save['host_grouping_type'] = 1; $save['sort_children_type'] = 1; $save['title'] = $title; $id = sql_save($save, 'graph_tree_items'); api_tree_sort_branch($id, $tree_id); header('Content-Type: application/json; charset=utf-8'); print json_encode(array('id' => 'tbranch:' . $id)); } /* api_tree_get_lock - given a lock name, placed a timeed lock on the database. * This function allows simulating transactions in an MyISAM database. * @arg $lockname - The name of the lock to be created * @returns - true depending on outcome */ function api_tree_get_lock($lockname, $timeout = 10) { input_validate_input_number($timeout); $lockname = sanitize_search_string($lockname); while (true) { $locked = db_fetch_cell("SELECT GET_LOCK('$lockname', $timeout)"); if ($locked) { return true; } else { sleep(1); } } } /* api_tree_release_lock - given a lock name, release that lock. * This function allows simulating transactions in an MyISAM database. * @arg $lockname - The name of the lock to be released * @returns - true or false depending on outcome */ function api_tree_release_lock($lockname) { $lockname = sanitize_search_string($lockname); $unlocked = db_fetch_cell("SELECT RELEASE_LOCK('$lockname')"); } /* api_tree_create_node - given a tree, a desintation leaf_id, order position, and title, create a branch/leaf. * @arg $tree_id - The tree to remove from * @arg $node_id - The branch/leaf to place the new branch/leaf * @arg $title - The new brnach/leaf title * @returns - json encoded new leaf information */ function api_tree_create_node($tree_id, $node_id, $position, $title = 'New Branch') { input_validate_input_number($tree_id); input_validate_input_number($position); /* clean up text string */ if (isset($title)) { $title = sanitize_search_string(htmlspecialchars_decode($title)); } $data = api_tree_parse_node_data($node_id); if ($data['leaf_id'] < 0) { cacti_log("ERROR: Invalid BranchID: '" . (isset($data['leaf_id']) ? $data['leaf_id']:'-') . "', Function create_node", false); return; } $i = 0; $found = false; $orig = $title; while(true) { $title = $orig . ($found ? ' (' . $i . ')':''); $exists_id = api_tree_branch_exists($tree_id, $data['leaf_id'], $title); if ($exists_id == false) { break; } else { $found = true; $i++; } } /* watch out for monkey business */ input_validate_input_number($data['leaf_id']); $save = array(); $save['parent'] = $data['leaf_id']; $save['position'] = $position; $save['graph_tree_id'] = $tree_id; $save['local_graph_id'] = 0; $save['host_id'] = 0; $save['host_grouping_type'] = 1; $save['sort_children_type'] = 1; $save['title'] = $title; $id = sql_save($save, 'graph_tree_items'); api_tree_sort_branch($id, $tree_id); header('Content-Type: application/json; charset=utf-8'); print json_encode(array('id' => 'tbranch:' . $id, 'text' => $title)); } /* api_tree_branch_exists - given a tree, parent branch, and a title, will check for a branch * @arg $tree_id - The tree_id to search * @arg $parent - The parent leaf_id to search * @arg $title - The branch name to search for * @returns - the id of the branch if it exists */ function api_tree_branch_exists($tree_id, $parent, $title) { $id = db_fetch_cell_prepared('SELECT id FROM graph_tree_items WHERE graph_tree_id = ? AND parent = ? AND title = ?', array($tree_id, $parent, $title)); if ($id > 0) { return $id; } else { return false; } } /* api_tree_host_exists - given a tree, parent branch, and a host_id, will check host on that branch * @arg $tree_id - The tree_id to search * @arg $parent - The parent leaf_id to search * @arg $host_id - The host_id to search for * @returns - the id of the leaf if it exists */ function api_tree_host_exists($tree_id, $parent, $host_id) { $id = db_fetch_cell_prepared('SELECT id FROM graph_tree_items WHERE graph_tree_id = ? AND parent = ? AND host_id = ?', array($tree_id, $parent, $host_id)); if ($id > 0) { return $id; } else { return false; } } /* api_tree_graph_exists - given a tree, parent branch, and a local_graph_id, will check graph on that branch * @arg $tree_id - The tree_id to search * @arg $parent - The parent leaf_id to search * @arg $local_graph_id - The local_graph_id to search for * @returns - the id of the leaf if it exists */ function api_tree_graph_exists($tree_id, $parent, $local_graph_id) { $id = db_fetch_cell_prepared('SELECT id FROM graph_tree_items WHERE graph_tree_id = ? AND parent = ? AND local_graph_id = ?', array($tree_id, $parent, $local_graph_id)); if ($id > 0) { return $id; } else { return false; } } /* api_tree_delete - given a tree and a branch/leaf, delete the node and it's content * @arg $tree_id - The tree to remove from * @arg $leaf_id - The branch to remove * @returns - null */ function api_tree_delete_node($tree_id, $node_id) { input_validate_input_number($tree_id); // Basic Error Checking if (empty($tree_id) || $tree_id < 0) { cacti_log("ERROR: Invalid TreeID: '$tree_id', Function delete_node", false); return; } if (empty($node_id)) { cacti_log("ERROR: Invalid NodeID: '$node_id', Function delete_node", false); return; } $data = api_tree_parse_node_data($node_id); if (isset($data['leaf_id']) && $data['leaf_id'] > 0) { if ($data['host'] == 0 && $data['graph'] == 0) { api_tree_delete_node_content($tree_id, $data['leaf_id']); } db_execute_prepared('DELETE FROM graph_tree_items WHERE graph_tree_id = ? AND id = ?', array($tree_id, $data['leaf_id'])); } } /* api_tree_delete_content - given a tree and a branch/leaf, recursively remove all elements * @arg $tree_id - The tree to remove from * @arg $leaf_id - The branch to remove * @returns - null */ function api_tree_delete_node_content($tree_id, $leaf_id) { $children = db_fetch_assoc_prepared('SELECT * FROM graph_tree_items WHERE graph_tree_id = ? AND parent = ?', array($tree_id, $leaf_id)); if (sizeof($children)) { foreach($children as $child) { if ($child['host_id'] == 0 && $child['graph_id'] == 0) { api_tree_delete_node_content($tree_id, $child['id']); } db_execute_prepared('DELETE FROM graph_tree_items WHERE graph_tree_id = ? AND id = ?', array($tree_id, $child['id'])); } } } /* api_tree_move_node - given the current node information and it's new branch, move it. * @arg $variable - The request variable to parse * @returns - array of information about the variable */ function api_tree_move_node($tree_id, $node_id, $new_parent, $new_position) { input_validate_input_number($tree_id); input_validate_input_number($new_position); $new_position++; // Basic Error Checking if (empty($tree_id) || $tree_id < 0) { cacti_log("ERROR: Invalid TreeID: '$tree_id', Function delete_node", false); return; } if (empty($node_id)) { cacti_log("ERROR: Invalid NodeID: '$node_id', Function move_node", false); return; } if (empty($new_parent)) { cacti_log("ERROR: Invalid Parent Node '$new_parent' for NodeID: '$node_id', Function move_node", false); return; } elseif ($new_parent == '#') { $pdata['leaf_id'] = 0; } else { $pdata = api_tree_parse_node_data($new_parent); } $data = api_tree_parse_node_data($node_id); if ($data['parent'] != $pdata['leaf_id']) { db_execute_prepared('UPDATE graph_tree_items SET parent = ?, position = ? WHERE id = ? AND graph_tree_id = ?', array($pdata['leaf_id'], $new_position, $data['leaf_id'], $tree_id)); $others = db_fetch_assoc_prepared('SELECT id FROM graph_tree_items WHERE parent = ? AND id != ? AND position >= ?', array($pdata['leaf_id'], $data['leaf_id'], $new_position)); $position = $new_position + 1; if (sizeof($others)) { foreach($others as $other) { db_execute_prepared('UPDATE graph_tree_items SET position = ? WHERE id = ?', array($position, $other['id'])); $position++; } } api_tree_sort_branch($data['leaf_id'], $tree_id); } elseif (isset($data['leaf_id']) && $data['leaf_id'] > 0 && isset($pdata['leaf_id']) && $pdata['leaf_id'] >= 0) { db_execute_prepared('UPDATE graph_tree_items SET position = ? WHERE graph_tree_id = ? AND id = ?', array($new_position, $tree_id, $data['leaf_id'])); $others = db_fetch_assoc_prepared('SELECT id FROM graph_tree_items WHERE parent = ? AND id != ? AND position >= ?', array($pdata['leaf_id'], $data['leaf_id'], $new_position)); $position = $new_position + 1; if (sizeof($others)) { foreach($others as $other) { db_execute_prepared('UPDATE graph_tree_items SET position = ? WHERE id = ?', array($position, $other['id'])); $position++; } } api_tree_sort_branch($data['leaf_id'], $tree_id); } else { cacti_log('Invalid Source Destination Branches, Function move_node', false); } return; } /* api_tree_parse_node_data - given the node information parse into a branch, parent, host, graph array * @arg $variable - The request variable to parse * @returns - array of information about the variable */ function api_tree_parse_node_data($variable) { // Initialize some variables $leaf_id = 0; $graph_id = 0; $host_id = 0; if ($variable != '#') { // Process the 'id' variable $ndata = explode('_', $variable); if (sizeof($ndata)) { foreach($ndata as $data) { list($type, $tid) = explode(':', $data); /* watch out for monkey business */ input_validate_input_number($tid); switch ($type) { case 'tbranch': $leaf_id = $tid; break; case 'tgraph': $graph_id = $tid; break; case 'thost': $host_id = $tid; break; } } } } if ($leaf_id > 0) { $parent = db_fetch_cell_prepared('SELECT parent FROM graph_tree_items WHERE id = ?', array($leaf_id)); } else { $parent = '0'; } return array('leaf_id' => $leaf_id, 'graph' => $graph_id, 'host' => $host_id, 'parent' => $parent); } /* api_tree_rename_node - given the tree and the node information rename the tree branch/leaf. * This function is used for editing. * @arg $tree_id - The id of the tree you are parsing * @arg $node_id - The branch/leaf id of the node to be renamed * @arg $text - The new branch/leaf title * @returns - string of the tree items in html format */ function api_tree_rename_node($tree_id, $node_id = '', $text = '') { input_validate_input_number($tree_id); /* clean up text string */ $text = sanitize_search_string(htmlspecialchars_decode($text)); // Basic Error Checking if ($tree_id <= 0) { cacti_log("ERROR: Invalid TreeID: '" . $tree_id . "', Function rename_node", false); header('Content-Type: application/json; charset=utf-8'); print json_encode(array('id' => $node_id, 'result' => false)); return; } if (empty($node_id)) { cacti_log("ERROR: Invalid NodeID: '" . $node_id . "', Function rename_node", false); header('Content-Type: application/json; charset=utf-8'); print json_encode(array('id' => $node_id, 'result' => 'false')); return; } // Initialize some variables $leaf_id = 0; $graph_id = 0; $host_id = 0; // Process the 'id' variable $ndata = explode('_', $node_id); if (sizeof($ndata)) { foreach($ndata as $data) { list($type, $tid) = explode(':', $data); /* watch out for monkey business */ input_validate_input_number($tid); switch ($type) { case 'tbranch': $leaf_id = $tid; break; case 'tgraph': $graph_id = $tid; break; case 'thost': $host_id = $tid; break; } } } if (isset($leaf_id) && $leaf_id > 0) { if ($host_id > 0 || $graph_id > 0) { // Ignore. Need to customize context } else { db_execute_prepared('UPDATE graph_tree_items SET title = ? WHERE graph_tree_id = ? AND id = ?', array($text, $tree_id, $leaf_id)); } } header('Content-Type: application/json; charset=utf-8'); print json_encode(array('id' => $node_id, 'result' => 'true')); } /* api_tree_get_main - given the tree and the parent node information return tree elements. * This function is used for graphing. * @arg $tree_id - The id of the tree you are parsing * @arg $parent - The parent id of the branch/leaf * @returns - string of the tree items in html format */ function api_tree_get_main($tree_id, $parent = 0) { $is_root = false; if ($parent == -1) { $parent = 0; $is_root = true; if ($tree_id > 0) { $name = db_fetch_cell_prepared('SELECT name FROM graph_tree WHERE id = ?', array($tree_id)); print "\n"; } } /* api_tree_get_node - given the tree and the node information return tree elements * @arg $tree_id - The id of the tree you are parsing * @arg $node_id - The encoded node id of the branch/leaf * @returns - string of the tree items in html format */ function api_tree_get_node($tree_id, $node_id) { if ($node_id == '#') { $heirarchy = draw_dhtml_tree_level($tree_id, 0); } else { $data = api_tree_parse_node_data($node_id); $id = $data['leaf_id']; input_validate_input_number($id); $heirarchy = draw_dhtml_tree_level($tree_id, $id); } if (sizeof($heirarchy)) { foreach($heirarchy as $h) { print $h; } } } /** api_tree_item_save - saves the tree object and then resorts the tree * @arg $id - the leaf_id for the object * @arg $tree_id - the tree id for the object * @arg $type - the item type graph, host, leaf * @arg $parent_tree_item_id - The parent leaf for the object * @arg $title - The leaf title in the caseo a leaf * @arg $local_graph_id - The graph id in the case of a graph * @arg $host_id - The host id in the case of a graph * @arg $host_grouping_type - The sort order for the host under expanded hosts * @arg $sort_children - The sort type in the case of a leaf * @arg $propagate_changes - Wether the changes should be cascaded through all children * @returns - boolean true or false depending on the outcome of the operation */ function api_tree_item_save($id, $tree_id, $type, $parent_tree_item_id, $title, $local_graph_id, $host_id, $host_grouping_type, $sort_children_type, $propagate_changes) { global $config; input_validate_input_number($tree_id); input_validate_input_number($parent_tree_item_id); //api_tree_get_lock('tree-lock', 10); if ($local_graph_id > 0) { $exists = db_fetch_cell_prepared('SELECT id FROM graph_tree_items WHERE local_graph_id = ? AND parent = ? AND graph_tree_id = ?', array($local_graph_id, $parent_tree_item_id, $tree_id)); if ($exists) { return false; } } elseif ($host_id > 0) { $exists = db_fetch_cell_prepared('SELECT id FROM graph_tree_items WHERE host_id = ? AND parent = ? AND graph_tree_id = ?', array($host_id, $parent_tree_item_id, $tree_id)); if ($exists) { return false; } } $save['id'] = $id; $save['graph_tree_id'] = $tree_id; $save['title'] = form_input_validate($title, 'title', '', ($type == TREE_ITEM_TYPE_HEADER ? false : true), 3); $save['parent'] = $parent_tree_item_id; $save['local_graph_id'] = form_input_validate($local_graph_id, 'local_graph_id', '', true, 3); $save['host_id'] = form_input_validate($host_id, 'host_id', '', true, 3); $save['host_grouping_type'] = form_input_validate($host_grouping_type, 'host_grouping_type', '', true, 3); $save['sort_children_type'] = form_input_validate($sort_children_type, 'sort_children_type', '', true, 3); $tree_item_id = 0; if (!is_error_message()) { $tree_item_id = sql_save($save, 'graph_tree_items'); if ($tree_item_id) { raise_message(1); api_tree_sort_branch($tree_item_id, $tree_id); } else { raise_message(2); } } //api_tree_release_lock('tree-lock'); return $tree_item_id; } /* api_tree_get_item_type - gets the type of tree item @arg $tree_item_id - the id of the tree item to fetch the type for @returns - a string reprenting the type of the tree item. valid return values are 'header', 'graph', and 'host' */ function api_tree_get_item_type($tree_item_id) { $tree_item = db_fetch_row_prepared('SELECT title,local_graph_id,host_id FROM graph_tree_items WHERE id = ?', array($tree_item_id)); if (!sizeof($tree_item)) { return ''; } elseif ($tree_item['local_graph_id'] > 0) { return 'graph'; } elseif ($tree_item['title'] != '') { return 'header'; } elseif ($tree_item['host_id'] > 0) { return 'host'; } return ''; } /* naturally_sort_graphs - deprecated - callback to naturally sort an array * This function is used to sort graphs and trees * @arg $a - first graph array to compare * @arg $b - second graph array to compare * @returns - the re-ordered arrays */ function naturally_sort_graphs($a, $b) { return strnatcasecmp($a['title_cache'], $b['title_cache']); } /* api_tree_get_branch_ordering - determine the ordering of any elements owning leaf * This function is to assist with ordering tree items * @arg $leaf_id - the leaf_id of the element * @returns - the ordering of the parent leaf/branch */ function api_tree_get_branch_ordering($leaf_id) { $leaf = db_fetch_row_prepared('SELECT sort_children_type, parent, graph_tree_id FROM graph_tree_items WHERE id = ?', array($leaf_id)); if (sizeof($leaf)) { if ($leaf['sort_children_type'] == 0) { $parent = $leaf['parent']; if ($parent > 0) { return api_tree_get_branch_ordering($parent); } else { return db_fetch_cell_prepared('SELECT sort_type FROM graph_tree WHERE id = ?', array($leaf['graph_tree_id'])); } } else { return $leaf['sort_children_type']; } } else { return 1; } } /* api_tree_get_branch_name - determine the name of a branch leaf * This function is to assist with editing trees * @arg $tree_id - the tree id * @arg $leaf_id - the leaf id * @returns - the name of the leaf */ function api_tree_get_branch_name($tree_id, $leaf_id) { return db_fetch_cell_prepared('SELECT title FROM graph_tree_items WHERE graph_tree_id = ? AND id = ?', array($tree_id, $leaf_id)); } /* api_tree_get_branch_id - given a tree, parent, and title return the leaf_id * @arg $tree_id - the tree id * @arg $parent - the parent leaf id * @arg $title - the branch/leaf title * @returns - the name of the leaf */ function api_tree_get_branch_id($tree_id, $parent, $title) { return db_fetch_cell_prepared('SELECT id FROM graph_tree_items WHERE graph_tree_id = ? AND parent = ? AND title = ?', array($tree_id, $parent, $title)); } /* api_tree_sort_branch - sorts a branch based upon sorting rules. * Trees always go first, then hosts, and finally, graphs. * @arg $leaf_id - the leaf id * @arg $tree_id - the tree id * @returns - the name of the leaf */ function api_tree_sort_branch($leaf_id, $tree_id = 0, $lock = true) { static $level = 1; if ($lock) { //api_tree_get_lock('tree-lock', 10); } // Sorting will go in this order for anyone sorting: // Tree Branches go first, then Devices, then Graphs $sequence = 1; if (!is_numeric($leaf_id)) { $data = api_tree_parse_node_data($leaf_id); $leaf_id = $data['leaf_id']; } if ($leaf_id > 0) { $pdata = db_fetch_row_prepared('SELECT parent, graph_tree_id FROM graph_tree_items WHERE id = ?', array($leaf_id)); $parent = $pdata['parent']; $tree_id = $pdata['graph_tree_id']; } elseif ($tree_id > 0) { $parent = 0; } else { cacti_log('Error Sorting Tree'); return; } if ($parent > 0) { $sort_style = api_tree_get_branch_ordering($parent); } else { $sort_style = db_fetch_cell_prepared('SELECT sort_type FROM graph_tree WHERE id = ?', array($tree_id)); } if ($sort_style == TREE_ORDERING_ALPHABETIC) { $order_by = 'ORDER BY title'; } else { $order_by = 'ORDER BY position'; } $sort_array = array_rekey(db_fetch_assoc_prepared('SELECT id, title FROM graph_tree_items AS gti WHERE parent = ? AND graph_tree_id = ? AND local_graph_id = 0 AND host_id = 0 ' . $order_by, array($parent, $tree_id)), 'id', 'title'); if (sizeof($sort_array)) { if ($sort_style == TREE_ORDERING_NUMERIC) { asort($sort_array, SORT_NUMERIC); } elseif ($sort_style == TREE_ORDERING_ALPHABETIC) { // Let's let the database do it! } elseif ($sort_style == TREE_ORDERING_NATURAL) { if (defined('SORT_FLAG_CASE')) { asort($sort_array, SORT_NATURAL | SORT_FLAG_CASE); } else { natcasesort($sort_array); } } foreach($sort_array as $id => $element) { $sort = db_fetch_cell_prepared('SELECT sort_children_type FROM graph_tree_items WHERE id = ?', array($id)); if ($sort == TREE_ORDERING_INHERIT) { $first_child = db_fetch_cell_prepared('SELECT id FROM graph_tree_items WHERE parent = ? ORDER BY position LIMIT 1', array($id)); if (!empty($first_child)) { $level++; api_tree_sort_branch($first_child, $tree_id, false); } } db_execute_prepared('UPDATE graph_tree_items SET position = ? WHERE id = ?', array($sequence, $id)); $sequence++; } } if ($sort_style == TREE_ORDERING_ALPHABETIC) { $order_by = 'ORDER BY h.description'; } else { $order_by = 'ORDER BY position'; } $sort_array = array_rekey(db_fetch_assoc_prepared('SELECT h.description, gti.id FROM graph_tree_items AS gti INNER JOIN host AS h ON h.id=gti.host_id WHERE parent = ? AND graph_tree_id = ? AND host_id > 0 ' . $order_by, array($parent, $tree_id)), 'id', 'description'); if (sizeof($sort_array)) { if ($sort_style == TREE_ORDERING_NUMERIC) { asort($sort_array, SORT_NUMERIC); } elseif ($sort_style == TREE_ORDERING_ALPHABETIC) { // Let's let the database do it! } elseif ($sort_style == TREE_ORDERING_NATURAL) { if (defined('SORT_FLAG_CASE')) { asort($sort_array, SORT_NATURAL | SORT_FLAG_CASE); } else { natcasesort($sort_array); } } foreach($sort_array as $id => $element) { db_execute_prepared('UPDATE graph_tree_items SET position = ? WHERE id = ?', array($sequence, $id)); $sequence++; } } if ($sort_style == TREE_ORDERING_ALPHABETIC) { $order_by = 'ORDER BY gtg.title_cache'; } else { $order_by = 'ORDER BY position'; } $sort_array = array_rekey(db_fetch_assoc_prepared('SELECT gtg.title_cache, gti.id FROM graph_tree_items AS gti INNER JOIN graph_templates_graph AS gtg ON gtg.local_graph_id=gti.local_graph_id WHERE parent = ? AND graph_tree_id = ? AND gti.local_graph_id > 0 ' . $order_by, array($parent, $tree_id)), 'id', 'title_cache'); if (sizeof($sort_array)) { if ($sort_style == TREE_ORDERING_NUMERIC) { asort($sort_array, SORT_NUMERIC); } elseif ($sort_style == TREE_ORDERING_ALPHABETIC) { // Let's let the database do it! } elseif ($sort_style == TREE_ORDERING_NATURAL) { if (defined('SORT_FLAG_CASE')) { asort($sort_array, SORT_NATURAL | SORT_FLAG_CASE); } else { natcasesort($sort_array); } } foreach($sort_array as $id => $element) { db_execute_prepared('UPDATE graph_tree_items SET position = ? WHERE id = ?', array($sequence, $id)); $sequence++; } } if ($lock) { //api_tree_release_lock('tree-lock'); } }