6) { return false; } return $value; } /** * Validates a graph page size against the configured selector values. * * @param mixed $value The requested page size. * * @return int|false The validated page size, or false when it is unsupported. */ function html_graph_validate_page_size(mixed $value) : int|false { global $item_rows; $value = filter_var($value, FILTER_VALIDATE_INT); if ($value === false || !array_key_exists($value, $item_rows)) { return false; } return $value; } /** * Sets the default graph action based on user settings and permissions. * * This function checks if a request variable 'action' is set. If not, it sets up a default action * based on the user's settings and permissions. The function prioritizes the following actions: * 'tree', 'list', and 'preview', in that order. If none of these actions are allowed it attempts * to find the first action that the user has permission to. If it can not find one of these * the user is actually in an area that they do not have permission to, so we raise a message. * * The function leverages the session sess_graph_view_action to remember the last page that * the user visited. There are only three good values here: tree, preview, and list. * * @return void */ function set_default_graph_action() : void { // go through the settings and create a default $modes = [ 'tree' => ['permission' => 'show_tree', 'id' => '1'], 'preview' => ['permission' => 'show_preview', 'id' => '3'], 'list' => ['permission' => 'show_list', 'id' => '2'], ]; if (isrv('action')) { $action = gnrv('action'); } else { $action = ''; } if ($action == '') { // setup the default action if (!isset($_SESSION['sess_graph_view_action'])) { $user_setting = read_user_setting('default_view_mode'); $good_mode = ''; // check the defaults foreach ($modes as $action => $info) { if (is_view_allowed($info['permission']) && $user_setting == $info['id']) { $good_mode = $action; srv('action', $action); $_SESSION['sess_graph_view_action'] = $good_mode; break; } } if ($good_mode == '') { foreach ($modes as $action => $info) { if (is_view_allowed($info['permission'])) { $good_mode = $action; srv('action', $action); $_SESSION['sess_graph_view_action'] = $good_mode; break; } } } if ($good_mode == '') { raise_message('no_mode', __('Your User account does not have access to any Graph data'), MESSAGE_LEVEL_ERROR); } } elseif (in_array($_SESSION['sess_graph_view_action'], array_keys($modes), true) && is_view_allowed('show_' . $_SESSION['sess_graph_view_action'])) { srv('action', $_SESSION['sess_graph_view_action']); } else { unset($_SESSION['sess_graph_view_action']); foreach ($modes as $fallback_action => $info) { if (is_view_allowed($info['permission'])) { srv('action', $fallback_action); $_SESSION['sess_graph_view_action'] = $fallback_action; break; } } if (!isset($_SESSION['sess_graph_view_action'])) { raise_message('no_mode', __('Your User account does not have access to any Graph data'), MESSAGE_LEVEL_ERROR); } } } elseif (in_array($action, ['get_node', 'tree_content'], true)) { $_SESSION['sess_graph_view_action'] = 'tree'; } elseif (in_array($action, array_keys($modes), true)) { if (is_view_allowed('show_' . $action)) { $_SESSION['sess_graph_view_action'] = $action; } } } function create_graphs_preview_filter(string $session_var) : array { global $item_rows; $all = ['-1' => __('All')]; $any = ['-1' => __('Any')]; $none = ['0' => __('None')]; $sites = array_rekey( db_fetch_assoc('SELECT id, name FROM sites ORDER BY name'), 'id', 'name' ); $sites = $any + $sites; $locations = array_rekey( db_fetch_assoc('SELECT DISTINCT location FROM host ORDER BY location'), 'location', 'location' ); $locations = $any + $none + $locations; // unset the ordering if we have a setup that does not support ordering if (isrv('graph_template_id')) { if (str_contains(gnrv('graph_template_id'), ',') || gnrv('graph_template_id') <= 0) { srv('graph_order', ''); srv('graph_source', ''); } } /* The filter array below is what declares host_id, so nothing has validated * it at this point and get_request_var() would return $_REQUEST untouched. * The value reaches an interpolated SQL fragment further down, and '> 0' * does not gate it: PHP compares a non-numeric string against an int as a * string, so '1 AND ...' passes. Filter it here, at the read. */ if (isrv('host_id')) { $host_id = gfrv('host_id'); } elseif (isset($_SESSION[$session_var . '_host_id'])) { $host_id = $_SESSION[$session_var . '_host_id']; } else { $host_id = '-1'; } if ($host_id > 0) { $hostname = db_fetch_cell_prepared('SELECT description FROM host WHERE id = ?', [$host_id]); } elseif ($host_id == '') { $host_id = '-1'; $hostname = __('Any'); } elseif ($host_id == 0) { $host_id = '0'; $hostname = __('None'); } else { $host_id = '-1'; $hostname = __('Any'); } if ($host_id == 0) { $templates = get_allowed_graph_templates_normalized('gl.host_id=0', 'name', '', $total_rows); } elseif ($host_id > 0) { $templates = get_allowed_graph_templates_normalized('gl.host_id=' . (int) $host_id, 'name', '', $total_rows); } else { $templates = get_allowed_graph_templates_normalized('', 'name', '', $total_rows); } $normalized_templates = []; if (cacti_sizeof($templates)) { foreach ($templates as $t) { $normalized_templates[$t['id']] = $t['name']; } } $normalized_templates = $all + $none + $normalized_templates; $columns = [ '1' => __('%d Column', 1), '2' => __('%d Columns', 2), '3' => __('%d Columns', 3), '4' => __('%d Columns', 4), '5' => __('%d Columns', 5), '6' => __('%d Columns', 6) ]; $column_setting = html_graph_validate_columns(read_user_setting('num_columns', '2')); if ($column_setting === false) { $column_setting = 2; } $metrics_array = html_graph_order_filter_array(); if (isrv('business_hours')) { $business_hours = gnrv('business_hours'); } else { $business_hours = read_user_setting('show_business_hours') == 'on' ? 'true' : 'false'; } if (isrv('thumbnails')) { $thumbnails = gnrv('thumbnails'); } else { $thumbnails = read_user_setting('thumbnail_section_preview') == 'on' ? 'true' : 'false'; } $filters = [ 'rows' => [ [ 'site_id' => [ 'method' => 'drop_array', 'friendly_name' => __('Site'), 'filter' => FILTER_VALIDATE_INT, 'default' => '-1', 'pageset' => true, 'array' => $sites, 'value' => '-1' ], 'location' => [ 'method' => 'drop_array', 'friendly_name' => __('Location'), 'filter' => FILTER_CALLBACK, 'filter_options' => ['options' => 'sanitize_search_string'], 'default' => '-1', 'pageset' => true, 'array' => $locations, 'value' => '-1' ], 'host_id' => [ 'method' => 'drop_callback', 'friendly_name' => __('Device'), 'filter' => FILTER_VALIDATE_INT, 'default' => '-1', 'class' => 'select2-callback', 'pageset' => true, 'request_vars' => 'location,site_id,graph_template_id', 'sql' => 'SELECT DISTINCT id, description AS name FROM host ORDER BY description', 'action' => 'ajax_hosts', 'id' => $host_id, 'value' => $hostname, 'on_change' => 'applyGraphFilter()' ], ], [ 'graph_template_id' => [ 'method' => 'drop_multi', 'bar' => true, 'friendly_name' => __('Template'), 'filter' => FILTER_VALIDATE_REGEXP, 'filter_options' => ['options' => ['regexp' => '/^(cg_[0-9]+|dq_[0-9]+|-?[0-9]+)(,(cg_[0-9]+|dq_[0-9]+|-?[0-9]+))*$/']], 'default' => '-1', 'dynamic' => false, 'class' => 'select2-multi-count', 'select_all_text' => __('All Graph Templates'), 'select_count_text' => __('Templates Selected'), 'select_all_value' => '-1', 'pageset' => true, 'array' => $normalized_templates, 'value' => gnrv('graph_template_id') ], ], [ 'graphs' => [ 'method' => 'drop_array', 'friendly_name' => __('Graphs'), 'filter' => FILTER_CALLBACK, 'filter_options' => ['options' => 'html_graph_validate_page_size'], 'default' => '-1', 'pageset' => true, 'array' => $item_rows, 'value' => '' ], 'columns' => [ 'method' => 'drop_array', 'friendly_name' => __('Columns'), 'filter' => FILTER_CALLBACK, 'filter_options' => ['options' => 'html_graph_validate_columns'], 'default' => $column_setting, 'pageset' => true, 'array' => $columns, 'value' => $column_setting ], 'thumbnails' => [ 'method' => 'filter_checkbox', 'friendly_name' => __('Thumbnails'), 'filter' => FILTER_VALIDATE_REGEXP, 'filter_options' => ['options' => ['regexp' => '/^(true|false)$/']], 'default' => read_user_setting('thumbnail_section_preview') == 'on' ? 'true' : 'false', 'value' => $thumbnails ], 'business_hours' => [ 'method' => 'filter_checkbox', 'friendly_name' => __('Business Hours'), 'filter' => FILTER_VALIDATE_REGEXP, 'filter_options' => ['options' => ['regexp' => '/^(true|false)$/']], 'default' => read_user_setting('show_business_hours') == 'on' ? 'true' : 'false', 'value' => $business_hours ] ], [ 'rfilter' => [ 'method' => 'textbox', 'friendly_name' => __('Search'), 'filter' => FILTER_VALIDATE_IS_REGEX, 'placeholder' => __('Enter a search term'), 'size' => '55', 'default' => '', 'pageset' => true, 'max_length' => '120', 'value' => '' ] ], [ 'timespan' => [ 'method' => 'timespan', 'refresh' => true, 'clear' => true, 'shifter' => true, 'default' => read_user_setting('default_timespan') ], 'graph_list' => [ 'method' => 'validate', 'filter' => FILTER_VALIDATE_IS_NUMERIC_LIST, 'default' => '' ], 'graph_add' => [ 'method' => 'validate', 'filter' => FILTER_VALIDATE_IS_NUMERIC_LIST, 'default' => '' ], 'graph_remove' => [ 'method' => 'validate', 'filter' => FILTER_VALIDATE_IS_NUMERIC_LIST, 'default' => '' ], 'style' => [ 'method' => 'validate', 'filter' => FILTER_DEFAULT, 'default' => '' ] ] ], 'buttons' => [ 'go' => [ 'method' => 'submit', 'display' => __('Go'), 'title' => __('Apply filter to table'), 'callback' => 'applyGraphFilter()' ], 'clear' => [ 'method' => 'button', 'display' => __('Clear'), 'title' => __('Reset filter to default values'), 'callback' => 'clearGraphFilter()' ] ] ]; if (cacti_sizeof($metrics_array)) { $filters['rows'][1] += $metrics_array; } if (is_view_allowed('graph_settings')) { $filters['buttons']['save'] = [ 'method' => 'button', 'display' => __('Save'), 'title' => __('Save filter to the database'), 'callback' => 'saveGraphFilter("preview")' ]; } return $filters; } function draw_graphs_preview_filter(bool $render = false, string $page = '', string $action = 'get') : void { $header = __('Graph Preview Filters') . (isrv('style') && grv('style') != '' ? ' ' . __('[ Custom Graph List Applied - Filtering from List ]') : ''); // create the page filter $filters = create_graphs_preview_filter('sess_pview'); $pageFilter = new CactiTableFilter($header, $page, 'form_graph_view', 'sess_pview', '', false, false); $pageFilter->rows_label = __('Graphs'); $pageFilter->form_method = $action; $pageFilter->set_filter_array($filters); $pageFilter->inject_content = inject_realtime_form(); if ($render) { $pageFilter->render(); } else { $pageFilter->sanitize(); } } function inject_realtime_form() : string { global $graphs_per_page, $realtime_window, $realtime_refresh, $graph_timeshifts, $graph_timespans; $content = "
"; return $content; } /** * Generates the HTML for the graph preview filter form. * * This function creates a form that allows users to filter and preview graphs based on various criteria such as site, location, host, template, and time span. * * @param string $page The current page URL. * @param string $action The action to be performed on form submission. * @param string $devices_where SQL condition for filtering devices (optional). * @param string $templates_where SQL condition for filtering templates (optional). * * @global array $graphs_per_page Array of graphs per page options. * @global array $realtime_window Array of real-time window options. * @global array $realtime_refresh Array of real-time refresh interval options. * @global array $graph_timeshifts Array of graph time shift options. * @global array $graph_timespans Array of graph time span options. * * @return void */ function html_graph_preview_filter(string $page, string $action, string $devices_where = '', string $templates_where = '') : void { global $graphs_per_page, $realtime_window, $realtime_refresh, $graph_timeshifts, $graph_timespans; initialize_realtime_step_and_window(); draw_graphs_preview_filter(true, $page, $action); ?> $form_array) { foreach ($form_array as $form_id1 => $form_array2) { ob_start(); $count = html_graph_custom_data($host_id, $host_template_id, $snmp_query_id, $form_type, $form_id1, $form_array2); $output = (string) ob_get_clean(); if (array_sum($count)) { $output_sections[] = $output; } } } // no fields were actually drawn on the form; just save without prompting the user if (!cacti_sizeof($output_sections)) { /* since the user didn't actually click "Create" to POST the data; we have to pretend like they did here */ srv('save_component_new_graphs', '1'); srv('selected_graphs_array', serialize($selected_graphs_array)); host_new_graphs_save($host_id); header('Location: ' . $page . '?host_id=' . $host_id); exit; } top_header(); form_start('graphs_new.php', 'new_graphs'); print implode('', $output_sections); form_hidden_box('host_template_id', $host_template_id, '0'); form_hidden_box('host_id', $host_id, '0'); form_hidden_box('save_component_new_graphs', '1', ''); form_hidden_box('selected_graphs_array', serialize($selected_graphs_array), ''); if (isset($_SERVER['HTTP_REFERER']) && !str_contains($_SERVER['HTTP_REFERER'], 'graphs_new')) { srv('returnto', basename($_SERVER['HTTP_REFERER'])); } load_current_session_value('returnto', 'sess_grn_returnto', ''); form_save_button(gnrv('returnto')); bottom_footer(); } /** * Generates custom HTML form data for graph creation based on the provided parameters. * * @param int $host_id The ID of the host. * @param int $host_template_id The ID of the host template. * @param int $snmp_query_id The ID of the SNMP query. * @param string $form_type The type of form ('cg' for graph template, 'sg' for SNMP query). * @param string $form_id1 The ID of the form element. * @param array $form_array2 An array of form elements. * * @return array An array of output fields for the form. */ function html_graph_custom_data(int $host_id, int $host_template_id, int $snmp_query_id, string $form_type, string $form_id1, array $form_array2) : array { // ================= input validation ================= input_validate_input_number($form_id1, 'form_id1'); // ==================================================== $num_output_fields = []; if ($form_type == 'cg') { $graph_template_id = intval($form_id1); $graph_template_name = db_fetch_cell_prepared('SELECT name FROM graph_templates WHERE id = ?', [$graph_template_id]); if (!graph_template_has_override($graph_template_id)) { return []; } return html_graph_custom_data_template( $graph_template_id, $snmp_query_id, 0, __('Create Graph from %s', htmle($graph_template_name)) ); } if ($form_type == 'sg') { foreach ($form_array2 as $form_id2 => $form_array3) { // ================= input validation ================= input_validate_input_number($form_id2, 'form_id2'); // ==================================================== $snmp_query_id = $form_id1; $snmp_query_graph_id = $form_id2; $num_graphs = cacti_sizeof($form_array3); $query_graph = db_fetch_row_prepared('SELECT sq.name, sqg.graph_template_id FROM snmp_query AS sq INNER JOIN snmp_query_graph AS sqg ON sqg.snmp_query_id = sq.id WHERE sq.id = ? AND sqg.id = ?', [$snmp_query_id, $snmp_query_graph_id]); if (!cacti_sizeof($query_graph)) { raise_message( 'invalid_snmp_query_graph_' . $snmp_query_graph_id, __('The selected Data Query Graph does not belong to the selected Data Query.'), MESSAGE_LEVEL_ERROR ); continue; } $graph_template_id = (int) $query_graph['graph_template_id']; if (!graph_template_has_override($graph_template_id)) { continue; } if ($num_graphs > 1) { $header = __('Create %s Graphs from %s', $num_graphs, htmle($query_graph['name'])); } else { $header = __('Create Graph from %s', htmle($query_graph['name'])); } $num_output_fields = array_merge( $num_output_fields, html_graph_custom_data_template($graph_template_id, (int) $snmp_query_id, (int) $snmp_query_graph_id, $header) ); } } return $num_output_fields; } /** * Draws override fields for one graph template. * * @param int $graph_template_id The graph template being rendered. * @param int $snmp_query_id The associated SNMP query, or zero. * @param int $snmp_query_graph_id The associated SNMP query graph, or zero. * @param string $header The form section heading. * * @return array The number of fields emitted by each field renderer. */ function html_graph_custom_data_template(int $graph_template_id, int $snmp_query_id, int $snmp_query_graph_id, string $header) : array { $num_output_fields = []; html_start_box($header, '100%', false, 3, 'center', ''); // ================= input validation ================= input_validate_input_number($graph_template_id, 'graph_template_id'); // ==================================================== $data_templates = db_fetch_assoc_prepared('SELECT data_template.name AS data_template_name, data_template_rrd.data_source_name, data_template_data.* FROM (data_template, data_template_rrd, data_template_data, graph_templates_item) WHERE graph_templates_item.task_item_id = data_template_rrd.id AND data_template_rrd.data_template_id = data_template.id AND data_template_data.data_template_id = data_template.id AND data_template_rrd.local_data_id = 0 AND data_template_data.local_data_id = 0 AND graph_templates_item.local_graph_id = 0 AND graph_templates_item.graph_template_id = ? GROUP BY data_template.id ORDER BY data_template.name', [$graph_template_id]); $graph_template = db_fetch_row_prepared('SELECT gt.name AS graph_template_name, gtg.* FROM graph_templates AS gt INNER JOIN graph_templates_graph AS gtg ON gt.id = gtg.graph_template_id WHERE gt.id = ? AND gtg.local_graph_id = 0', [$graph_template_id]); array_push($num_output_fields, draw_nontemplated_fields_graph($graph_template_id, $graph_template, "g_$snmp_query_id" . '_' . $graph_template_id . '_|field|', __('Graph [Template: %s]', htmle($graph_template['graph_template_name'])), true, false, $snmp_query_graph_id)); array_push($num_output_fields, draw_nontemplated_fields_graph_item($graph_template_id, 0, 'gi_' . $snmp_query_id . '_' . $graph_template_id . '_|id|_|field|', __('Graph Items [Template: %s]', htmle($graph_template['graph_template_name'])), true)); // DRAW: Data Sources if (cacti_sizeof($data_templates)) { foreach ($data_templates as $data_template) { array_push($num_output_fields, draw_nontemplated_fields_data_source($data_template['data_template_id'], 0, $data_template, 'd_' . $snmp_query_id . '_' . $graph_template_id . '_' . $data_template['data_template_id'] . '_|field|', __('Data Source [Template: %s]', htmle($data_template['data_template_name'])), true, false, $snmp_query_graph_id)); $data_template_items = db_fetch_assoc_prepared('SELECT data_template_rrd.* FROM data_template_rrd WHERE data_template_rrd.data_template_id = ? AND local_data_id = 0', [$data_template['data_template_id']]); array_push($num_output_fields, draw_nontemplated_fields_data_source_item($data_template['data_template_id'], $data_template_items, 'di_' . $snmp_query_id . '_' . $graph_template_id . '_' . $data_template['data_template_id'] . '_|id|_|field|', '', true, false, false, $snmp_query_graph_id)); array_push($num_output_fields, draw_nontemplated_fields_custom_data($data_template['id'], 'c_' . $snmp_query_id . '_' . $graph_template_id . '_' . $data_template['data_template_id'] . '_|id|', __('Custom Data [Template: %s]', htmle($data_template['data_template_name'])), true, false, $snmp_query_id)); } } html_end_box(false); return $num_output_fields; } function html_save_graph_settings() : void { if (is_view_allowed('graph_settings')) { gfrv('columns', FILTER_CALLBACK, ['options' => 'html_graph_validate_columns']); gfrv('predefined_timespan'); gfrv('predefined_timeshift'); gfrv('graphs', FILTER_CALLBACK, ['options' => 'html_graph_validate_page_size']); gfrv('thumbnails', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^(true|false)$/']]); gfrv('business_hours', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^(true|false)$/']]); if (isrv('predefined_timespan')) { set_user_setting('default_timespan', grv('predefined_timespan')); } if (isrv('predefined_timeshift')) { set_user_setting('default_timeshift', grv('predefined_timeshift')); } if (isrv('business_hours')) { set_user_setting('show_business_hours', grv('business_hours') == 'true' ? 'on' : ''); } if (isrv('section') && gnrv('section') == 'preview') { if (isrv('columns')) { set_user_setting('num_columns', grv('columns')); } if (isrv('graphs')) { if (grv('graphs') != '-1') { set_user_setting('preview_graphs_per_page', grv('graphs')); } } if (isrv('thumbnails')) { set_user_setting('thumbnail_section_preview', gnrv('thumbnails') == 'true' ? 'on' : ''); } } else { if (isrv('columns')) { set_user_setting('num_columns_tree', grv('columns')); } if (isrv('graphs')) { if (grv('graphs') != '-1') { set_user_setting('treeview_graphs_per_page', grv('graphs')); } } if (isrv('thumbnails')) { set_user_setting('thumbnail_section_tree', grv('thumbnails') == 'true' ? 'on' : ''); } } } } function html_graph_preview_view() : void { global $is_request_ajax; if (!is_view_allowed('show_preview')) { header('Location: permission_denied.php'); exit; } if (isrv('external_id')) { $host_id = db_fetch_cell_prepared('SELECT id FROM host WHERE external_id = ?', [gnrv('external_id')]); if (!empty($host_id)) { srv('host_id', $host_id); srv('reset',true); } } top_graph_header(); html_graph_preview_filter('graph_view.php', 'preview'); api_plugin_hook_function('graph_tree_page_buttons', [ 'mode' => 'preview', 'timespan' => $_SESSION['sess_current_timespan'], 'starttime' => get_current_graph_start(), 'endtime' => get_current_graph_end() ] ); // the user select a bunch of graphs of the 'list' view and wants them displayed here $sql_or = ''; if (isrv('style')) { if (grv('style') == 'selective') { $graph_list = []; // process selected graphs if (!ierv('graph_list')) { foreach (explode(',', grv('graph_list')) as $item) { if (is_numeric($item)) { $graph_list[$item] = 1; } } } if (!ierv('graph_add')) { foreach (explode(',', grv('graph_add')) as $item) { if (is_numeric($item)) { $graph_list[$item] = 1; } } } // remove items if (!ierv('graph_remove')) { foreach (explode(',', grv('graph_remove')) as $item) { unset($graph_list[$item]); } } $i = 0; foreach ($graph_list as $item => $value) { $graph_array[$i] = $item; $i++; } if ((isset($graph_array)) && (cacti_sizeof($graph_array) > 0)) { // build sql string including each graph the user checked $sql_or = array_to_sql_or($graph_array, 'gtg.local_graph_id'); } } } $total_graphs = 0; // create filter for sql $sql_where = ''; if (!ierv('rfilter')) { $sql_where .= ' (gtg.title_cache RLIKE ' . db_qstr(grv('rfilter')); if (ctype_digit(grv('rfilter'))) { $sql_where .= ' OR gl.id = ' . (int) grv('rfilter'); } $sql_where .= ')'; } $sql_where .= ($sql_or != '' && $sql_where != '' ? ' AND ' : '') . $sql_or; if (!ierv('site_id') && grv('site_id') > 0) { $sql_where .= ($sql_where == '' ? '' : ' AND') . ' h.site_id=' . grv('site_id'); } elseif (ierv('site_id')) { $sql_where .= ($sql_where == '' ? '' : ' AND') . ' h.site_id=0'; } if (!ierv('host_id') && grv('host_id') > 0) { $sql_where .= ($sql_where == '' ? '' : ' AND') . ' gl.host_id=' . gfrv('host_id'); } elseif (ierv('host_id')) { $sql_where .= ($sql_where == '' ? '' : ' AND') . ' gl.host_id=0'; } if (grv('location') != '' && grv('location') != '-1' && grv('location') != '0') { $sql_where .= ($sql_where == '' ? '' : ' AND') . ' h.location = ' . db_qstr(grv('location')); } elseif (grv('location') == '0') { $sql_where .= ($sql_where == '' ? '' : ' AND') . ' h.location = ""'; } if (!ierv('graph_template_id') && grv('graph_template_id') != '-1' && grv('graph_template_id') != '0') { $graph_templates = html_transform_graph_template_ids(grv('graph_template_id')); $sql_where .= ($sql_where != '' ? ' AND ' : '') . ' ' . db_in_clause('gl.graph_template_id', $graph_templates); } elseif (grv('graph_template_id') == '0') { $sql_where .= ($sql_where != '' ? ' AND ' : '') . ' ' . db_in_clause('gl.graph_template_id', 0); } if (grv('graphs') == '-1') { $graph_rows = read_user_setting('preview_graphs_per_page', read_config_option('preview_graphs_per_page') ?? 20); } else { $graph_rows = grv('graphs'); } $graph_rows = html_graph_validate_page_size($graph_rows); if ($graph_rows === false || $graph_rows == -1) { $graph_rows = 20; } $sql_limit = ($graph_rows * (grv('page') - 1)) . ',' . $graph_rows; if (read_config_option('dsstats_enable') == 'on' && grv('graph_source') != '' && grv('graph_order') != '') { $sql_order = [ 'data_source' => grv('graph_source'), 'order' => grv('graph_order'), 'start_time' => get_current_graph_start(), 'end_time' => get_current_graph_end(), 'cf' => grv('cf'), 'measure' => grv('measure') ]; } else { $sql_order = 'gtg.title_cache'; } $graphs = get_allowed_graphs($sql_where, $sql_order, $sql_limit, $total_graphs); $nav = html_nav_bar('graph_view.php', MAX_DISPLAY_PAGES, grv('page'), $graph_rows, $total_graphs, grv('columns'), __('Graphs'), 'page', 'main'); print $nav; html_start_box('', '100%', false, 3, 'center', ''); if (grv('thumbnails') == 'true') { html_graph_thumbnail_area($graphs, '', 'graph_start=' . get_current_graph_start() . '&graph_end=' . get_current_graph_end(), '', grv('columns')); } else { html_graph_area($graphs, '', 'graph_start=' . get_current_graph_start() . '&graph_end=' . get_current_graph_end(), '', grv('columns')); } html_end_box(); if ($total_graphs) { print $nav; } if (!$is_request_ajax) { bottom_footer(); } } function create_listview_filter(string $session_var) : array { global $item_rows; $all = ['-1' => __('All')]; $any = ['-1' => __('Any')]; $none = ['0' => __('None')]; $sites = array_rekey( db_fetch_assoc('SELECT id, name FROM sites ORDER BY name'), 'id', 'name' ); $sites = $any + $sites; $locations = array_rekey( db_fetch_assoc('SELECT DISTINCT location FROM host ORDER BY location'), 'location', 'location' ); $locations = $any + $none + $locations; /* The filter array below is what declares host_id, so nothing has validated * it at this point and get_request_var() would return $_REQUEST untouched. * The value reaches an interpolated SQL fragment further down, and '> 0' * does not gate it: PHP compares a non-numeric string against an int as a * string, so '1 AND ...' passes. Filter it here, at the read. */ if (isrv('host_id')) { $host_id = gfrv('host_id'); } elseif (isset($_SESSION[$session_var . '_host_id'])) { $host_id = $_SESSION[$session_var . '_host_id']; } else { $host_id = '-1'; } if ($host_id > 0) { $hostname = db_fetch_cell_prepared('SELECT description FROM host WHERE id = ?', [$host_id]); } elseif ($host_id == '') { $host_id = '-1'; $hostname = __('Any'); } elseif ($host_id == 0) { $host_id = '0'; $hostname = __('None'); } else { $host_id = '-1'; $hostname = __('Any'); } if ($host_id == 0) { $templates = get_allowed_graph_templates_normalized('gl.host_id=0', 'name', '', $total_rows); } elseif ($host_id > 0) { $templates = get_allowed_graph_templates_normalized('gl.host_id=' . (int) $host_id, 'name', '', $total_rows); } else { $templates = get_allowed_graph_templates_normalized('', 'name', '', $total_rows); } $normalized_templates = []; if (cacti_sizeof($templates)) { foreach ($templates as $t) { $normalized_templates[$t['id']] = $t['name']; } } $normalized_templates = $all + $none + $normalized_templates; $filters = [ 'rows' => [ [ 'site_id' => [ 'method' => 'drop_array', 'friendly_name' => __('Site'), 'filter' => FILTER_VALIDATE_INT, 'default' => '-1', 'pageset' => true, 'array' => $sites, 'value' => '-1' ], 'location' => [ 'method' => 'drop_array', 'friendly_name' => __('Location'), 'filter' => FILTER_CALLBACK, 'filter_options' => ['options' => 'sanitize_search_string'], 'default' => '-1', 'pageset' => true, 'array' => $locations, 'value' => '-1' ], 'host_id' => [ 'method' => 'drop_callback', 'friendly_name' => __('Device'), 'filter' => FILTER_VALIDATE_INT, 'default' => '-1', 'class' => 'select2-callback', 'pageset' => true, 'request_vars' => 'location,site_id,graph_template_id', 'sql' => 'SELECT DISTINCT id, description AS name FROM host ORDER BY description', 'action' => 'ajax_hosts', 'id' => $host_id, 'value' => $hostname, 'on_change' => 'applyGraphFilter()' ] ], [ 'rfilter' => [ 'method' => 'textbox', 'friendly_name' => __('Search'), 'filter' => FILTER_VALIDATE_IS_REGEX, 'placeholder' => __('Enter a search term'), 'size' => '55', 'default' => '', 'pageset' => true, 'max_length' => '120', 'value' => '' ], 'graph_template_id' => [ 'method' => 'drop_multi', 'friendly_name' => __('Template'), 'filter' => FILTER_VALIDATE_REGEXP, 'filter_options' => ['options' => ['regexp' => '/^(cg_[0-9]+|dq_[0-9]+|-?[0-9]+)(,(cg_[0-9]+|dq_[0-9]+|-?[0-9]+))*$/']], 'default' => '-1', 'dynamic' => false, 'class' => 'select2-multi-count', 'select_all_text' => __('All Graph Templates'), 'select_count_text' => __('Templates Selected'), 'select_all_value' => '-1', 'pageset' => true, 'array' => $normalized_templates, 'value' => gnrv('graph_template_id') ], 'graphs' => [ 'method' => 'drop_array', 'friendly_name' => __('Graphs'), 'filter' => FILTER_CALLBACK, 'filter_options' => ['options' => 'html_graph_validate_page_size'], 'default' => '-1', 'pageset' => true, 'array' => $item_rows, 'value' => '' ], 'graph_list' => [ 'method' => 'validate', 'filter' => FILTER_VALIDATE_IS_NUMERIC_LIST, 'default' => '' ], 'graph_add' => [ 'method' => 'validate', 'filter' => FILTER_VALIDATE_IS_NUMERIC_LIST, 'default' => '' ], 'graph_remove' => [ 'method' => 'validate', 'filter' => FILTER_VALIDATE_IS_NUMERIC_LIST, 'default' => '' ], 'style' => [ 'method' => 'validate', 'filter' => FILTER_DEFAULT, 'default' => '' ] ] ], 'buttons' => [ 'go' => [ 'method' => 'submit', 'display' => __('Go'), 'title' => __('Apply filter to table'), ], 'clear' => [ 'method' => 'button', 'display' => __('Clear'), 'title' => __('Reset filter to default values'), ], 'view' => [ 'method' => 'button', 'display' => __('View'), 'title' => __('View the selected Graphs in Preview mode'), 'callback' => 'viewGraphs()' ] ] ]; $reports = db_fetch_assoc_prepared('SELECT * FROM reports WHERE user_id = ?', [$_SESSION[SESS_USER_ID]]); if (cacti_sizeof($reports)) { $filters['buttons']['report'] = [ 'method' => 'button', 'display' => __('Report'), 'title' => __('Place the selected Graphs on an existing Report'), 'callback' => 'addReport()' ]; } return $filters; } function draw_listview_filter(bool $render = false) : void { $header = __('Graph List View Filters') . (isrv('style') && grv('style') != '' ? ' ' . __('[ Custom Graph List Applied - Filtering from List ]') : ''); // create the page filter $filters = create_listview_filter('sess_lview'); $pageFilter = new CactiTableFilter($header, 'graph_view.php?action=list', 'form_graph_view', 'sess_lview'); $pageFilter->rows_label = __('Graphs'); $pageFilter->form_method = 'post'; $pageFilter->set_filter_array($filters); if ($render) { $pageFilter->render(); } else { $pageFilter->sanitize(); } } function html_graph_list_view() : void { global $graph_timespans, $alignment, $graph_sources, $item_rows; if (!is_view_allowed('show_list')) { header('Location: permission_denied.php'); exit; } // reset the graph list on a new viewing if (!isrv('page')) { srv('graph_list', ''); } top_graph_header(); draw_listview_filter(true); if (grv('graphs') == '-1') { $graph_rows = read_config_option('num_rows_table'); } else { $graph_rows = grv('graphs'); } $graph_rows = html_graph_validate_page_size($graph_rows); if ($graph_rows === false || $graph_rows == -1) { $graph_rows = 20; } // check to see if site_id and location are mismatched if (grv('site_id') >= 0) { if (grv('location') != '0' && grv('location') != '-1') { $exists = db_fetch_cell_prepared('SELECT COUNT(*) FROM host WHERE site_id = ? AND location = ?', [grv('site_id'), grv('location')]); if (!$exists) { srv('location', '-1'); } } } $graph_list = []; // save selected graphs into url if (!ierv('graph_list')) { foreach (explode(',', grv('graph_list')) as $item) { if (is_numeric($item)) { $graph_list[$item] = 1; } } } if (!ierv('graph_add')) { foreach (explode(',', grv('graph_add')) as $item) { if (is_numeric($item)) { $graph_list[$item] = 1; } } } // remove items if (!ierv('graph_remove')) { foreach (explode(',', grv('graph_remove')) as $item) { unset($graph_list[$item]); } } // update the revised graph list session variable if (cacti_sizeof($graph_list)) { srv('graph_list', implode(',', array_keys($graph_list))); } load_current_session_value('graph_list', 'sess_gl_graph_list', ''); $reports = db_fetch_assoc_prepared('SELECT * FROM reports WHERE user_id = ?', [$_SESSION[SESS_USER_ID]]); form_start('graph_view.php', 'chk'); form_hidden_box('style', 'selective', ''); form_hidden_box('action', 'list', ''); form_hidden_box('graph_add', '', ''); form_hidden_box('graph_remove', '', ''); form_hidden_box('graph_list', grv('graph_list'), ''); // create filter for sql $sql_where = ''; if (!ierv('rfilter')) { $sql_where .= ' (gtg.title_cache RLIKE ' . db_qstr(grv('rfilter')); if (ctype_digit(grv('rfilter'))) { $sql_where .= ' OR gl.id = ' . (int) grv('rfilter'); } $sql_where .= ')'; } if (!ierv('site_id') && grv('site_id') > 0) { $sql_where .= ($sql_where == '' ? '' : ' AND') . ' h.site_id=' . grv('site_id'); } elseif (ierv('site_id')) { $sql_where .= ($sql_where == '' ? '' : ' AND') . ' h.site_id=0'; } if (!ierv('host_id') && grv('host_id') > 0) { $sql_where .= ($sql_where == '' ? '' : ' AND') . ' gl.host_id=' . gfrv('host_id'); } elseif (ierv('host_id')) { $sql_where .= ($sql_where == '' ? '' : ' AND') . ' gl.host_id=0'; } if (grv('location') != '' && grv('location') != '-1' && grv('location') != '0') { $sql_where .= ($sql_where == '' ? '' : ' AND') . ' h.location = ' . db_qstr(grv('location')); } elseif (grv('location') == '0') { $sql_where .= ($sql_where == '' ? '' : ' AND') . ' h.location = ""'; } if (!ierv('graph_template_id') && grv('graph_template_id') != '-1' && grv('graph_template_id') != '0') { $graph_templates = html_transform_graph_template_ids(grv('graph_template_id')); $sql_where .= ($sql_where != '' ? ' AND ' : '') . ' ' . db_in_clause('gl.graph_template_id', $graph_templates); } elseif (grv('graph_template_id') == '0') { $sql_where .= ($sql_where != '' ? ' AND ' : '') . ' ' . db_in_clause('gl.graph_template_id', 0); } $total_rows = 0; $sql_limit = ($graph_rows * (grv('page') - 1)) . ',' . $graph_rows; $graphs = get_allowed_graphs($sql_where, 'gtg.title_cache', $sql_limit, $total_rows); $nav = html_nav_bar('graph_view.php?action=list', MAX_DISPLAY_PAGES, grv('page'), $graph_rows, $total_rows, 5, __('Graphs'), 'page', 'main'); print $nav; html_start_box('', '100%', false, 3, 'center', ''); if (is_realm_allowed(10)) { $display_text = [ 'title_cache' => [ 'display' => __('Graph Name'), 'align' => 'left', 'tip' => __('The Title of this Graph. Generally programmatically generated from the Graph Template definition or Suggested Naming rules. The max length of the Title is controlled under Settings->Visual.') ], 'site_name' => [ 'display' => __('Site Name'), 'align' => 'left', 'tip' => __('The Site Name for this Graph.') ], 'location' => [ 'display' => __('Site Location'), 'align' => 'left', 'tip' => __('The Site Location for this Graph.') ], 'local_graph_id' => [ 'display' => __('Device'), 'align' => 'left', 'tip' => __('The device for this Graph.') ], 'source' => [ 'display' => __('Source Type'), 'align' => 'right', 'tip' => __('The underlying source that this Graph was based upon.') ], 'name' => [ 'display' => __('Source Name'), 'align' => 'left', 'tip' => __('The Graph Template or Data Query that this Graph was based upon.') ], 'height' => [ 'display' => __('Size'), 'align' => 'left', 'tip' => __('The size of this Graph when not in Preview mode.') ] ]; } else { $display_text = [ 'title_cache' => [ 'display' => __('Graph Name'), 'align' => 'left', 'tip' => __('The Title of this Graph. Generally programmatically generated from the Graph Template definition or Suggested Naming rules. The max length of the Title is controlled under Settings->Visual.') ], 'height' => [ 'display' => __('Size'), 'align' => 'left', 'tip' => __('The size of this Graph when not in Preview mode.') ] ]; } html_header_checkbox($display_text, false); $i = 0; if (cacti_sizeof($graphs)) { foreach ($graphs as $graph) { // we're escaping strings here, so no need to escape them on form_selectable_cell $template_details = get_graph_template_details($graph['local_graph_id']); if ($graph['graph_source'] == '0') { // Not Templated, customize graph source and template details. $template_details = api_plugin_hook_function('customize_template_details', $template_details); $graph = api_plugin_hook_function('customize_graph', $graph); } if (isset($template_details['graph_name'])) { $graph['name'] = $template_details['graph_name']; } if (isset($template_details['graph_description'])) { $graph['description'] = $template_details['graph_description']; } $current_page = get_current_page(); form_alternate_row('line' . $graph['local_graph_id'], true); form_selectable_cell(filter_value($graph['title_cache'], grv('rfilter'), $current_page . '?action=view&local_graph_id=' . $graph['local_graph_id'] . '&rra_id=0'), $graph['local_graph_id']); if (is_realm_allowed(10)) { if ($graph['site_name'] != '') { form_selectable_ecell($graph['site_name'], $graph['local_graph_id']); } else { form_selectable_ecell('-', $graph['local_graph_id']); } if ($graph['location'] != '') { form_selectable_ecell($graph['location'], $graph['local_graph_id']); } else { form_selectable_ecell('-', $graph['local_graph_id']); } form_selectable_ecell($graph['description'], $graph['local_graph_id']); form_selectable_cell(filter_value($graph_sources[$template_details['source']], grv('rfilter')), $graph['local_graph_id'], '', 'right'); form_selectable_cell(filter_value($template_details['name'], grv('rfilter'), $template_details['url']), $graph['local_graph_id'], '', 'left'); } form_selectable_ecell($graph['height'] . 'x' . $graph['width'], $graph['local_graph_id']); form_checkbox_cell($graph['title_cache'], $graph['local_graph_id']); form_end_row(); } } html_end_box(false); if (cacti_sizeof($graphs)) { print $nav; } form_end(); $report_text = ''; if (cacti_sizeof($reports)) { $report_text = ''; } ?>
 
$_SESSION['sess_current_date1'], 'date2' => $_SESSION['sess_current_date2'], 'timestamp1' => $_SESSION['sess_current_timespan_begin_now'], 'timestamp2' => $_SESSION['sess_current_timespan_end_now'], ]; print json_encode($return); } } function html_graph_get_reports() : void { // Add to a report gfrv('report_id'); gfrv('timespan'); gfrv('align'); if (isrv('graph_list')) { $items = explode(',', grv('graph_list')); if (cacti_sizeof($items)) { $good = true; foreach ($items as $item) { if (!reports_add_graphs(gfrv('report_id'), intval($item), grv('timespan'), grv('align'))) { raise_message('reports_add_error'); $good = false; break; } } if ($good) { raise_message('reports_graphs_added'); } } } else { raise_message('reports_no_graph'); } header('Location: graph_view.php?action=list'); } function html_graph_single_validate() : void { // ================= input validation ================= gfrv('rra_id', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^([0-9]+|all)$/']]); gfrv('local_graph_id'); gfrv('graph_end'); gfrv('graph_start'); gfrv('view_type', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^([a-zA-Z0-9]+)$/']]); gfrv('business_hours', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^([a-zA-Z0-9]+)$/']]); // ==================================================== if (isrv('business_hours')) { $_SESSION['sess_business_hours'] = grv('business_hours'); } elseif (isset($_SESSION['sess_business_hours'])) { srv('business_hours', $_SESSION['sess_business_hours']); } if (!isrv('rra_id')) { srv('rra_id', 'all'); } } function html_graph_check_access() : void { $exists = db_fetch_cell_prepared('SELECT local_graph_id FROM graph_templates_graph WHERE local_graph_id = ?', [grv('local_graph_id')] ); // make sure the graph requested exists (sanity) if (!$exists) { print '' . __('GRAPH DOES NOT EXIST') . ''; bottom_footer(); exit; } // take graph permissions into account here if (!is_graph_allowed(grv('local_graph_id'))) { header('Location: permission_denied.php'); exit; } } function html_graph_get_info() : array { $rras = []; $graph_title = null; if (grv('rra_id') == 'all' || ierv('rra_id')) { $sql_where = ' AND dspr.id IS NOT NULL'; } else { $sql_where = ' AND dspr.id=' . grv('rra_id'); } $rras = get_associated_rras(grv('local_graph_id'), $sql_where); $graph_title = get_graph_title(grv('local_graph_id')); return ['rras' => $rras, 'title' => $graph_title]; } function html_graph_single_view() : void { html_graph_single_validate(); html_graph_check_access(); $info = html_graph_get_info(); $rras = $info['rras']; $graph_title = $info['title']; $current_page = get_current_page(); if ($current_page == 'graph.php') { top_header(); } elseif ($current_page == 'graphs.php') { top_header(); } elseif ($current_page == 'graph_view.php') { top_graph_header(); } else { general_header(); } if (str_contains(grv('action'), 'tree')) { $suffix = 'tree'; } else { $suffix = 'preview'; } print "
"; html_start_box(__esc('Graph Utility View for Graph: %s', $graph_title), '100%', true, 3, 'center', ''); api_plugin_hook_function( 'page_buttons', [ 'lgid' => grv('local_graph_id'), 'leafid' => '', // $leaf_id, 'mode' => 'mrtg', 'rraid' => grv('rra_id') ] ); $graph = db_fetch_row_prepared('SELECT gtg.local_graph_id, width, height, title_cache, gtg.graph_template_id, h.id AS host_id, h.disabled FROM graph_templates_graph AS gtg INNER JOIN graph_local AS gl ON gtg.local_graph_id = gl.id LEFT JOIN host AS h ON gl.host_id = h.id WHERE gtg.local_graph_id = ?', [grv('local_graph_id')]); $graph_template_id = $graph['graph_template_id']; $i = 0; if (cacti_sizeof($rras)) { $graph_end = time() - 30; print '
'; foreach ($rras as $rra) { if (!empty($rra['timespan'])) { $graph_start = $graph_end - $rra['timespan']; } else { $graph_start = $graph_end - ($rra['step'] * $rra['rows'] * $rra['steps']); } $aggregate_url = aggregate_build_children_url(grv('local_graph_id'), $graph_start, $graph_end, $rra['id']); print "
"; print '
'; print "
"; if (is_realm_allowed(27)) { print "
"; print ""; print "
"; print ""; print "
"; if (is_realm_allowed(10) && $graph_template_id > 0) { print ""; print ""; print '
'; } if (read_config_option('realtime_enabled') == 'on' || is_realm_allowed(25)) { print "
"; } print($aggregate_url != '' ? $aggregate_url : ''); api_plugin_hook('graph_buttons', ['hook' => 'view', 'local_graph_id' => grv('local_graph_id'), 'rra' => $rra['id'], 'view_type' => grv('view_type')]); print '
'; } print '
' . htmle($rra['name']) . '
'; print "
"; print "
"; print '
'; $i++; } print '
'; api_plugin_hook_function('tree_view_page_end'); } ?> '; bottom_footer(); } /** * Parse and sanitize a comma-separated graph list into validated integer IDs. * * @param string $csv_list Comma-separated list of graph IDs (from request var) * * @return array Array of unique positive integer graph IDs */ function sanitize_graph_id_list(string $csv_list): array { $result = []; foreach (explode(',', $csv_list) as $item) { $item = trim($item); if ($item !== '' && ctype_digit($item)) { $graph_id = (int) $item; if ($graph_id > 0) { $result[] = $graph_id; } } } return array_values(array_unique($result)); } function html_graph_zoom() : void { html_graph_single_validate(); html_graph_check_access(); $info = html_graph_get_info(); $rras = $info['rras']; $graph_title = $info['title']; if (str_contains(gnrv('action'), 'tree')) { $suffix = 'tree'; } else { $suffix = 'preview'; } // find the maximum time span a graph can show $max_timespan = 1; if (cacti_sizeof($rras)) { foreach ($rras as $rra) { if ($rra['steps'] * $rra['rows'] * $rra['rrd_step'] > $max_timespan) { $max_timespan = $rra['steps'] * $rra['rows'] * $rra['rrd_step']; } } } // fetch information for the current RRA if (isrv('rra_id') && grv('rra_id') > 0) { $rra = db_fetch_row_prepared('SELECT dspr.id, step, steps, dspr.name, `rows` FROM data_source_profiles_rra AS dspr INNER JOIN data_source_profiles AS dsp ON dsp.id=dspr.data_source_profile_id WHERE dspr.id = ?', [grv('rra_id')]); $rra['timespan'] = $rra['steps'] * $rra['step'] * $rra['rows']; } else { $rra = db_fetch_row_prepared('SELECT dspr.id, step, steps, dspr.name, `rows` FROM data_source_profiles_rra AS dspr INNER JOIN data_source_profiles AS dsp ON dsp.id=dspr.data_source_profile_id WHERE dspr.id = ?', [$rras[0]['id']]); $rra['timespan'] = $rra['steps'] * $rra['step'] * $rra['rows']; } // define the time span, which decides which rra to use $timespan = - ($rra['timespan']); // find the step and how often this graph is updated with new data $ds_step = db_fetch_cell_prepared('SELECT data_template_data.rrd_step FROM (data_template_data, data_template_rrd, graph_templates_item) WHERE graph_templates_item.task_item_id = data_template_rrd.id AND data_template_rrd.local_data_id = data_template_data.local_data_id AND graph_templates_item.local_graph_id = ? LIMIT 0,1', [grv('local_graph_id')]); $ds_step = empty($ds_step) ? 300 : $ds_step; $seconds_between_graph_updates = ($ds_step * $rra['steps']); $now = time(); if (isrv('graph_end') && (grv('graph_end') <= $now - $seconds_between_graph_updates)) { $graph_end = grv('graph_end'); } else { $graph_end = $now - $seconds_between_graph_updates; } if (isrv('graph_start')) { if (($graph_end - grv('graph_start')) > $max_timespan) { $graph_start = $now - $max_timespan; } else { $graph_start = grv('graph_start'); } } else { $graph_start = $now + $timespan; } // required for zoom out function if ($graph_start == $graph_end) { $graph_start--; } $graph = db_fetch_row_prepared('SELECT gtg.local_graph_id, width, height, title_cache, gtg.graph_template_id, h.id AS host_id, h.disabled FROM graph_templates_graph AS gtg INNER JOIN graph_local AS gl ON gtg.local_graph_id = gl.id LEFT JOIN host AS h ON gl.host_id = h.id WHERE gtg.local_graph_id = ?', [grv('local_graph_id')]); $graph_height = $graph['height']; $graph_width = $graph['width']; $graph_template_id = $graph['graph_template_id']; if (read_user_setting('custom_fonts') == 'on' && read_user_setting('title_size') != '') { $title_font_size = read_user_setting('title_size'); } elseif (read_config_option('title_size') != '') { $title_font_size = read_config_option('title_size'); } else { $title_font_size = 10; } $current_page = get_current_page(); if ($current_page == 'graph.php') { top_header(); } elseif ($current_page == 'graphs.php') { top_header(); } elseif ($current_page == 'graph_view.php') { top_graph_header(); } else { general_header(); } print "
"; html_start_box(__esc('Graph Utility View for Graph: %s', $graph_title), '100%', true, 3, 'center', ''); ?>
'>
' graph_id='' rra_id='' graph_width='' graph_height='' title_font_size=''>
' style='vertical-align:top;' class='graphDrillDown noprint'> _properties' class='iconLink properties'> '>
_csv' class='iconLink properties'> '>
0) { print ""; print '
'; } api_plugin_hook('graph_buttons', ['hook' => 'zoom', 'local_graph_id' => grv('local_graph_id'), 'rra' => grv('rra_id'), 'view_type' => grv('view_type')]); ?>
' . htmle($graph['title_cache']) . '
' : ''); ?>
'> '>
'; bottom_footer(); } function html_graph_properties() : void { html_graph_single_validate(); html_graph_check_access(); $current_page = get_current_page(); if ($current_page == 'graph.php') { top_header(); } elseif ($current_page == 'graphs.php') { top_header(); } elseif ($current_page == 'graph_view.php') { top_graph_header(); } else { general_header(); } $graph_data_array['print_source'] = true; // override: graph start time (unix time) if (!ierv('graph_start')) { $graph_data_array['graph_start'] = grv('graph_start'); } // override: graph end time (unix time) if (!ierv('graph_end')) { $graph_data_array['graph_end'] = grv('graph_end'); } $graph_data_array['output_flag'] = RRDTOOL_OUTPUT_RETURN_STDERR; $graph_data_array['print_source'] = 1; ?>

$options) { $validate[$variable] = $options; } } validate_store_request_vars($validate, 'sess_pview'); }