diff --git a/.phpcs.xml b/.phpcs.xml deleted file mode 100644 index 74cb6a2c..00000000 --- a/.phpcs.xml +++ /dev/null @@ -1,213 +0,0 @@ - - - Observium rules for PHP CodeSniffer - - - - - . - - - - - */attic/* - - */devel/* - - */vendor/* - - */weathermap/* - - tests/php-compatibility/* - - - - - - - - - - - - - - - - irc\.php$ - */weathermap/* - - - - - - - - - - - - - - - - - libs/random_compat/* - - - libs/random_compat/* - - - libs/random_compat/* - - - libs/random_compat/* - libs/pear/Crypt/CHAP\.php - - - libs/random_compat/* - libs/pear/Crypt/CHAP\.php - - - - - libs/pear/Crypt/CHAP\.php - - - libs/pear/Crypt/CHAP\.php - - - libs/pear/Crypt/CHAP\.php - - - libs/pear/Crypt/CHAP\.php - - - libs/pear/Crypt/CHAP\.php - - - libs/pear/Crypt/CHAP\.php - - - libs/pear/Crypt/CHAP\.php - - - libs/pear/Crypt/CHAP\.php - - - - - libs/pear/Net/Socket\.php - - - libs/pear/Net/Socket\.php - - - libs/pear/Net/Socket\.php - - - - - includes/common\.inc\.php - libs/Fabiang/Xmpp/* - - - tests/* - libs/pear/* - - - libs/pear/Mail/mime* - - - includes/definitions\.inc\.php - - - includes/db/mysql\.inc\.php - - - html/includes/authenticate\.inc\.php - - - tests/IncludesEncryptTest\.php - includes/encrypt\.inc\.php - - - tests/IncludesEncryptTest\.php - includes/encrypt\.inc\.php - - - tests/IncludesEncryptTest\.php - includes/encrypt\.inc\.php - - - tests/IncludesEncryptTest\.php - includes/encrypt\.inc\.php - - - tests/IncludesEncryptTest\.php - includes/encrypt\.inc\.php - - - tests/IncludesEncryptTest\.php - includes/encrypt\.inc\.php - - - tests/IncludesEncryptTest\.php - includes/encrypt\.inc\.php - libs/random_compat/* - libs/pear/Crypt/CHAP\.php - - - tests/IncludesEncryptTest\.php - includes/encrypt\.inc\.php - libs/pear/Crypt/CHAP\.php - - - tests/IncludesEncryptTest\.php - includes/encrypt\.inc\.php - libs/pear/Crypt/CHAP\.php - - - tests/IncludesEncryptTest\.php - includes/encrypt\.inc\.php - libs/pear/Crypt/CHAP\.php - - - tests/IncludesEncryptTest\.php - includes/encrypt\.inc\.php - libs/pear/Crypt/CHAP\.php - - - html/includes/collectd/functions.php - - - html/includes/authenticate.inc.php - - - - html/includes/authentication/ldap.inc.php - - - html/includes/authentication/ldap.inc.php - - - html/includes/authentication/ldap.inc.php - - - html/includes/authentication/ldap.inc.php - - - html/includes/authentication/ldap.inc.php - - - includes/entities/sensor.inc.php - - - includes/db/mysqli.inc.php - - - - - - diff --git a/VERSION b/VERSION index fdeb1e34..aa1e3452 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Observium CE 22.5 +Observium CE 22.12 diff --git a/alerter.php b/alerter.php index d7ddedfb..540b546c 100755 --- a/alerter.php +++ b/alerter.php @@ -7,13 +7,13 @@ * * @package observium * @subpackage cli - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ chdir(dirname($argv[0])); -$options = getopt("h:i:m:n:p:dqrsV"); +$options = getopt("h:p:dqrsV"); include("includes/sql-config.inc.php"); @@ -40,7 +40,7 @@ if ($options['h'] === "all") { $where = " "; $doing = "all"; } elseif ($options['h']) { - $params = array(); + $params = []; if (is_numeric($options['h'])) { $where = "AND `device_id` = ?"; $doing = $options['h']; @@ -52,25 +52,26 @@ if ($options['h'] === "all") { } } +if (isset($options['p'])) { + print_cli_heading("%WConstrained to poller partition id ".$options['p']); + $where .= ' AND `poller_id` = ?'; + $params[] = $options['p']; +} + if (!$where) { print_message("%n USAGE: -$scriptname [-drqV] [-i instances] [-n number] [-m module] [-h device] +$scriptname [-drqV] [-p poller_id] [-h device] EXAMPLE: -h | Poll single device --h odd Poll odd numbered devices (same as -i 2 -n 0) --h even Poll even numbered devices (same as -i 2 -n 1) -h all Poll all devices --h new Poll all devices that have not had a discovery run before --i -n Poll as instance of - Instances start at 0. 0-3 for -n 4 +-p Poll for specific poller_id OPTIONS: - -h Device hostname, id or key odd/even/all/new. - -i Poll instance. - -n Poll number. + -h Device hostname, id or hostname or keys all. + -p Poller ID. -s Sends alerts even if they have already been sent. -q Quiet output. -V Show version and exit. @@ -79,7 +80,6 @@ DEBUGGING OPTIONS: -r Do not create or update RRDs -d Enable debugging output. -dd More verbose debugging output. - -m Specify module(s) (separated by commas) to be run. %rInvalid arguments!%n", 'color'); exit; @@ -100,14 +100,16 @@ $_SESSION['userlevel'] = 10; //$params[] = $config['poller_id']; $query = "SELECT * FROM `devices` WHERE `disabled` = 0 $where ORDER BY `device_id` ASC"; -foreach (dbFetch($query, $params) as $device) { +foreach (dbFetchRows($query, $params) as $device) { humanize_device($device); process_alerts($device); - process_notifications(array('device_id' => $device['device_id'])); // Send all notifications (also for syslog from queue) + if ($config['poller-wrapper']['notifications'] || $spam) { + process_notifications([ 'device_id' => $device['device_id'] ]); // Send all notifications (also for syslog from queue) + } - dbUpdate(array('last_alerter' => array('NOW()')), 'devices', '`device_id` = ?', array($device['device_id'])); + dbUpdate([ 'last_alerter' => [ 'NOW()' ] ], 'devices', '`device_id` = ?', [ $device['device_id'] ]); } diff --git a/discovery.php b/discovery.php index 24182df2..af68dfe3 100755 --- a/discovery.php +++ b/discovery.php @@ -122,14 +122,13 @@ if (isset($options['h'])) { } } -if (isset($options['i']) && $options['i'] && isset($options['n'])) { +if (isset($options['i'], $options['n']) && $options['i']) { $where .= ' AND MOD(device_id,' . $options['i'] . ') = ?'; $params[] = $options['n']; $doing = $options['n'] . '/' . $options['i']; } -if (!$where && !$options['u'] && !isset($options['a'])) -{ +if (!$where && !$options['u'] && !isset($options['a'])) { print_message("%n USAGE: $scriptname [-dquV] [-i instances] [-n number] [-m module] [-h device] @@ -169,10 +168,19 @@ if ($config['version_check'] && ($options['h'] !== 'new' || $options['u'])) { if (!$where) { // Only update Group/Alert tables if (isset($options['a'])) { - $silent = isset($options['q']); - // Not exist in CE - if (function_exists('update_group_tables')) { update_group_tables($silent); } - if (function_exists('update_alert_tables')) { update_alert_tables($silent); } + + if (OBS_DISTRIBUTED && function_exists('run_action_queue')) { + //run_action_queue('device_add'); + //run_action_queue('device_rename'); + //run_action_queue('device_delete'); + + // Update alert and group tables + run_action_queue('tables_update'); + } else { + $silent = isset($options['q']); + if (function_exists('update_group_tables')) { update_group_tables($silent); } // Not exist in CE + if (function_exists('update_alert_tables')) { update_alert_tables($silent); } + } } exit; @@ -215,11 +223,10 @@ if (($discovered_devices && !isset($options['m'])) || isset($options['a'])) { if (OBS_DISTRIBUTED && !isset($options['a']) && function_exists('add_action_queue') && $action_id = add_action_queue('tables_update', 'discovery', [ 'silent' => $silent ])) { print_message("Update alert and group tables added to queue [$action_id]."); - //log_event("Device with hostname '$hostname' added to queue [$action_id] for addition on remote Poller [${vars['poller_id']}].", NULL, 'info', NULL, 7); - } elseif (OBSERVIUM_EDITION !== 'community') { - // Not exist in CE - update_group_tables($silent); - update_alert_tables($silent); + //log_event("Device with hostname '$hostname' added to queue [$action_id] for addition on remote Poller [{$vars['poller_id']}].", NULL, 'info', NULL, 7); + } else { + if (function_exists('update_group_tables')) { update_group_tables($silent); } // Not exist in CE + if (function_exists('update_alert_tables')) { update_alert_tables($silent); } } } diff --git a/html/ajax/actions.php b/html/ajax/actions.php index b3729718..7c9c0fbb 100644 --- a/html/ajax/actions.php +++ b/html/ajax/actions.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage ajax - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -235,13 +235,18 @@ switch ($vars['action']) { exit(); } - $widget = dbFetchRow("SELECT * FROM `dash_widgets` WHERE widget_id = ?", array($vars['widget_id'])); + $widget = dbFetchRow("SELECT * FROM `dash_widgets` WHERE `widget_id` = ?", array($vars['widget_id'])); $widget['widget_config'] = safe_json_decode($widget['widget_config']); // Verify config value applies to this widget here + $default_on = [ 'legend' ]; + if (isset($vars['config_field']) && isset($vars['config_value'])) { - if (empty($vars['config_value'])) { + if ( empty($vars['config_value']) || + (in_array($vars['config_field'], $default_on) && get_var_true($vars['config_value'])) || + (!in_array($vars['config_field'], $default_on) && get_var_false($vars['config_value'])) ) { + // Just unset the value if it's empty or it's a default value. unset($widget['widget_config'][$vars['config_field']]); } else { $widget['widget_config'][$vars['config_field']] = $vars['config_value']; @@ -265,7 +270,7 @@ switch ($vars['action']) { // Validate CSRF Token //r($vars); $json = ''; - if (!str_contains_array($vars['action'], [ 'widget', 'dash' ]) && // widget & dashboard currently not send request token + if (!str_contains_array($vars['action'], [ 'widget', 'dash', 'settings_user' ]) && // widget & dashboard currently not send request token !request_token_valid($vars, $json)) { $json = safe_json_decode($json); $json['reload'] = TRUE; diff --git a/html/ajax/actions/edit_widget.inc.php b/html/ajax/actions/edit_widget.inc.php index d248c3ab..0fde55d2 100644 --- a/html/ajax/actions/edit_widget.inc.php +++ b/html/ajax/actions/edit_widget.inc.php @@ -6,13 +6,13 @@ * * @package observium * @subpackage ajax - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ if ($readonly) { return; } // Currently edit allowed only for 7+ -$widget = dbFetchRow("SELECT * FROM `dash_widgets` WHERE widget_id = ?", array($vars['widget_id'])); +$widget = dbFetchRow("SELECT * FROM `dash_widgets` WHERE `widget_id` = ?", [ $vars['widget_id'] ]); $widget['widget_config'] = safe_json_decode($widget['widget_config']); @@ -22,11 +22,111 @@ switch ($widget['widget_type']) { if (safe_count($widget['widget_config'])) { +// echo ' +//
+// Title +//
+// '; + + //r($widget['widget_config']); + + //r(isset($widget['widget_config']['legend']) && $widget['widget_config']['legend'] === 'no'); + + $modal_args = [ + 'id' => 'modal-edit_widget_' . $widget['widget_id'], + 'title' => 'Configure Widget', + //'hide' => TRUE, + //'fade' => TRUE, + //'role' => 'dialog', + //'class' => 'modal-md', + ]; + + $form = [ + 'form_only' => TRUE, // Do not add modal open/close divs (it's generated outside) + 'type' => 'horizontal', + 'id' => 'edit_widget_' . $widget['widget_id'], + 'userlevel' => 7, // Minimum user level for display form + 'modal_args' => $modal_args, // !!! This generate modal specific form + //'help' => 'This will completely delete the rule and all associations and history.', + 'class' => '', // Clean default box class! + //'url' => generate_url([ 'page' => 'syslog_rules' ]), + 'onsubmit' => "return false", + ]; + $form['fieldset']['body'] = [ 'class' => 'modal-body' ]; // Required this class for modal body! + $form['fieldset']['footer'] = [ 'class' => 'modal-footer' ]; // Required this class for modal footer! + + $form['row'][1]['widget-config-title'] = [ + 'type' => 'text', + 'fieldset' => 'body', + 'name' => 'Title', + 'placeholder' => 'Graph Title', + 'class' => 'input-xlarge', + 'attribs' => [ + 'data-id' => $widget['widget_id'], + 'data-field' => 'title', + 'data-type' => 'text' + ], + 'value' => $widget['widget_config']['title'] + ]; + $form['row'][2]['widget-config-legend'] = [ + 'type' => 'checkbox', + 'fieldset' => 'body', + 'name' => 'Show Legend', + //'placeholder' => 'Yes, please delete this rule.', + //'onchange' => "javascript: toggleAttrib('disabled', 'delete_button_".$la['la_id']."'); showDiv(!this.checked, 'warning_".$la['la_id']."_div');", + 'attribs' => [ + 'data-id' => $widget['widget_id'], + 'data-field' => 'legend', + 'data-type' => 'checkbox' + ], + 'value' => safe_empty($widget['widget_config']['legend']) ? 'yes' : $widget['widget_config']['legend'] //'legend' + ]; + + + $form['row'][8]['close'] = [ + 'type' => 'submit', + 'fieldset' => 'footer', + 'div_class' => '', // Clean default form-action class! + 'name' => 'Close', + 'icon' => '', + 'attribs' => [ + 'data-dismiss' => 'modal', + 'aria-hidden' => 'true' + ] + ]; + + echo generate_form_modal($form); + unset($form); + + /* echo ' -
- Title -
- '; +
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+
+ + + +
'; + */ + } else { diff --git a/html/ajax/actions/settings_edit.inc.php b/html/ajax/actions/settings_edit.inc.php index ccd514af..b8f11dbb 100644 --- a/html/ajax/actions/settings_edit.inc.php +++ b/html/ajax/actions/settings_edit.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -34,7 +34,7 @@ $updates = 0; // Set fields that were submitted with custom value if (safe_count($sets)) { - $query = 'SELECT * FROM `users_prefs` WHERE `user_id` = ?' . generate_query_values(array_keys($sets), 'pref'); + $query = 'SELECT * FROM `users_prefs` WHERE `user_id` = ?' . generate_query_values_and(array_keys($sets), 'pref'); // Fetch current rows in config file so we know which one to UPDATE and which one to INSERT $in_db = []; foreach (dbFetchRows($query, [ $user_id ]) as $row) { @@ -52,7 +52,7 @@ if (safe_count($sets)) { // Delete fields that were reset to default if (safe_count($deletes)) { - dbDelete('users_prefs', '`user_id` = ? ' . generate_query_values($deletes, 'pref'), [ $user_id ]); + dbDelete('users_prefs', '`user_id` = ? ' . generate_query_values_and($deletes, 'pref'), [ $user_id ]); $updates++; } diff --git a/html/ajax/actions/settings_user.inc.php b/html/ajax/actions/settings_user.inc.php new file mode 100644 index 00000000..d2cc7fe7 --- /dev/null +++ b/html/ajax/actions/settings_user.inc.php @@ -0,0 +1,66 @@ +', '|', $vars['setting'])) { + case "theme": + case "web_theme_default": + $pref = 'web_theme_default'; + if ($vars['value'] === 'reset') { + session_unset_var("theme"); + if ($config['web_theme_default'] === 'system') { + // Override default + session_unset_var("theme_default"); + } + + if (del_user_pref($_SESSION['user_id'], $pref)) { + print_json_status('ok', 'Theme reset.'); + } + } elseif (isset($config['themes'][$vars['value']]) || $vars['value'] === 'system') { + if (set_user_pref($_SESSION['user_id'], $pref, serialize($vars['value']))) { + print_json_status('ok', 'Theme set.'); + } + } else { + print_json_status('failed', 'Invalid theme.'); + } + break; + + case "big_graphs": + $pref = 'graphs|size'; + if (set_user_pref($_SESSION['user_id'], $pref, serialize('big'))) { + print_json_status('ok', 'Big graphs set.'); + session_unset_var("big_graphs"); // clear old + } + //session_set_var("big_graphs", TRUE); + //print_json_status('ok', 'Big graphs set.'); + break; + + case "normal_graphs": + $pref = 'graphs|size'; + if (set_user_pref($_SESSION['user_id'], $pref, serialize('normal'))) { + print_json_status('ok', 'Normal graphs set.'); + session_unset_var("big_graphs"); // clear old + } + //session_unset_var("big_graphs"); + //print_json_status('ok', 'Small graphs set.'); + break; + + case "sensors|web_measured_compact": + // BOOL values + $pref = $vars['setting']; + if (set_user_pref($_SESSION['user_id'], $pref, serialize(get_var_true($vars['value'])))) { + print_json_status('ok', 'Setting was set.', [ 'reload' => TRUE ]); + } + break; + +} +// EOF diff --git a/html/ajax/entity_popup.php b/html/ajax/entity_popup.php index 0769f1d9..eda71084 100644 --- a/html/ajax/entity_popup.php +++ b/html/ajax/entity_popup.php @@ -21,10 +21,12 @@ if (!$_SESSION['authenticated']) { print_error('Session expired, please log in a ob_start(); -$vars = get_vars(); +$vars = get_vars([ 'JSON', 'POST', 'GET' ]); $vars['page'] = "popup"; +if(isset($vars['debug'])) { r($vars); } + switch ($vars['entity_type']) { case "port": if (is_numeric($vars['entity_id']) && (port_permitted($vars['entity_id']))) { @@ -35,6 +37,23 @@ switch ($vars['entity_type']) { } break; + case "link": + if (is_numeric($vars['entity_id_a']) && (port_permitted($vars['entity_id_a']))) { + $port = get_port_by_id($vars['entity_id_a']); + echo generate_port_popup($port); + } else { + print_warning("You are not permitted to view this port."); + } + + if (is_numeric($vars['entity_id_b']) && (port_permitted($vars['entity_id_b']))) { + $port = get_port_by_id($vars['entity_id_b']); + echo generate_port_popup($port, '','none'); // suppress graph for b side of link + } else { + print_warning("You are not permitted to view this port."); + } + break; + + case "device": if (is_numeric($vars['entity_id']) && device_permitted($vars['entity_id'])) { $device = device_by_id_cache($vars['entity_id']); @@ -53,7 +72,6 @@ switch ($vars['entity_type']) { } break; - // FIXME : mac is not an observium entity. This should go elsewhere! case "mac": if (preg_match('/^' . OBS_PATTERN_MAC . '$/i', $vars['entity_id'])) { $mac = format_mac($vars['entity_id']); diff --git a/html/ajax/input.php b/html/ajax/input.php index 0f82d641..d71ce116 100644 --- a/html/ajax/input.php +++ b/html/ajax/input.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage ajax - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -48,11 +48,11 @@ if ($cache_key && $options = get_cache_session($cache_key)) { list($ip_version) = explode('_', $vars['field']); $query_permitted = generate_query_permitted('ports'); $network_permitted = dbFetchColumn('SELECT DISTINCT(`' . $ip_version . '_network_id`) FROM `' . $ip_version . '_addresses` WHERE 1' . $query_permitted); - $query = 'SELECT `' . $ip_version . '_network` FROM `' . $ip_version . '_networks` WHERE 1 ' . generate_query_values($network_permitted, $ip_version . '_network_id'); + $query = 'SELECT `' . $ip_version . '_network` FROM `' . $ip_version . '_networks` WHERE 1 ' . generate_query_values_and($network_permitted, $ip_version . '_network_id'); if (!safe_empty($vars['query'])) { //$query .= ' AND `' . $ip_version . '_network` LIKE ?'; //$params[] = '%' . $vars['query'] . '%'; - $query .= generate_query_values($vars['query'], $vars['field'], '%LIKE%'); + $query .= generate_query_values_and($vars['query'], $vars['field'], '%LIKE%'); } $query .= ' ORDER BY `' . $ip_version . '_network`;'; //print_vars($query); @@ -69,7 +69,7 @@ if ($cache_key && $options = get_cache_session($cache_key)) { //$query_permitted = generate_query_permitted(); $query = 'SELECT DISTINCT `program` FROM `syslog`'; if (is_intnum($vars['device_id'])) { - $query .= ' WHERE ' . generate_query_values($vars['device_id'], 'device_id', NULL, FALSE); + $query .= ' WHERE ' . generate_query_values_ng($vars['device_id'], 'device_id'); } $array_filter = TRUE; // Search query string in array instead sql query (when this faster) break; @@ -86,7 +86,7 @@ if ($cache_key && $options = get_cache_session($cache_key)) { $query .= ' AND (`' . $column . '` LIKE ? OR `astext` LIKE ?)'; $params[] = '%' . $vars['query'] . '%'; $params[] = '%' . $vars['query'] . '%'; - //$query .= generate_query_values($vars['query'], $vars['field'], '%LIKE%'); + //$query .= generate_query_values_and($vars['query'], $vars['field'], '%LIKE%'); } break; @@ -100,7 +100,7 @@ if ($cache_key && $options = get_cache_session($cache_key)) { $query_permitted = generate_query_permitted('devices'); $query = 'SELECT DISTINCT `' . $column . '` FROM `bgpPeers` WHERE 1 ' . $query_permitted; if (!safe_empty($vars['query'])) { - $query .= generate_query_values($vars['query'], $column, '%LIKE%'); + $query .= generate_query_values_and($vars['query'], $column, '%LIKE%'); } break; diff --git a/html/ajax/search.php b/html/ajax/search.php index a42acf03..72a689d6 100644 --- a/html/ajax/search.php +++ b/html/ajax/search.php @@ -26,8 +26,7 @@ $query_limit = 8; // Limit per query $vars = get_vars([ 'POST', 'GET' ]); // Is there a POST/GET query string? -if (isset($vars['queryString'])) -{ +if (isset($vars['queryString'])) { $queryString = trim($vars['queryString']); // Is the string length greater than 0? diff --git a/html/ajax/widget.php b/html/ajax/widget.php index db54d8d2..bfc7c158 100644 --- a/html/ajax/widget.php +++ b/html/ajax/widget.php @@ -169,8 +169,14 @@ function print_dash_mod ($mod) echo '
'; echo ' '; echo '
'; - print_syslogs(array('short' => TRUE, 'pagesize' => ($height - 36) / 26, - 'priority' => $config['frontpage']['syslog']['priority'])); + + $syslog_vars = $mod['vars']; + + $syslog_vars = array_merge($syslog_vars, ['short' => TRUE, 'pagesize' => ($height - 36) / 26, + 'priority' => $config['frontpage']['syslog']['priority']]); + + print_syslogs($syslog_vars); + echo '
'; echo '
'; break; @@ -372,7 +378,7 @@ function print_dash_graph($mod, $width, $height) { if ($graph_array['width'] > 350) { $graph_array['height'] -= 6; - } // RRD graphs > 350px are 6 px wider because of larger legend font + } // RRD graphs > 350px are 6 px taller because of larger legend font $title_div = 'top:0px; left: 0px; padding: 4px; border-top-left-radius: 4px; border: 1px solid #e5e5e5; border-left: none; border-top: none; background-color: rgba(255, 255,255, 0.75); '; $title_div = 'widget-title'; @@ -411,7 +417,10 @@ function print_dash_graph($mod, $width, $height) { //$graph_array['format'] = 'png'; //$graph_array['img_id'] = generate_random_string(5); - $graph_array['legend'] = 'no'; + //$graph_array['legend'] = 'no'; + + $graph_array['rigid_height'] = 'yes'; // Force height of graph to be same as height of graph_type. + $graph_array['class'] = 'image-refresh'; $graph = generate_graph_tag($graph_array, TRUE); @@ -419,6 +428,7 @@ function print_dash_graph($mod, $width, $height) { $link_array = $graph_array; $link_array['page'] = "graphs"; unset($link_array['graph_only']); + unset($link_array['rigid_height']); unset($link_array['height'], $link_array['width']); $link = generate_url($link_array); diff --git a/html/css/bootstrap.css b/html/css/bootstrap.css index 56de8a23..257d066a 100644 --- a/html/css/bootstrap.css +++ b/html/css/bootstrap.css @@ -10404,7 +10404,7 @@ a.badge:focus { box-shadow: none; padding: 0; } -.qtip-content { +.qtip-content, .tippy-content { position: relative; padding: 5px 9px; overflow: hidden; @@ -10503,7 +10503,7 @@ a.badge:focus { * Tested with IE 8, IE 9, Chrome 18, Firefox 9, Opera 11. * Does not work with IE 7. */ -.qtip-bootstrap { +.qtip-bootstrap, .tippy-box { /** Taken from Bootstrap body */ font-size: 14px; line-height: 20px; diff --git a/html/css/easymde.min.css b/html/css/easymde.min.css new file mode 100644 index 00000000..c12d90a4 --- /dev/null +++ b/html/css/easymde.min.css @@ -0,0 +1,7 @@ +/** + * easymde v2.17.0 + * Copyright Jeroen Akkerman + * @link https://github.com/ionaru/easy-markdown-editor + * @license MIT + */ +.CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding:0 4px}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-fat-cursor .CodeMirror-line::selection,.cm-fat-cursor .CodeMirror-line>span::selection,.cm-fat-cursor .CodeMirror-line>span>span::selection{background:0 0}.cm-fat-cursor .CodeMirror-line::-moz-selection,.cm-fat-cursor .CodeMirror-line>span::-moz-selection,.cm-fat-cursor .CodeMirror-line>span>span::-moz-selection{background:0 0}.cm-fat-cursor{caret-color:transparent}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-type,.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta{color:#555}.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-s-default .cm-error{color:red}.cm-invalidchar{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:0;position:relative;z-index:0}.CodeMirror-sizer{position:relative;border-right:50px solid transparent}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{position:absolute;z-index:6;display:none;outline:0}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:0 0!important;border:none!important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:0 0;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:0}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}span.CodeMirror-selectedtext{background:0 0}.EasyMDEContainer{display:block}.CodeMirror-rtl pre{direction:rtl}.EasyMDEContainer.sided--no-fullscreen{display:flex;flex-direction:row;flex-wrap:wrap}.EasyMDEContainer .CodeMirror{box-sizing:border-box;height:auto;border:1px solid #ced4da;border-bottom-left-radius:4px;border-bottom-right-radius:4px;padding:10px;font:inherit;z-index:0;word-wrap:break-word}.EasyMDEContainer .CodeMirror-scroll{cursor:text}.EasyMDEContainer .CodeMirror-fullscreen{background:#fff;position:fixed!important;top:50px;left:0;right:0;bottom:0;height:auto;z-index:8;border-right:none!important;border-bottom-right-radius:0!important}.EasyMDEContainer .CodeMirror-sided{width:50%!important}.EasyMDEContainer.sided--no-fullscreen .CodeMirror-sided{border-right:none!important;border-bottom-right-radius:0;position:relative;flex:1 1 auto}.EasyMDEContainer .CodeMirror-placeholder{opacity:.5}.EasyMDEContainer .CodeMirror-focused .CodeMirror-selected{background:#d9d9d9}.editor-toolbar{position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;padding:9px 10px;border-top:1px solid #ced4da;border-left:1px solid #ced4da;border-right:1px solid #ced4da;border-top-left-radius:4px;border-top-right-radius:4px}.editor-toolbar.fullscreen{width:100%;height:50px;padding-top:10px;padding-bottom:10px;box-sizing:border-box;background:#fff;border:0;position:fixed;top:0;left:0;opacity:1;z-index:9}.editor-toolbar.fullscreen::before{width:20px;height:50px;background:-moz-linear-gradient(left,#fff 0,rgba(255,255,255,0) 100%);background:-webkit-gradient(linear,left top,right top,color-stop(0,#fff),color-stop(100%,rgba(255,255,255,0)));background:-webkit-linear-gradient(left,#fff 0,rgba(255,255,255,0) 100%);background:-o-linear-gradient(left,#fff 0,rgba(255,255,255,0) 100%);background:-ms-linear-gradient(left,#fff 0,rgba(255,255,255,0) 100%);background:linear-gradient(to right,#fff 0,rgba(255,255,255,0) 100%);position:fixed;top:0;left:0;margin:0;padding:0}.editor-toolbar.fullscreen::after{width:20px;height:50px;background:-moz-linear-gradient(left,rgba(255,255,255,0) 0,#fff 100%);background:-webkit-gradient(linear,left top,right top,color-stop(0,rgba(255,255,255,0)),color-stop(100%,#fff));background:-webkit-linear-gradient(left,rgba(255,255,255,0) 0,#fff 100%);background:-o-linear-gradient(left,rgba(255,255,255,0) 0,#fff 100%);background:-ms-linear-gradient(left,rgba(255,255,255,0) 0,#fff 100%);background:linear-gradient(to right,rgba(255,255,255,0) 0,#fff 100%);position:fixed;top:0;right:0;margin:0;padding:0}.EasyMDEContainer.sided--no-fullscreen .editor-toolbar{width:100%}.editor-toolbar .easymde-dropdown,.editor-toolbar button{background:0 0;display:inline-block;text-align:center;text-decoration:none!important;height:30px;margin:0;padding:0;border:1px solid transparent;border-radius:3px;cursor:pointer}.editor-toolbar button{font-weight:700;min-width:30px;padding:0 6px;white-space:nowrap}.editor-toolbar button.active,.editor-toolbar button:hover{background:#fcfcfc;border-color:#95a5a6}.editor-toolbar i.separator{display:inline-block;width:0;border-left:1px solid #d9d9d9;border-right:1px solid #fff;color:transparent;text-indent:-10px;margin:0 6px}.editor-toolbar button:after{font-family:Arial,"Helvetica Neue",Helvetica,sans-serif;font-size:65%;vertical-align:text-bottom;position:relative;top:2px}.editor-toolbar button.heading-1:after{content:"1"}.editor-toolbar button.heading-2:after{content:"2"}.editor-toolbar button.heading-3:after{content:"3"}.editor-toolbar button.heading-bigger:after{content:"▲"}.editor-toolbar button.heading-smaller:after{content:"▼"}.editor-toolbar.disabled-for-preview button:not(.no-disable){opacity:.6;pointer-events:none}@media only screen and (max-width:700px){.editor-toolbar i.no-mobile{display:none}}.editor-statusbar{padding:8px 10px;font-size:12px;color:#959694;text-align:right}.EasyMDEContainer.sided--no-fullscreen .editor-statusbar{width:100%}.editor-statusbar span{display:inline-block;min-width:4em;margin-left:1em}.editor-statusbar .lines:before{content:'lines: '}.editor-statusbar .words:before{content:'words: '}.editor-statusbar .characters:before{content:'characters: '}.editor-preview-full{position:absolute;width:100%;height:100%;top:0;left:0;z-index:7;overflow:auto;display:none;box-sizing:border-box}.editor-preview-side{position:fixed;bottom:0;width:50%;top:50px;right:0;z-index:9;overflow:auto;display:none;box-sizing:border-box;border:1px solid #ddd;word-wrap:break-word}.editor-preview-active-side{display:block}.EasyMDEContainer.sided--no-fullscreen .editor-preview-active-side{flex:1 1 auto;height:auto;position:static}.editor-preview-active{display:block}.editor-preview{padding:10px;background:#fafafa}.editor-preview>p{margin-top:0}.editor-preview pre{background:#eee;margin-bottom:10px}.editor-preview table td,.editor-preview table th{border:1px solid #ddd;padding:5px}.cm-s-easymde .cm-tag{color:#63a35c}.cm-s-easymde .cm-attribute{color:#795da3}.cm-s-easymde .cm-string{color:#183691}.cm-s-easymde .cm-header-1{font-size:calc(1.375rem + 1.5vw)}.cm-s-easymde .cm-header-2{font-size:calc(1.325rem + .9vw)}.cm-s-easymde .cm-header-3{font-size:calc(1.3rem + .6vw)}.cm-s-easymde .cm-header-4{font-size:calc(1.275rem + .3vw)}.cm-s-easymde .cm-header-5{font-size:1.25rem}.cm-s-easymde .cm-header-6{font-size:1rem}.cm-s-easymde .cm-header-1,.cm-s-easymde .cm-header-2,.cm-s-easymde .cm-header-3,.cm-s-easymde .cm-header-4,.cm-s-easymde .cm-header-5,.cm-s-easymde .cm-header-6{margin-bottom:.5rem;line-height:1.2}.cm-s-easymde .cm-comment{background:rgba(0,0,0,.05);border-radius:2px}.cm-s-easymde .cm-link{color:#7f8c8d}.cm-s-easymde .cm-url{color:#aab2b3}.cm-s-easymde .cm-quote{color:#7f8c8d;font-style:italic}.editor-toolbar .easymde-dropdown{position:relative;background:linear-gradient(to bottom right,#fff 0,#fff 84%,#333 50%,#333 100%);border-radius:0;border:1px solid #fff}.editor-toolbar .easymde-dropdown:hover{background:linear-gradient(to bottom right,#fff 0,#fff 84%,#333 50%,#333 100%)}.easymde-dropdown-content{display:block;visibility:hidden;position:absolute;background-color:#f9f9f9;box-shadow:0 8px 16px 0 rgba(0,0,0,.2);padding:8px;z-index:2;top:30px}.easymde-dropdown:active .easymde-dropdown-content,.easymde-dropdown:focus .easymde-dropdown-content,.easymde-dropdown:focus-within .easymde-dropdown-content{visibility:visible}.easymde-dropdown-content button{display:block}span[data-img-src]::after{content:'';background-image:var(--bg-image);display:block;max-height:100%;max-width:100%;background-size:contain;height:0;padding-top:var(--height);width:var(--width);background-repeat:no-repeat}.CodeMirror .cm-spell-error:not(.cm-url):not(.cm-comment):not(.cm-tag):not(.cm-word){background:rgba(255,0,0,.15)} \ No newline at end of file diff --git a/html/css/observium.css b/html/css/observium.css index 4f983c57..f5262317 100644 --- a/html/css/observium.css +++ b/html/css/observium.css @@ -6275,6 +6275,10 @@ i.menu-icon, margin-right: 5px; margin-top: 1px; } +.dropdown-scrollable .dropdown-menu { + max-height: 1000px; + overflow-y: auto; +} .well { min-height: 20px; padding: 10px; @@ -6769,6 +6773,7 @@ i.menu-icon, color: #444; display: block; padding: 7px 10px; + padding-bottom: 4px; position: relative; background-color: #fafafa; } @@ -10449,7 +10454,8 @@ a.badge:focus { * Tested with IE 8, IE 9, Chrome 18, Firefox 9, Opera 11. * Does not work with IE 7. */ -.qtip-bootstrap { +.qtip-bootstrap, +.tippy-box { /** Taken from Bootstrap body */ font-size: 14px; line-height: 20px; @@ -10496,9 +10502,10 @@ a.badge:focus { top: 45%; border-style: none; } -.qtip-bootstrap .qtip-content { +.qtip-bootstrap .qtip-content, +.tippy-content { /** Taken from Bootstrap .popover-content */ - padding: 9px 14px; + padding: 9px 9px; } .qtip-bootstrap .qtip-icon { /** @@ -10916,11 +10923,13 @@ select.selectpicker { overflow: hidden; } .bootstrap-select .dropdown-toggle .caret { + right: 12px; + /* position: absolute; top: 50%; - right: 12px; margin-top: -2px; vertical-align: middle; +*/ } .input-group .bootstrap-select.form-control .dropdown-toggle { border-radius: inherit; @@ -12127,6 +12136,12 @@ form.pagination { .form-horizontal .col-md-4 .control-label { width: 120px; } +.dygraph-axis-label > .dygraph-axis-label-x { + color: #333333; +} +.dygraph-axis-label > .dygraph-axis-label-y { + color: #333333; +} /*EOF*/ #suggestions { display: none; diff --git a/html/css/simplemde.min.css b/html/css/simplemde.min.css deleted file mode 100644 index d62f4d77..00000000 --- a/html/css/simplemde.min.css +++ /dev/null @@ -1,7 +0,0 @@ -/** - * simplemde v1.11.2 - * Copyright Next Step Webs, Inc. - * @link https://github.com/NextStepWebs/simplemde-markdown-editor - * @license MIT - */ -.CodeMirror{color:#000}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-ruler{border-left:1px solid #ccc;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:0;position:relative}.CodeMirror-sizer{position:relative;border-right:30px solid transparent}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-30px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:0 0!important;border:none!important;-webkit-user-select:none;-moz-user-select:none;user-select:none}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:0 0;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:none;font-variant-ligatures:none}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;overflow:auto}.CodeMirror-code{outline:0}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected,.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}span.CodeMirror-selectedtext{background:0 0}.CodeMirror{height:auto;min-height:300px;border:1px solid #ddd;border-bottom-left-radius:4px;border-bottom-right-radius:4px;padding:10px;font:inherit;z-index:1}.CodeMirror-scroll{min-height:300px}.CodeMirror-fullscreen{background:#fff;position:fixed!important;top:50px;left:0;right:0;bottom:0;height:auto;z-index:9}.CodeMirror-sided{width:50%!important}.editor-toolbar{position:relative;opacity:.6;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;padding:0 10px;border-top:1px solid #bbb;border-left:1px solid #bbb;border-right:1px solid #bbb;border-top-left-radius:4px;border-top-right-radius:4px}.editor-toolbar:after,.editor-toolbar:before{display:block;content:' ';height:1px}.editor-toolbar:before{margin-bottom:8px}.editor-toolbar:after{margin-top:8px}.editor-toolbar:hover,.editor-wrapper input.title:focus,.editor-wrapper input.title:hover{opacity:.8}.editor-toolbar.fullscreen{width:100%;height:50px;overflow-x:auto;overflow-y:hidden;white-space:nowrap;padding-top:10px;padding-bottom:10px;box-sizing:border-box;background:#fff;border:0;position:fixed;top:0;left:0;opacity:1;z-index:9}.editor-toolbar.fullscreen::before{width:20px;height:50px;background:-moz-linear-gradient(left,rgba(255,255,255,1) 0,rgba(255,255,255,0) 100%);background:-webkit-gradient(linear,left top,right top,color-stop(0,rgba(255,255,255,1)),color-stop(100%,rgba(255,255,255,0)));background:-webkit-linear-gradient(left,rgba(255,255,255,1) 0,rgba(255,255,255,0) 100%);background:-o-linear-gradient(left,rgba(255,255,255,1) 0,rgba(255,255,255,0) 100%);background:-ms-linear-gradient(left,rgba(255,255,255,1) 0,rgba(255,255,255,0) 100%);background:linear-gradient(to right,rgba(255,255,255,1) 0,rgba(255,255,255,0) 100%);position:fixed;top:0;left:0;margin:0;padding:0}.editor-toolbar.fullscreen::after{width:20px;height:50px;background:-moz-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,1) 100%);background:-webkit-gradient(linear,left top,right top,color-stop(0,rgba(255,255,255,0)),color-stop(100%,rgba(255,255,255,1)));background:-webkit-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,1) 100%);background:-o-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,1) 100%);background:-ms-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,1) 100%);background:linear-gradient(to right,rgba(255,255,255,0) 0,rgba(255,255,255,1) 100%);position:fixed;top:0;right:0;margin:0;padding:0}.editor-toolbar a{display:inline-block;text-align:center;text-decoration:none!important;color:#2c3e50!important;width:30px;height:30px;margin:0;border:1px solid transparent;border-radius:3px;cursor:pointer}.editor-toolbar a.active,.editor-toolbar a:hover{background:#fcfcfc;border-color:#95a5a6}.editor-toolbar a:before{line-height:30px}.editor-toolbar i.separator{display:inline-block;width:0;border-left:1px solid #d9d9d9;border-right:1px solid #fff;color:transparent;text-indent:-10px;margin:0 6px}.editor-toolbar a.fa-header-x:after{font-family:Arial,"Helvetica Neue",Helvetica,sans-serif;font-size:65%;vertical-align:text-bottom;position:relative;top:2px}.editor-toolbar a.fa-header-1:after{content:"1"}.editor-toolbar a.fa-header-2:after{content:"2"}.editor-toolbar a.fa-header-3:after{content:"3"}.editor-toolbar a.fa-header-bigger:after{content:"▲"}.editor-toolbar a.fa-header-smaller:after{content:"▼"}.editor-toolbar.disabled-for-preview a:not(.no-disable){pointer-events:none;background:#fff;border-color:transparent;text-shadow:inherit}@media only screen and (max-width:700px){.editor-toolbar a.no-mobile{display:none}}.editor-statusbar{padding:8px 10px;font-size:12px;color:#959694;text-align:right}.editor-statusbar span{display:inline-block;min-width:4em;margin-left:1em}.editor-preview,.editor-preview-side{padding:10px;background:#fafafa;overflow:auto;display:none;box-sizing:border-box}.editor-statusbar .lines:before{content:'lines: '}.editor-statusbar .words:before{content:'words: '}.editor-statusbar .characters:before{content:'characters: '}.editor-preview{position:absolute;width:100%;height:100%;top:0;left:0;z-index:7}.editor-preview-side{position:fixed;bottom:0;width:50%;top:50px;right:0;z-index:9;border:1px solid #ddd}.editor-preview-active,.editor-preview-active-side{display:block}.editor-preview-side>p,.editor-preview>p{margin-top:0}.editor-preview pre,.editor-preview-side pre{background:#eee;margin-bottom:10px}.editor-preview table td,.editor-preview table th,.editor-preview-side table td,.editor-preview-side table th{border:1px solid #ddd;padding:5px}.CodeMirror .CodeMirror-code .cm-tag{color:#63a35c}.CodeMirror .CodeMirror-code .cm-attribute{color:#795da3}.CodeMirror .CodeMirror-code .cm-string{color:#183691}.CodeMirror .CodeMirror-selected{background:#d9d9d9}.CodeMirror .CodeMirror-code .cm-header-1{font-size:200%;line-height:200%}.CodeMirror .CodeMirror-code .cm-header-2{font-size:160%;line-height:160%}.CodeMirror .CodeMirror-code .cm-header-3{font-size:125%;line-height:125%}.CodeMirror .CodeMirror-code .cm-header-4{font-size:110%;line-height:110%}.CodeMirror .CodeMirror-code .cm-comment{background:rgba(0,0,0,.05);border-radius:2px}.CodeMirror .CodeMirror-code .cm-link{color:#7f8c8d}.CodeMirror .CodeMirror-code .cm-url{color:#aab2b3}.CodeMirror .CodeMirror-code .cm-strikethrough{text-decoration:line-through}.CodeMirror .CodeMirror-placeholder{opacity:.5}.CodeMirror .cm-spell-error:not(.cm-url):not(.cm-comment):not(.cm-tag):not(.cm-word){background:rgba(255,0,0,.15)} \ No newline at end of file diff --git a/html/data.php b/html/data.php index f2720886..e827a686 100644 --- a/html/data.php +++ b/html/data.php @@ -1,24 +1,22 @@ - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2019 Observium Limited + * @subpackage web + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ + include_once("../includes/sql-config.inc.php"); include($config['html_dir'] . "/includes/functions.inc.php"); include($config['html_dir'] . "/includes/authenticate.inc.php"); -if (is_numeric($_GET['id']) && ($config['allow_unauth_graphs'] || port_permitted($_GET['id']))) -{ +if (is_numeric($_GET['id']) && ($config['allow_unauth_graphs'] || port_permitted($_GET['id']))) { $port = get_port_by_id($_GET['id']); $device = device_by_id_cache($port['device_id']); //$title = generate_device_link($device); @@ -28,9 +26,9 @@ if (is_numeric($_GET['id']) && ($config['allow_unauth_graphs'] || port_permitted $time = time(); $HC = ($port['port_64bit'] ? 'HC' : ''); - $data = snmp_get_multi_oid($device, "if${HC}InOctets.".$port['ifIndex']." if${HC}OutOctets.".$port['ifIndex'], array(),"IF-MIB"); + $data = snmp_get_multi_oid($device, "if{$HC}InOctets.".$port['ifIndex']." if{$HC}OutOctets.".$port['ifIndex'], [], "IF-MIB"); - printf("%lf|%s|%s\n", $time, $data[$port['ifIndex']]["if${HC}InOctets"], $data[$port['ifIndex']]["if${HC}OutOctets"]); + printf("%lf|%s|%s\n", $time, $data[$port['ifIndex']]["if{$HC}InOctets"], $data[$port['ifIndex']]["if{$HC}OutOctets"]); } else { echo("unauthenticated"); exit; diff --git a/html/graph-realtime.php b/html/graph-realtime.php index 9a129290..16683236 100644 --- a/html/graph-realtime.php +++ b/html/graph-realtime.php @@ -199,8 +199,12 @@ function fetch_data() { function plot_data(obj) { // Show datetimelegend var now = new Date(); - var datetime = (now.getMonth()+1) + "/" + now.getDate() + "/" + now.getFullYear() + ' ' + - LZ(now.getHours()) + ":" + LZ(now.getMinutes()) + ":" + LZ(now.getSeconds()); + //var datetime = (now.getMonth()+1) + "/" + now.getDate() + "/" + now.getFullYear() + ' ' + + // LZ(now.getHours()) + ":" + LZ(now.getMinutes()) + ":" + LZ(now.getSeconds()); + + datetime = now.toLocaleString(); + //datetime = now.toISOString(); + SVGDoc.getElementById('datetime').firstChild.data = datetime; if (!obj.success) diff --git a/html/graph.php b/html/graph.php index 6de537c2..c7d24a71 100644 --- a/html/graph.php +++ b/html/graph.php @@ -15,9 +15,9 @@ // Define this is graph define('OBS_GRAPH', TRUE); -include_once("../includes/sql-config.inc.php"); +$start = microtime(TRUE); // Needs common.php -$start = utime(); // Needs common.php +include_once("../includes/sql-config.inc.php"); include($config['html_dir'] . "/includes/functions.inc.php"); @@ -44,7 +44,7 @@ $vars = get_vars('GET', $auth); include($config['html_dir'] . "/includes/graphs/graph.inc.php"); -$runtime = utime() - $start; +$runtime = microtime(TRUE) - $start; print_debug("Runtime ".$runtime." secs"); diff --git a/html/images/os/acksys.png b/html/images/os/acksys.png new file mode 100644 index 00000000..03975dcd Binary files /dev/null and b/html/images/os/acksys.png differ diff --git a/html/images/os/acksys_2x.png b/html/images/os/acksys_2x.png new file mode 100644 index 00000000..64ce9241 Binary files /dev/null and b/html/images/os/acksys_2x.png differ diff --git a/html/images/os/affirmed.png b/html/images/os/affirmed.png new file mode 100644 index 00000000..5aa6a2a6 Binary files /dev/null and b/html/images/os/affirmed.png differ diff --git a/html/images/os/affirmed_2x.png b/html/images/os/affirmed_2x.png new file mode 100644 index 00000000..e095b452 Binary files /dev/null and b/html/images/os/affirmed_2x.png differ diff --git a/html/images/os/allot-dark.png b/html/images/os/allot-dark.png new file mode 100644 index 00000000..61141227 Binary files /dev/null and b/html/images/os/allot-dark.png differ diff --git a/html/images/os/allot-dark_2x.png b/html/images/os/allot-dark_2x.png new file mode 100644 index 00000000..09b6622f Binary files /dev/null and b/html/images/os/allot-dark_2x.png differ diff --git a/html/images/os/allot.png b/html/images/os/allot.png new file mode 100644 index 00000000..36e8982a Binary files /dev/null and b/html/images/os/allot.png differ diff --git a/html/images/os/allot_2x.png b/html/images/os/allot_2x.png new file mode 100644 index 00000000..79786f86 Binary files /dev/null and b/html/images/os/allot_2x.png differ diff --git a/html/images/os/axis-dark.png b/html/images/os/axis-dark.png new file mode 100644 index 00000000..cbc39477 Binary files /dev/null and b/html/images/os/axis-dark.png differ diff --git a/html/images/os/axis-dark_2x.png b/html/images/os/axis-dark_2x.png new file mode 100644 index 00000000..6ba1c221 Binary files /dev/null and b/html/images/os/axis-dark_2x.png differ diff --git a/html/images/os/axis.png b/html/images/os/axis.png index 8a1554e6..7c7bed2b 100644 Binary files a/html/images/os/axis.png and b/html/images/os/axis.png differ diff --git a/html/images/os/axis_2x.png b/html/images/os/axis_2x.png index 225800e7..da94e5a9 100644 Binary files a/html/images/os/axis_2x.png and b/html/images/os/axis_2x.png differ diff --git a/html/images/os/cumulus.png b/html/images/os/cumulus.png index ee2b9185..c1d974cf 100644 Binary files a/html/images/os/cumulus.png and b/html/images/os/cumulus.png differ diff --git a/html/images/os/cumulus_2x.png b/html/images/os/cumulus_2x.png index 48d004c8..4b057fc6 100644 Binary files a/html/images/os/cumulus_2x.png and b/html/images/os/cumulus_2x.png differ diff --git a/html/images/os/genexis.png b/html/images/os/genexis.png new file mode 100644 index 00000000..b4f32131 Binary files /dev/null and b/html/images/os/genexis.png differ diff --git a/html/images/os/genexis_2x.png b/html/images/os/genexis_2x.png new file mode 100644 index 00000000..b43f4dfb Binary files /dev/null and b/html/images/os/genexis_2x.png differ diff --git a/html/images/os/hardenedbsd.png b/html/images/os/hardenedbsd.png new file mode 100644 index 00000000..d8819305 Binary files /dev/null and b/html/images/os/hardenedbsd.png differ diff --git a/html/images/os/hardenedbsd_2x.png b/html/images/os/hardenedbsd_2x.png new file mode 100644 index 00000000..6abf5625 Binary files /dev/null and b/html/images/os/hardenedbsd_2x.png differ diff --git a/html/images/os/lantronix.png b/html/images/os/lantronix.png new file mode 100644 index 00000000..9a9ac986 Binary files /dev/null and b/html/images/os/lantronix.png differ diff --git a/html/images/os/lantronix_2x.png b/html/images/os/lantronix_2x.png new file mode 100644 index 00000000..64f8bd28 Binary files /dev/null and b/html/images/os/lantronix_2x.png differ diff --git a/html/images/os/luve.png b/html/images/os/luve.png new file mode 100644 index 00000000..46d6e1d8 Binary files /dev/null and b/html/images/os/luve.png differ diff --git a/html/images/os/luve_2x.png b/html/images/os/luve_2x.png new file mode 100644 index 00000000..3953e453 Binary files /dev/null and b/html/images/os/luve_2x.png differ diff --git a/html/images/os/monnit.png b/html/images/os/monnit.png new file mode 100644 index 00000000..e5ddbbb7 Binary files /dev/null and b/html/images/os/monnit.png differ diff --git a/html/images/os/monnit_2x.png b/html/images/os/monnit_2x.png new file mode 100644 index 00000000..47e437d1 Binary files /dev/null and b/html/images/os/monnit_2x.png differ diff --git a/html/images/os/powershield.png b/html/images/os/powershield.png new file mode 100644 index 00000000..f04821ad Binary files /dev/null and b/html/images/os/powershield.png differ diff --git a/html/images/os/powershield_2x.png b/html/images/os/powershield_2x.png new file mode 100644 index 00000000..a85b87e7 Binary files /dev/null and b/html/images/os/powershield_2x.png differ diff --git a/html/images/os/powertek-dark.png b/html/images/os/powertek-dark.png new file mode 100644 index 00000000..9b149ace Binary files /dev/null and b/html/images/os/powertek-dark.png differ diff --git a/html/images/os/powertek-dark_2x.png b/html/images/os/powertek-dark_2x.png new file mode 100644 index 00000000..777e8ff9 Binary files /dev/null and b/html/images/os/powertek-dark_2x.png differ diff --git a/html/images/os/powertek.png b/html/images/os/powertek.png new file mode 100644 index 00000000..3d73012d Binary files /dev/null and b/html/images/os/powertek.png differ diff --git a/html/images/os/powertek_2x.png b/html/images/os/powertek_2x.png new file mode 100644 index 00000000..f03efa4d Binary files /dev/null and b/html/images/os/powertek_2x.png differ diff --git a/html/images/os/seagate.png b/html/images/os/seagate.png new file mode 100644 index 00000000..0357b142 Binary files /dev/null and b/html/images/os/seagate.png differ diff --git a/html/images/os/seagate_2x.png b/html/images/os/seagate_2x.png new file mode 100644 index 00000000..64d0eb74 Binary files /dev/null and b/html/images/os/seagate_2x.png differ diff --git a/html/images/os/sigur.png b/html/images/os/sigur.png new file mode 100644 index 00000000..251881e9 Binary files /dev/null and b/html/images/os/sigur.png differ diff --git a/html/images/os/sigur_2x.png b/html/images/os/sigur_2x.png new file mode 100644 index 00000000..1fc75309 Binary files /dev/null and b/html/images/os/sigur_2x.png differ diff --git a/html/images/os/snr.png b/html/images/os/snr.png index 4c9d5117..1bf0de5d 100644 Binary files a/html/images/os/snr.png and b/html/images/os/snr.png differ diff --git a/html/images/os/snr_2x.png b/html/images/os/snr_2x.png index c20ca85a..a0b57349 100644 Binary files a/html/images/os/snr_2x.png and b/html/images/os/snr_2x.png differ diff --git a/html/images/os/tfortis.png b/html/images/os/tfortis.png new file mode 100644 index 00000000..8c04f6cd Binary files /dev/null and b/html/images/os/tfortis.png differ diff --git a/html/images/os/tfortis_2x.png b/html/images/os/tfortis_2x.png new file mode 100644 index 00000000..0ee24920 Binary files /dev/null and b/html/images/os/tfortis_2x.png differ diff --git a/html/images/os/unitrends-dark.png b/html/images/os/unitrends-dark.png new file mode 100644 index 00000000..d9c822bb Binary files /dev/null and b/html/images/os/unitrends-dark.png differ diff --git a/html/images/os/unitrends-dark_2x.png b/html/images/os/unitrends-dark_2x.png new file mode 100644 index 00000000..47fd4049 Binary files /dev/null and b/html/images/os/unitrends-dark_2x.png differ diff --git a/html/images/os/unitrends.png b/html/images/os/unitrends.png new file mode 100644 index 00000000..84572816 Binary files /dev/null and b/html/images/os/unitrends.png differ diff --git a/html/images/os/unitrends_2x.png b/html/images/os/unitrends_2x.png new file mode 100644 index 00000000..d4dfe5c0 Binary files /dev/null and b/html/images/os/unitrends_2x.png differ diff --git a/html/images/os/waveos.png b/html/images/os/waveos.png new file mode 100644 index 00000000..2e0b6571 Binary files /dev/null and b/html/images/os/waveos.png differ diff --git a/html/images/os/waveos_2x.png b/html/images/os/waveos_2x.png new file mode 100644 index 00000000..5358ee6a Binary files /dev/null and b/html/images/os/waveos_2x.png differ diff --git a/html/images/os/wisi.png b/html/images/os/wisi.png new file mode 100644 index 00000000..2d968605 Binary files /dev/null and b/html/images/os/wisi.png differ diff --git a/html/images/os/wisi_2x.png b/html/images/os/wisi_2x.png new file mode 100644 index 00000000..543349b2 Binary files /dev/null and b/html/images/os/wisi_2x.png differ diff --git a/html/images/os/zyxel-dark.png b/html/images/os/zyxel-dark.png new file mode 100644 index 00000000..c09d84b0 Binary files /dev/null and b/html/images/os/zyxel-dark.png differ diff --git a/html/images/os/zyxel-dark_2x.png b/html/images/os/zyxel-dark_2x.png new file mode 100644 index 00000000..e7426b28 Binary files /dev/null and b/html/images/os/zyxel-dark_2x.png differ diff --git a/html/images/os/zyxel.png b/html/images/os/zyxel.png index 003b4fe4..12f5dfc9 100644 Binary files a/html/images/os/zyxel.png and b/html/images/os/zyxel.png differ diff --git a/html/images/os/zyxel_2x.png b/html/images/os/zyxel_2x.png index a62a071b..c5d3bd7a 100644 Binary files a/html/images/os/zyxel_2x.png and b/html/images/os/zyxel_2x.png differ diff --git a/html/img/router.png b/html/img/router.png new file mode 100644 index 00000000..7eb6753d Binary files /dev/null and b/html/img/router.png differ diff --git a/html/includes/actions/role_add.inc.php b/html/includes/actions/role_add.inc.php index 836fc6f4..2a4c9b3c 100644 --- a/html/includes/actions/role_add.inc.php +++ b/html/includes/actions/role_add.inc.php @@ -1,25 +1,28 @@ $vars['role_descr'], - 'role_name' => $vars['role_name']) +if ($_SESSION['userlevel'] == 10 && request_token_valid($vars)) { // Only valid forms from level 10 users + if (!safe_empty($vars['role_name']) && + !safe_empty($vars['role_descr'])) { + $oid_id = dbInsert('roles', [ 'role_descr' => $vars['role_descr'], + 'role_name' => $vars['role_name'] ] ); - if ($oid_id) - { + if ($oid_id) { print_success("SUCCESS: Added role"); - } - else - { + } else { print_warning("WARNING: Role not added"); } - } - else - { + } else { print_error("ERROR: All fields must be completed to add a new role."); } } \ No newline at end of file diff --git a/html/includes/actions/role_entity_add.inc.php b/html/includes/actions/role_entity_add.inc.php index 97ca4d9c..30615e37 100644 --- a/html/includes/actions/role_entity_add.inc.php +++ b/html/includes/actions/role_entity_add.inc.php @@ -6,42 +6,45 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2020 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ -if ($_SESSION['userlevel'] == 10 && request_token_valid($vars)) // Only valid forms from level 10 users -{ +if ($_SESSION['userlevel'] == 10 && request_token_valid($vars)) { // Only valid forms from level 10 users - if (isset($vars['entity_id'])) - { - } // use entity_id - elseif (isset($vars[$vars['entity_type'] . '_entity_id'])) // use type_entity_id - { + if (isset($vars['entity_id'])) { + // use entity_id + } elseif (isset($vars[$vars['entity_type'] . '_entity_id'])) { + // use type_entity_id $vars['entity_id'] = $vars[$vars['entity_type'] . '_entity_id']; } - if (!is_array($vars['entity_id'])) - { - $vars['entity_id'] = array($vars['entity_id']); + + if (!is_array($vars['entity_id'])) { + $vars['entity_id'] = [ $vars['entity_id'] ]; } - foreach ($vars['entity_id'] as $entity_id) - { - if (get_entity_by_id_cache($vars['entity_type'], $entity_id)) // Skip not exist entities - { + $changed = 0; + foreach ($vars['entity_id'] as $entity_id) { + if (get_entity_by_id_cache($vars['entity_type'], $entity_id)) { // Skip not exist entities if (!dbExist('roles_entity_permissions', '`role_id` = ? AND `entity_type` = ? AND `entity_id` = ?', - array($vars['role_id'], $vars['entity_type'], $entity_id) - )) - { + [ $vars['role_id'], $vars['entity_type'], $entity_id ])) { - if(!in_array($vars['access'], array('ro', 'rw'))) { $vars['access'] = 'ro'; } + if (!in_array($vars['access'], [ 'ro', 'rw' ])) { + $vars['access'] = 'ro'; + } - dbInsert(array('entity_id' => $entity_id, 'entity_type' => $vars['entity_type'], 'role_id' => $vars['role_id'], 'access' => $vars['access']), - 'roles_entity_permissions' - ); + dbInsert([ 'entity_id' => $entity_id, 'entity_type' => $vars['entity_type'], 'role_id' => $vars['role_id'], 'access' => $vars['access'] ], + 'roles_entity_permissions'); + $changed++; } - } else { print_error('Error: Invalid Entity.'); } + } else { + print_error('Error: Invalid Entity.'); + } } + + // Reset permissions cache + if ($changed) { set_cache_clear('wui'); } + unset($changed); } // EOF diff --git a/html/includes/actions/role_entity_del.inc.php b/html/includes/actions/role_entity_del.inc.php index a1c3b32d..9a5c5060 100644 --- a/html/includes/actions/role_entity_del.inc.php +++ b/html/includes/actions/role_entity_del.inc.php @@ -6,32 +6,31 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2020 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ -if ($_SESSION['userlevel'] == 10 && request_token_valid($vars)) // Only valid forms from level 10 users -{ +if ($_SESSION['userlevel'] == 10 && request_token_valid($vars)) { // Only valid forms from level 10 users - if (isset($vars['entity_id'])) - { - } // use entity_id - elseif (isset($vars[$vars['entity_type'] . '_entity_id'])) // use type_entity_id - { + if (isset($vars['entity_id'])) { + // use entity_id + } elseif (isset($vars[$vars['entity_type'] . '_entity_id'])) { + // use type_entity_id $vars['entity_id'] = $vars[$vars['entity_type'] . '_entity_id']; } - $where = '`role_id` = ? AND `entity_type` = ?' . generate_query_values($vars['entity_id'], 'entity_id'); + $where = '`role_id` = ? AND `entity_type` = ?' . generate_query_values_and($vars['entity_id'], 'entity_id'); //if (@dbFetchCell("SELECT COUNT(*) FROM `entity_permissions` WHERE " . $where, array($vars['user_id'], $vars['entity_type']))) - if (dbExist('roles_entity_permissions', $where, array($vars['role_id'], $vars['entity_type']))) - { + if (dbExist('roles_entity_permissions', $where, [ $vars['role_id'], $vars['entity_type'] ])) { dbDelete('roles_entity_permissions', $where, array($vars['role_id'], $vars['entity_type'])); //print_vars(dbError()); - } else { } + // Reset permissions cache + set_cache_clear('wui'); + } } -echo ("nope"); // Hrm? +//echo ("nope"); // Hrm? // EOF diff --git a/html/includes/alerting-navbar.inc.php b/html/includes/alerting-navbar.inc.php index e08b4760..a7d57d92 100644 --- a/html/includes/alerting-navbar.inc.php +++ b/html/includes/alerting-navbar.inc.php @@ -6,11 +6,10 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ - /// CONTACTS ACTIONS $readonly = $_SESSION['userlevel'] < 10; @@ -60,7 +59,7 @@ if (!$readonly) $exist_contacts = dbFetchColumn('SELECT `contact_id` FROM `alert_contacts_assoc` WHERE `aca_type` = ? AND `alert_checker_id` = ?', array('alert', $vars['alert_test_id'])); //print_vars($exist_contacts); $sql = "SELECT `contact_id` FROM `alert_contacts` WHERE `contact_disabled` = 0 AND `contact_method` != 'syscontact'" . - generate_query_values($exist_contacts, 'contact_id', '!='); // exclude exist contacts + generate_query_values_and($exist_contacts, 'contact_id', '!='); // exclude exist contacts //print_vars($sql); foreach (dbFetchColumn($sql) as $contact_id) { diff --git a/html/includes/authenticate-functions.inc.php b/html/includes/authenticate-functions.inc.php index ff945a3b..a305f6ed 100644 --- a/html/includes/authenticate-functions.inc.php +++ b/html/includes/authenticate-functions.inc.php @@ -262,4 +262,12 @@ function auth_user_info($username) } } +// Create placeholder user for users logged in via non-MySQL mechanisms to enable user list +function create_mysql_user($username, $userid, $level = '1', $type = 'mysql') +{ + if(isset($username) && isset($userid) && is_numeric($userid)) { + dbInsert(array('username' => $username, 'user_id' => $userid, 'level' => $level, 'type' => $type), 'users'); + } +} + // EOF diff --git a/html/includes/authenticate.inc.php b/html/includes/authenticate.inc.php index be101699..74c52777 100644 --- a/html/includes/authenticate.inc.php +++ b/html/includes/authenticate.inc.php @@ -5,8 +5,8 @@ * This file is part of Observium. * * @package observium - * @subpackage authentication - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @subpackage web + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -23,15 +23,19 @@ define('OBS_AJAX', (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SE $debug_auth = FALSE; // Do not use this debug unless you Observium Developer ;) -if (PHP_VERSION_ID < 70100) -{ +if (PHP_VERSION_ID < 70100) { // Use sha1 to generate the session ID (option removed in php 7.1) // session.sid_length (Number of session ID characters - 22 to 256. // session.sid_bits_per_character (Bits used per character - 4 to 6. @ini_set('session.hash_function', '1'); } + @ini_set('session.referer_check', ''); // This config was causing so much trouble with Chrome -@ini_set('session.name', 'OBSID'); // Session name +if (OBS_API) { + @ini_set('session.name', 'OBSAPI'); // Session name for API +} else { + @ini_set('session.name', 'OBSID'); // Session name for common Web UI +} @ini_set('session.use_cookies', '1'); // Use cookies to store the session id on the client side @ini_set('session.use_only_cookies', '1'); // This prevents attacks involved passing session ids in URLs @ini_set('session.use_trans_sid', '0'); // Disable SID (no session id in url) @@ -48,13 +52,13 @@ $cookie_httponly = FALSE; //$cookie_httponly = TRUE; // Use custom session lifetime -if (is_numeric($GLOBALS['config']['web_session_lifetime']) && $GLOBALS['config']['web_session_lifetime'] >= 0) { +if (is_intnum($GLOBALS['config']['web_session_lifetime']) && $GLOBALS['config']['web_session_lifetime'] >= 0) { $lifetime = (int)$GLOBALS['config']['web_session_lifetime']; } @ini_set('session.gc_maxlifetime', $lifetime); // Session lifetime (for non "remember me" sessions) -if (PHP_VERSION_ID >= 70300) -{ + +if (PHP_VERSION_ID >= 70300) { // Allows servers to assert that a cookie ought not to be sent along with cross-site requests. // Lax will sent the cookie for cross-domain GET requests, while Strict will not //@ini_set('session.cookie_samesite', 'Strict'); @@ -64,7 +68,7 @@ if (PHP_VERSION_ID >= 70300) 'domain' => $cookie_domain, 'secure' => $cookie_https, 'httponly' => $cookie_httponly, - 'samesite' => 'Strict' + 'samesite' => 'Lax' // 'Strict' /// FIXME. Set this configurable? See: https://jira.observium.org/browse/OBS-4214 ]; session_set_cookie_params($cookie_params); } else { @@ -77,28 +81,24 @@ if (!session_is_active()) { session_regenerate(); } -if ($debug_auth && empty($_SESSION['authenticated'])) -{ +if ($debug_auth && empty($_SESSION['authenticated'])) { logfile('debug_auth.log', __LINE__ . " NOT Authenticated!!!. IP=[" . get_remote_addr($config['web_session_ip_by_header']) . "]. URL=[" . $_SERVER['REQUEST_URI'] . "]"); logfile('debug_auth.log', __LINE__ . ' ' . json_encode($_SESSION)); } // Fallback to MySQL auth as default - FIXME do this in sqlconfig file? -if (!isset($config['auth_mechanism'])) -{ +if (!isset($config['auth_mechanism'])) { $config['auth_mechanism'] = "mysql"; } // Trust Apache authenticated user, if configured to do so and username is available -if ($config['auth']['remote_user'] && $_SERVER['REMOTE_USER'] != '') -{ +if ($config['auth']['remote_user'] && is_valid_param($_SERVER['REMOTE_USER'], 'username')) { session_set_var('username', $_SERVER['REMOTE_USER']); } $auth_file = $config['html_dir'].'/includes/authentication/' . $config['auth_mechanism'] . '.inc.php'; if (is_file($auth_file)) { - if (isset($_SESSION['auth_mechanism']) && $_SESSION['auth_mechanism'] != $config['auth_mechanism']) - { + if (isset($_SESSION['auth_mechanism']) && $_SESSION['auth_mechanism'] != $config['auth_mechanism']) { // Logout if AUTH mechanism changed session_logout(); reauth_with_message('Authentication mechanism changed, please log in again!'); @@ -123,14 +123,12 @@ if (is_file($auth_file)) { if ($_SESSION['authenticated'] && str_starts(ltrim($_SERVER['REQUEST_URI'], '/'), 'logout')) { // Do not use $vars and get_vars here! //print_vars($_SERVER['REQUEST_URI']); - if (auth_can_logout()) - { + if (auth_can_logout()) { // No need for a feedback message if user requested a logout session_logout(function_exists('auth_require_login')); $redirect = auth_logout_url(); - if ($redirect) - { + if ($redirect) { redirect_to_url($redirect); exit(); } @@ -144,8 +142,7 @@ $user_unique_id = session_unique_id(); // Get unique user id and check if IP cha // Store logged remote IP with real proxied IP (if configured and available) $remote_addr = get_remote_addr(); $remote_addr_header = get_remote_addr(TRUE); // Remote addr by http header -if ($remote_addr_header && $remote_addr != $remote_addr_header) -{ +if ($remote_addr_header && $remote_addr != $remote_addr_header) { $remote_addr = $remote_addr_header . ' (' . $remote_addr . ')'; } @@ -156,15 +153,16 @@ if (isset($config['web_session_cidr']) && count($config['web_session_cidr'])) { } if (!$_SESSION['authenticated']) { - if (isset($_GET['username']) && isset($_GET['password']) && - is_string($_GET['username']) && is_string($_GET['password'])) { + if (isset($_GET['username'], $_GET['password']) && + is_valid_param($_GET['username'], 'username') && is_valid_param($_GET['password'], 'password')) { + session_set_var('username', $_GET['username']); $auth_password = $_GET['password']; //r($_GET); //r($_SESSION); - } elseif (isset($_POST['username']) && isset($_POST['password']) && - is_string($_POST['username']) && is_string($_POST['password'])) - { + } elseif (isset($_POST['username'], $_POST['password']) && + is_valid_param($_POST['username'], 'username') && is_valid_param($_POST['password'], 'password')) { + session_set_var('username', $_POST['username']); $auth_password = $_POST['password']; } elseif (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) { @@ -256,8 +254,7 @@ if (isset($_SESSION['username'])) { 'user_agent' => $_SERVER['HTTP_USER_AGENT'], 'result' => 'Logged In'), 'authlog'); // Generate keys for cookie auth - if (isset($_POST['remember']) && OBS_ENCRYPT) - { + if (isset($_POST['remember']) && OBS_ENCRYPT) { $ckey = md5(strgen()); $dkey = md5(strgen()); $encpass = encrypt($auth_password, $dkey); @@ -307,28 +304,15 @@ if (isset($_SESSION['username'])) { session_commit(); // Hardcoded level permissions + /// FIXME. It's seems unused?.. - $user_perms = array(); + $user_perms = []; - $perms[0] = []; - $perms[1] = ['LOGIN']; - $perms[2] = []; - $perms[3] = []; - $perms[5] = ['GLOBAL_READ']; - $perms[6] = []; - $perms[7] = []; - $perms[8] = []; - $perms[9] = []; - $perms[10] = ['ADMIN']; - - foreach($perms as $level => $array) - { - if($_SESSION['userlevel'] >= $level) - { - foreach($array AS $entry) { $user_perms[$entry] = $entry; } + foreach ($config['user_level'] as $level => $array) { + if ($_SESSION['userlevel'] >= $level) { + foreach($array['roles'] as $entry) { $user_perms[$entry] = $entry; } } } - //print_vars($user_perms); //print_vars($_SESSION); diff --git a/html/includes/authentication/ldap.inc.php b/html/includes/authentication/ldap.inc.php index 42032d8f..57e5c80e 100644 --- a/html/includes/authentication/ldap.inc.php +++ b/html/includes/authentication/ldap.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage authentication - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -67,7 +67,7 @@ function ldap_search_user($ldap_group, $userdn, $depth = -1) { $ldap_search = ldap_search($ds, trim($config['auth_ldap_groupbase'], ', '), $filter, array($config['auth_ldap_attr']['dn'])); //r($filter); - if (is_resource($ldap_search)) { + if (ldap_internal_is_valid($ldap_search)) { $ldap_results = ldap_get_entries($ds, $ldap_search); //r($ldap_results); @@ -101,30 +101,30 @@ function ldap_search_user($ldap_group, $userdn, $depth = -1) { * Initializes the LDAP connection to the specified server(s). Cycles through all servers, throws error when no server can be reached. * Private function for this LDAP module only. */ -function ldap_init() -{ +function ldap_init() { global $ds, $config; - if (!is_resource($ds)) - { + if (!ldap_internal_is_valid($ds)) { print_debug('LDAP[Connecting to ' . implode(' ',$config['auth_ldap_server']) . ']'); - $ds = @ldap_connect(implode(' ',$config['auth_ldap_server']), $config['auth_ldap_port']); + if ($config['auth_ldap_port'] === 636) { + print_debug('LDAP[Port 636. Prepending ldaps:// to server URI]'); + $ds = @ldap_connect(implode(' ',preg_filter('/^(ldaps:\/\/)?/', 'ldaps://', $config['auth_ldap_server'])), $config['auth_ldap_port']); + } else { + $ds = @ldap_connect(implode(' ',$config['auth_ldap_server']), $config['auth_ldap_port']); + } print_debug("LDAP[Connected]"); if ($config['auth_ldap_starttls'] && - (in_array($config['auth_ldap_starttls'], [ 'optional', 'require', '1', 1, TRUE ], TRUE))) - { + (in_array($config['auth_ldap_starttls'], [ 'optional', 'require', '1', 1, TRUE ], TRUE))) { $tls = ldap_start_tls($ds); - if ($config['auth_ldap_starttls'] === 'require' && !$tls) - { + if ($config['auth_ldap_starttls'] === 'require' && !$tls) { session_logout(); print_error("Fatal error: LDAP TLS required but not successfully negotiated [" . ldap_error($ds) . "]"); exit; } } - if ($config['auth_ldap_referrals']) - { + if ($config['auth_ldap_referrals']) { ldap_set_option($ds, LDAP_OPT_REFERRALS, $config['auth_ldap_referrals']); print_debug("LDAP[Referrals][Set to " . $config['auth_ldap_referrals'] . "]"); } else { @@ -132,8 +132,7 @@ function ldap_init() print_debug("LDAP[Referrals][Disabled]"); } - if ($config['auth_ldap_version']) - { + if ($config['auth_ldap_version']) { ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, $config['auth_ldap_version']); print_debug("LDAP[Version][Set to " . $config['auth_ldap_version'] . "]"); } @@ -385,11 +384,12 @@ function ldap_auth_user_id($username) $filter_params[] = ldap_filter_create('objectClass', $config['auth_ldap_objectclass']); $filter_params[] = ldap_filter_create($config['auth_ldap_attr']['uid'], $username); $filter = ldap_filter_combine($filter_params); - + print_debug("LDAP[Filter][$filter][" . trim($config['auth_ldap_suffix'], ', ') . "]"); $search = ldap_search($ds, trim($config['auth_ldap_suffix'], ', '), $filter); - $entries = is_resource($search) ? ldap_get_entries($ds, $search) : []; - //print_vars($entries); + //r($search); + $entries = ldap_internal_is_valid($search) ? ldap_get_entries($ds, $search) : []; + //r($entries); if ($entries['count']) { @@ -500,7 +500,7 @@ function ldap_auth_user_list($username = NULL) { //$group_filter .= '(memberof='.$group.')'; $group_params[] = ldap_filter_create($config['auth_ldap_attr']['memberOf'], $group); } - + $filter_params[] = ldap_filter_combine($group_params, '|'); //$filter = '(&'.$filter.'(|'.$group_filter.'))'; @@ -566,7 +566,7 @@ function ldap_internal_user_entries($entries, &$userlist) { $compare = ldap_search_user($ldap_group, $userdn); //print_warning("$username, $realname, "); - //print_vars($compare); + //r($compare); if ($compare === -1) { print_debug("LDAP[UserList][Compare LDAP error: " . ldap_error($ds) . "]"); @@ -606,9 +606,9 @@ function ldap_internal_paged_entries($filter, $attributes) do { $search = ldap_search( $ds, trim($config['auth_ldap_suffix'], ', '), $filter, $attributes, 0, 0, 0, LDAP_DEREF_NEVER, - [['oid' => LDAP_CONTROL_PAGEDRESULTS, 'value' => ['size' => $page_size, 'cookie' => $cookie]]] + [['oid' => LDAP_CONTROL_PAGEDRESULTS, 'value' => [ 'size' => $page_size, 'cookie' => $cookie ]]] ); - if (is_resource($search)) { + if (ldap_internal_is_valid($search)) { ldap_parse_result($ds, $search, $errcode, $matcheddn, $errmsg, $referrals, $controls); print_debug(ldap_error($ds)); $entries = array_merge($entries, ldap_get_entries($ds, $search)); @@ -642,7 +642,7 @@ function ldap_internal_paged_entries($filter, $attributes) $search = ldap_search($ds, trim($config['auth_ldap_suffix'], ', '), $filter, $attributes); print_debug(ldap_error($ds)); - if (is_resource($search)) { + if (ldap_internal_is_valid($search)) { $entries = array_merge($entries, ldap_get_entries($ds, $search)); //print_vars($filter); //print_vars($search); @@ -665,7 +665,7 @@ function ldap_internal_paged_entries($filter, $attributes) $search = ldap_search($ds, trim($config['auth_ldap_suffix'], ', '), $filter, $attributes); print_debug(ldap_error($ds)); - if (is_resource($search)) { + if (ldap_internal_is_valid($search)) { $entries = ldap_get_entries($ds, $search); //print_vars($filter); //print_vars($search); @@ -800,6 +800,9 @@ function ldap_bind_dn($username = "", $password = "") */ function ldap_internal_dn_from_username($username) { + + //r(debug_backtrace()); + global $config, $ds, $cache; if (!isset($cache['ldap']['dn'][$username])) @@ -813,7 +816,11 @@ function ldap_internal_dn_from_username($username) print_debug("LDAP[Filter][$filter][" . trim($config['auth_ldap_suffix'], ', ') . "]"); $search = ldap_search($ds, trim($config['auth_ldap_suffix'], ', '), $filter); - if (is_resource($search)) { + + //r($search); + //r(ldap_get_entries($ds, $search)); + + if (ldap_internal_is_valid($search)) { $entries = ldap_get_entries($ds, $search); if ($entries['count']) { @@ -1110,6 +1117,16 @@ function ldap_unescape_filter_value($values = array()) return $values; } +function ldap_internal_is_valid($obj) { + if (PHP_VERSION_ID >= 80100) { + // ldap_bind() returns an LDAP\Connection instance in 8.1; previously, a resource was returned + // ldap_search() returns an LDAP\Result instance in 8.1; previously, a resource was returned. + return is_object($obj); + } + + return is_resource($obj); +} + /** * Converts all ASCII chars < 32 to "\HEX" * diff --git a/html/includes/authentication/mysql.inc.php b/html/includes/authentication/mysql.inc.php index 009599cf..1ed1f5b0 100644 --- a/html/includes/authentication/mysql.inc.php +++ b/html/includes/authentication/mysql.inc.php @@ -1,5 +1,4 @@ $hash), 'users', '`username` = ?', array($username)); // FIXME should return BOOL + return dbUpdate([ 'password' => $hash ], 'users', '`username` = ? AND `type` = ?', [ $username, 'mysql' ]); // FIXME should return BOOL } /** @@ -124,16 +122,22 @@ function mysql_auth_usermanagement() * @param string $description User's description * @return bool TRUE if user addition is successful, FALSE if it is not */ -function mysql_adduser($username, $password, $level, $email = "", $realname = "", $can_modify_passwd='1', $description = "") +function mysql_adduser($username, $password, $level, $email = "", $realname = "", $can_modify_passwd = '1', $description = "") { if (!mysql_auth_user_exists($username)) { // $hash = crypt($password, '$1$' . strgen(8).'$'); // This is old hash, do not used anymore (keep for history) $hash = password_hash($password, PASSWORD_DEFAULT); - return dbInsert(array('username' => $username, 'password' => $hash, 'level' => $level, 'email' => $email, 'realname' => $realname, 'can_modify_passwd' => $can_modify_passwd, 'descr' => $description), 'users'); - } else { - return FALSE; + return dbInsert([ 'username' => $username, + 'password' => $hash, + 'level' => $level, + 'email' => $email, + 'realname' => $realname, + 'can_modify_passwd' => $can_modify_passwd, + 'descr' => $description ], 'users'); } + + return FALSE; } /** @@ -145,7 +149,7 @@ function mysql_adduser($username, $password, $level, $email = "", $realname = "" function mysql_auth_user_exists($username) { //return @dbFetchCell("SELECT COUNT(*) FROM `users` WHERE `username` = ?", array($username)); // FIXME should return BOOL - return dbExist('users', '`username` = ?', array($username)); + return dbExist('users', '`username` = ? AND `type` = ?', [ $username, 'mysql' ]); } /** @@ -156,7 +160,7 @@ function mysql_auth_user_exists($username) */ function mysql_auth_username_by_id($user_id) { - return dbFetchCell("SELECT `username` FROM `users` WHERE `user_id` = ?", array($user_id)); // FIXME should return FALSE if not found + return dbFetchCell("SELECT `username` FROM `users` WHERE `user_id` = ? AND `type` = ?", [ $user_id, 'mysql' ]); // FIXME should return FALSE if not found } /** @@ -167,7 +171,7 @@ function mysql_auth_username_by_id($user_id) */ function mysql_auth_user_level($username) { - return dbFetchCell("SELECT `level` FROM `users` WHERE `username` = ?", array($username)); + return dbFetchCell("SELECT `level` FROM `users` WHERE `username` = ? AND `type` = ?", [ $username, 'mysql' ]); } /** @@ -178,7 +182,7 @@ function mysql_auth_user_level($username) */ function mysql_auth_user_id($username) { - return dbFetchCell("SELECT `user_id` FROM `users` WHERE `username` = ?", array($username)); + return dbFetchCell("SELECT `user_id` FROM `users` WHERE `username` = ? AND `type` = ?", [ $username, 'mysql' ]); } /** @@ -196,7 +200,7 @@ function mysql_deluser($username) dbDelete('users_prefs', "`user_id` = ?", array($user_id)); dbDelete('users_ckeys', "`username` = ?", array($username)); - return dbDelete('users', "`username` = ?", array($username)); // FIXME should return BOOL + return dbDelete('users', "`username` = ? AND `type` = ?", [ $username, 'mysql' ]); // FIXME should return BOOL } /** @@ -206,7 +210,7 @@ function mysql_deluser($username) */ function mysql_auth_user_list() { - return dbFetchRows("SELECT * FROM `users`"); // FIXME hardcode list of returned fields as in all other backends; array content should not depend on db changes/column names. + return dbFetchRows("SELECT * FROM `users` WHERE `type` = ?", [ 'mysql' ]); // FIXME hardcode list of returned fields as in all other backends; array content should not depend on db changes/column names. } /** @@ -217,7 +221,7 @@ function mysql_auth_user_list() */ function mysql_auth_user_info($username) { - return dbFetchRow("SELECT * FROM `users` WHERE `username` = ?", array($username)); + return dbFetchRow("SELECT * FROM `users` WHERE `username` = ? AND `type` = ?", [ $username, 'mysql' ]); } // EOF diff --git a/html/includes/authentication/radius.inc.php b/html/includes/authentication/radius.inc.php index b7d95aac..a087200c 100644 --- a/html/includes/authentication/radius.inc.php +++ b/html/includes/authentication/radius.inc.php @@ -1,5 +1,4 @@ $rad_userlevel, 'user_id' => $user_id ], 'users', '`username` = ? AND `type` = ?', [ $username, 'radius' ]); + } + } return $rad_userlevel; } @@ -324,8 +334,8 @@ function radius_deluser($username) */ function radius_auth_user_list() { - $userlist = array(); - return $userlist; + // Send list of users from MySQL + return dbFetchRows("SELECT * FROM `users` WHERE `type` = ?", [ 'radius' ]); } // EOF diff --git a/html/includes/cache-data.inc.php b/html/includes/cache-data.inc.php index 298925e7..732a711e 100644 --- a/html/includes/cache-data.inc.php +++ b/html/includes/cache-data.inc.php @@ -6,10 +6,11 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2020 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ +$cache_data_start = microtime(TRUE); $cache_item = get_cache_item('data'); //print_vars($cache_item->isHit()); @@ -33,17 +34,22 @@ if (!ishit_cache_item($cache_item)) // This means device_by_id_cache actually never has to do any queries by itself, it'll always get the // cached version when running from the web interface. From the commandline obviously we'll need to fetch // the data per-device. We pre-fetch the graphs list as well, much faster than a query per device obviously. - $graphs_array = dbFetchRows("SELECT * FROM `device_graphs` FORCE INDEX (`graph`) ORDER BY `graph`;"); + //$graphs_array = dbFetchRows("SELECT * FROM `device_graphs` FORCE INDEX (`graph`) ORDER BY `graph`;"); - foreach ($graphs_array as $graph) + $cache['graphs'] = []; + foreach(dbFetchRows("SELECT `graph` FROM `device_graphs` GROUP BY `graph` ORDER BY `graph`;") as $entry) + { + $cache['graphs'][$entry['graph']] = $entry['graph']; + } + + /*foreach ($graphs_array as $graph) { // Cache this per device_id so we can assign it to the correct (cached) device in the for loop below if ($graph['enabled']) { $device_graphs[$graph['device_id']][$graph['graph']] = $graph; } - } - $cache['graphs'] = array(); // All permitted graphs + }*/ // Cache scheduled maintenance currently active $cache['maint'] = cache_alert_maintenance(); @@ -54,16 +60,18 @@ if (!ishit_cache_item($cache_item)) } else { $devices_array = dbFetchRows("SELECT * FROM `devices` ORDER BY `hostname`;"); } + foreach ($devices_array as $device) { if (device_permitted($device['device_id'])) { // Process device and add all the human-readable stuff. - humanize_device($device); + // Very slow on larger systems (3s with 2000 devices) + //humanize_device($device); // Assign device graphs from array created above - $device['graphs'] = (array)$device_graphs[$device['device_id']]; - $cache['graphs'] = array_unique(array_merge($cache['graphs'], array_keys($device['graphs']))); // Add to global array cache + //$device['graphs'] = (array)$device_graphs[$device['device_id']]; + //$cache['graphs'] = array_unique(array_merge($cache['graphs'], array_keys($device['graphs']))); // Add to global array cache $cache['devices']['permitted'][] = (int)$device['device_id']; // Collect IDs for permitted $cache['devices']['hostname'][$device['hostname']] = $device['device_id']; @@ -184,10 +192,10 @@ if (!ishit_cache_item($cache_item)) // Devices disabled if (isset($cache['devices']['disabled']) && count($cache['devices']['disabled']) > 0) { - $cache['ports']['device_disabled'] = dbFetchColumn("SELECT `port_id` FROM `ports` WHERE 1 " . $where_permitted . generate_query_values($cache['devices']['disabled'], 'device_id')); + $cache['ports']['device_disabled'] = dbFetchColumn("SELECT `port_id` FROM `ports` WHERE 1 " . $where_permitted . generate_query_values_and($cache['devices']['disabled'], 'device_id')); if (!$config['web_show_disabled']) { - $where_hide .= generate_query_values($cache['devices']['disabled'], 'device_id', '!='); + $where_hide .= generate_query_values_and($cache['devices']['disabled'], 'device_id', '!='); } } @@ -195,9 +203,9 @@ if (!ishit_cache_item($cache_item)) $where_devices_ignored = ''; if (isset($cache['devices']['ignored']) && count($cache['devices']['ignored']) > 0) { - $cache['ports']['device_ignored'] = dbFetchColumn("SELECT `port_id` FROM `ports` WHERE 1 " . $where_permitted . $where_hide . generate_query_values($cache['devices']['ignored'], 'device_id')); - $where_hide .= generate_query_values($cache['devices']['ignored'], 'device_id', '!='); - $where_devices_ignored = generate_query_values($cache['devices']['ignored'], 'device_id'); + $cache['ports']['device_ignored'] = dbFetchColumn("SELECT `port_id` FROM `ports` WHERE 1 " . $where_permitted . $where_hide . generate_query_values_and($cache['devices']['ignored'], 'device_id')); + $where_hide .= generate_query_values_and($cache['devices']['ignored'], 'device_id', '!='); + $where_devices_ignored = generate_query_values_and($cache['devices']['ignored'], 'device_id'); } $cache['ports']['stat']['device_ignored'] = count($cache['ports']['device_ignored']); @@ -650,6 +658,8 @@ unset($cache_item); //print_vars(get_cache_items('__wui')); //print_vars(get_cache_stats()); +$cache_data_time = microtime(TRUE) - $cache_data_start; + // EOF diff --git a/html/includes/contacts-navbar.inc.php b/html/includes/contacts-navbar.inc.php index be8c9dd7..c5ddc382 100644 --- a/html/includes/contacts-navbar.inc.php +++ b/html/includes/contacts-navbar.inc.php @@ -341,10 +341,10 @@ $("#contact_method").change(function() { } else { $script .= PHP_EOL . " } else if (select === '" . $transport . "') {" . PHP_EOL; } - $script .= " \$('div[id^=\"contact_${transport}_\"]').show();" . PHP_EOL . " "; + $script .= " \$('div[id^=\"contact_{$transport}_\"]').show();" . PHP_EOL . " "; foreach (array_keys($config['transports']) as $ltransport) { if ($transport != $ltransport) { - $script .= " \$('div[id^=\"contact_${ltransport}_\"]').hide();"; + $script .= " \$('div[id^=\"contact_{$ltransport}_\"]').hide();"; } } diff --git a/html/includes/entities/cbqos.inc.php b/html/includes/entities/cbqos.inc.php index 90d595d6..c4b091da 100644 --- a/html/includes/entities/cbqos.inc.php +++ b/html/includes/entities/cbqos.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -28,21 +28,21 @@ function build_cbqos_query($vars) switch ($var) { case "policy_name": case "object_name": - $sql .= generate_query_values($value, $var); + $sql .= generate_query_values_and($value, $var); break; case "group": case "group_id": $values = get_group_entities($value); - $sql .= generate_query_values($values, 'cbqos_id'); + $sql .= generate_query_values_and($values, 'cbqos_id'); break; case 'device_group_id': case 'device_group': $values = get_group_entities($value, 'device'); - $sql .= generate_query_values($values, 'ports_cbqos.device_id'); + $sql .= generate_query_values_and($values, 'ports_cbqos.device_id'); break; case "device": case "device_id": - $sql .= generate_query_values($value, 'ports_cbqos.device_id'); + $sql .= generate_query_values_and($value, 'ports_cbqos.device_id'); break; } } diff --git a/html/includes/entities/counter.inc.php b/html/includes/entities/counter.inc.php index ff13d402..880308c7 100644 --- a/html/includes/entities/counter.inc.php +++ b/html/includes/entities/counter.inc.php @@ -6,14 +6,14 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ /** * Humanize counter. * - * Returns a the $counter array with processed information: + * Returns a $counter array with processed information: * counter_state (TRUE: state counter, FALSE: normal counter) * human_value, counter_symbol, state_name, state_event, state_class * @@ -164,42 +164,42 @@ function build_counter_query($vars, $query_count = FALSE) case "group": case "group_id": $values = get_group_entities($value); - $sql .= generate_query_values($values, 'counters.counter_id'); + $sql .= generate_query_values_and($values, 'counters.counter_id'); break; case 'device_group_id': case 'device_group': $values = get_group_entities($value, 'device'); - $sql .= generate_query_values($values, 'counters.device_id'); + $sql .= generate_query_values_and($values, 'counters.device_id'); break; case "device": case "device_id": - $sql .= generate_query_values($value, 'counters.device_id'); + $sql .= generate_query_values_and($value, 'counters.device_id'); break; case "id": case "counter_id": - $sql .= generate_query_values($value, 'counters.counter_id'); + $sql .= generate_query_values_and($value, 'counters.counter_id'); break; case "entity_id": - $sql .= generate_query_values($value, 'counters.measured_entity'); + $sql .= generate_query_values_and($value, 'counters.measured_entity'); break; case "entity_type": - $sql .= generate_query_values($value, 'counters.measured_class'); + $sql .= generate_query_values_and($value, 'counters.measured_class'); break; case 'entity_state': case "measured_state": - $sql .= build_entity_measured_where('counter', ['measured_state' => $value]); + $sql .= build_entity_measured_where('counter', [ 'measured_state' => $value ]); break; case 'class': case "counter_class": - $sql .= generate_query_values($value, 'counter_class'); + $sql .= generate_query_values_and($value, 'counter_class'); break; case "descr": case "counter_descr": - $sql .= generate_query_values($value, 'counters.counter_descr', '%LIKE%'); + $sql .= generate_query_values_and($value, 'counters.counter_descr', '%LIKE%'); break; case "event": case "counter_event": - $sql .= generate_query_values($value, 'counter_event'); + $sql .= generate_query_values_and($value, 'counter_event'); break; } } @@ -443,7 +443,7 @@ function generate_counter_row($counter, $vars) $counter['counter_class'], $config['counter_types'][$counter['counter_class']]['alt_units']) as $unit => $unit_value) { - if (is_numeric($unit_value)) { $counter_tooltip .= "
${unit_value}${unit}"; } + if (is_numeric($unit_value)) { $counter_tooltip .= "
{$unit_value}{$unit}"; } } } diff --git a/html/includes/entities/device.inc.php b/html/includes/entities/device.inc.php index 6d7d1b7b..08493603 100644 --- a/html/includes/entities/device.inc.php +++ b/html/includes/entities/device.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -14,29 +14,25 @@ * Build devices where array * * This function returns an array of "WHERE" statements from a $vars array. - * The returned array can be implode()d and used on the devices table. + * The returned array can be imploded and used on the devices table. * Originally extracted from the /devices/ page * * @param array $vars * @return array */ -function build_devices_where_array($vars) -{ +function build_devices_where_array($vars) { $where_array = array(); - foreach ($vars as $var => $value) - { - if ($value != '') - { - switch ($var) - { + foreach ($vars as $var => $value) { + if (!safe_empty($value)) { + switch ($var) { case 'group': case 'group_id': $values = get_group_entities($value); - $where_array[$var] = generate_query_values($values, 'device_id'); + $where_array[$var] = generate_query_values_and($values, 'device_id'); break; case 'device': case 'device_id': - $where_array[$var] = generate_query_values($value, 'device_id'); + $where_array[$var] = generate_query_values_and($value, 'device_id'); break; case 'hostname': case 'sysname': @@ -44,13 +40,15 @@ function build_devices_where_array($vars) case 'sysDescr': case 'serial': case 'purpose': - $where_array[$var] = generate_query_values($value, $var, '%LIKE%'); + $condition = str_contains_array($value, [ '*', '?' ]) ? 'LIKE' : '%LIKE%'; + $where_array[$var] = generate_query_values_and($value, $var, $condition); break; case 'location_text': - $where_array[$var] = generate_query_values($value, 'devices.location', '%LIKE%'); + $condition = str_contains_array($value, [ '*', '?' ]) ? 'LIKE' : '%LIKE%'; + $where_array[$var] = generate_query_values_and($value, 'devices.location', $condition); break; case 'location': - $where_array[$var] = generate_query_values($value, 'devices.location'); + $where_array[$var] = generate_query_values_and($value, 'devices.location'); break; case 'location_lat': case 'location_lon': @@ -60,7 +58,7 @@ function build_devices_where_array($vars) case 'location_city': if ($GLOBALS['config']['geocoding']['enable']) { - $where_array[$var] = generate_query_values($value, 'devices_locations.' . $var); + $where_array[$var] = generate_query_values_and($value, 'devices_locations.' . $var); } break; case 'os': @@ -74,10 +72,10 @@ function build_devices_where_array($vars) case 'distro': case 'ignore': case 'disabled': - $where_array[$var] = generate_query_values($value, $var); + $where_array[$var] = generate_query_values_and($value, $var); break; case 'graph': - $where_array[$var] = generate_query_values(devices_with_graph($value), "devices.device_id"); + $where_array[$var] = generate_query_values_and(devices_with_graph($value), "devices.device_id"); } } } @@ -103,7 +101,6 @@ function devices_with_graph($graph) function build_devices_sort($vars) { $order = ''; - $desc_order = isset($vars['sort_desc']) && $vars['sort_desc']; switch ($vars['sort']) { case 'uptime': @@ -112,13 +109,12 @@ function build_devices_sort($vars) case 'features': case 'type': case 'os': + case 'sysName': case 'device_id': $order = ' ORDER BY `devices`.`'.$vars['sort'].'`'; - if ($desc_order) - { - $order .= " DESC"; - } + if ($vars['sort_order'] == "desc") { $order .= " DESC";} break; + case 'domain': // Special order hostnames in Domain Order // SELECT `hostname`, @@ -126,19 +122,18 @@ function build_devices_sort($vars) // SUBSTRING_INDEX(SUBSTRING_INDEX(`hostname`,'.',-2),'.',1) AS `middle`, // SUBSTRING_INDEX(`hostname`,'.',-1) AS `rightmost` // FROM `devices` ORDER by `middle`, `rightmost`, `leftmost`; - if ($desc_order) + if ($vars['sort_order'] == "desc") { $order = ' ORDER BY `middle` DESC, `rightmost` DESC, `leftmost` DESC'; } else { $order = ' ORDER BY `middle`, `rightmost`, `leftmost`'; } break; + + case 'hostname': default: $order = ' ORDER BY `devices`.`hostname`'; - if ($desc_order) - { - $order .= " DESC"; - } + if ($vars['sort_order'] == "desc") { $order .= " DESC"; } break; } return $order; @@ -150,27 +145,9 @@ function print_device_header($device, $args = array()) { if (!is_array($device)) { print_error("Invalid device passed to print_device_header()!"); } - /* FIXME. Unused? - if ($device['status'] == '0') { $class = "div-alert"; } else { $class = "div-normal"; } - if ($device['ignore'] == '1') - { - $class = "div-ignore-alert"; - if ($device['status'] == '1') - { - $class = "div-ignore"; - } - } - - if ($device['disabled'] == '1') - { - $class = "div-disabled"; - } - - $type = strtolower($device['os']); - */ $div_class = 'box box-solid'; if (!safe_empty($args['div-class'])) { - $div_class .= " ${args['div-class']}"; + $div_class .= " " . $args['div-class']; } echo '
@@ -200,12 +177,12 @@ function print_device_header($device, $args = array()) { } $graph_array = []; - $graph_array['height'] = "100"; - $graph_array['width'] = "310"; - $graph_array['to'] = $config['time']['now']; + //$graph_array['height'] = "100"; + //$graph_array['width'] = "310"; + $graph_array['to'] = get_time(); $graph_array['device'] = $device['device_id']; $graph_array['type'] = "device_bits"; - $graph_array['from'] = $config['time']['day']; + $graph_array['from'] = get_time('day'); $graph_array['legend'] = "no"; $graph_array['height'] = "45"; @@ -398,7 +375,7 @@ function print_device_row($device, $vars = array('view' => 'basic'), $link_vars // Preprocess device graphs array $graphs_enabled = []; - foreach ($GLOBALS['cache']['devices']['id'][$device['device_id']]['graphs'] as $graph) + foreach ($device['graphs'] as $graph) { $graphs_enabled[] = $graph['graph']; } @@ -515,50 +492,41 @@ function get_device_icon($device, $base_icon = FALSE, $dark = FALSE) { } // Icon by vendor name - if ($icon === 'generic' && ($config['os'][$device['os']]['vendor'] || $device['vendor'])) - { - if ($device['vendor']) - { + if ($icon === 'generic' && ($config['os'][$device['os']]['vendor'] || $device['vendor'])) { + if ($device['vendor']) { $vendor = $device['vendor']; } else { $vendor = rewrite_vendor($config['os'][$device['os']]['vendor']); // Compatibility, if device not polled for long time } $vendor_safe = safename(strtolower($vendor)); - if (isset($config['vendors'][$vendor_safe]['icon'])) - { + if (isset($config['vendors'][$vendor_safe]['icon'])) { $icon = $config['vendors'][$vendor_safe]['icon']; - } - elseif (is_file($config['html_dir'] . '/images/os/' . $vendor_safe . '.png')) - { + } elseif (is_file($config['html_dir'] . '/images/os/' . $vendor_safe . '.png')) { $icon = $vendor_safe; - } - elseif (isset($config['os'][$device['os']]['icons'])) - { + } elseif (isset($config['os'][$device['os']]['icons'])) { // Fallback to os alternative icon $icon = array_values($config['os'][$device['os']]['icons'])[0]; } } // Set dark mode by session - if (isset($_SESSION['theme'])) - { + if (isset($_SESSION['theme'])) { $dark = str_contains($_SESSION['theme'], 'dark'); } // Prefer dark variant of icon in dark mode - if ($dark && is_file($config['html_dir'] . '/images/os/' . $icon . '-dark.png')) - { + if ($dark && is_file($config['html_dir'] . '/images/os/' . $icon . '-dark.png')) { $icon .= '-dark'; } - if ($base_icon) - { + if ($base_icon) { // return base name for os icon return $icon; } // return image html tag + $base_url = rtrim($config['base_url'], '/'); $srcset = ''; // Now we always have 2x icon variant! //if (is_file($config['html_dir'] . '/images/os/' . $icon . '_2x.png')) // HiDPI image exist? @@ -566,14 +534,13 @@ function get_device_icon($device, $base_icon = FALSE, $dark = FALSE) { // Detect allowed screen ratio for current browser $ua_info = detect_browser(); - if ($ua_info['screen_ratio'] > 1) - { - $srcset = ' srcset="' .$config['base_url'] . '/images/os/' . $icon . '_2x.png'.' 2x"'; + if ($ua_info['screen_ratio'] > 1) { + $srcset = ' srcset="' . $base_url . '/images/os/' . $icon . '_2x.png'.' 2x"'; } //} // Image tag -- FIXME re-engineer this code to do this properly. This is messy. - return ''; + return ''; } // TESTME needs unit testing @@ -638,8 +605,11 @@ function generate_device_popup($device, $vars = []) { } } + $count = 0; foreach ($graphs as $entry) { + if($count == 3) { break; } + if ($entry && in_array(str_replace('device_', '', $entry), $graphs_enabled, TRUE)) { // No text provided for the minigraph, fetch from array if (preg_match(OBS_PATTERN_GRAPH_TYPE, $entry, $graphtype)) { @@ -664,17 +634,13 @@ function generate_device_popup($device, $vars = []) { $content .= '
'; $content .= "

" . $text . "

"; - /* - $content .= generate_box_open(array('title' => $text, - 'body-style' => 'white-space: nowrap;')); - */ $content .= generate_graph_tag($graph_array); - $graph_array['from'] = get_time('week'); $content .= generate_graph_tag($graph_array); - $content .= '
'; - //$content .= generate_box_close(); + + $count++; + } } @@ -722,41 +688,6 @@ function generate_device_link_short($device, $vars = [], $short = TRUE) { return generate_device_link($device, NULL, $vars, TRUE, $short); } -function device_name($device, $max_len = FALSE) { - global $config; - - switch (strtolower($config['web_device_name'])) { - case 'sysname': - $name_field = 'sysName'; - break; - case 'purpose': - case 'descr': - case 'description': - $name_field = 'purpose'; - break; - default: - $name_field = 'hostname'; - } - - if ($max_len && !is_intnum($max_len)) { - $max_len = $config['short_hostname']['length']; - } - - if ($name_field !== 'hostname' && !safe_empty($device[$name_field])) { - if ($name_field === 'sysName' && $max_len && $max_len > 3) { - // short sysname when is valid hostname (do not escape here) - return short_hostname($device[$name_field], $max_len, FALSE); - } - return $device[$name_field]; - } - - if ($max_len && $max_len > 3) { - // short hostname (do not escape here) - return short_hostname($device['hostname'], $max_len, FALSE); - } - return $device['hostname']; -} - function generate_device_form_values($form_filter = FALSE, $column = 'device_id', $options = array()) { global $cache; diff --git a/html/includes/entities/generic.inc.php b/html/includes/entities/generic.inc.php index 78dd5d11..4a3aa353 100644 --- a/html/includes/entities/generic.inc.php +++ b/html/includes/entities/generic.inc.php @@ -54,6 +54,30 @@ function get_customoid_by_id($oid_id) { } // end function get_customoid_by_id() +// DOCME needs phpdoc block +// TESTME needs unit testing +function get_application_by_id($application_id) +{ + if (is_numeric($application_id)) + { + $application = dbFetchRow("SELECT * FROM `applications` WHERE `app_id` = ?", array($application_id)); + } + if (is_array($application)) + { + return $application; + } else { + return FALSE; + } +} + +// DOCME needs phpdoc block +// TESTME needs unit testing +function accesspoint_by_id($ap_id, $refresh = '0') +{ + $ap = dbFetchRow("SELECT * FROM `accesspoints` WHERE `accesspoint_id` = ?", array($ap_id)); + + return $ap; +} function generate_entity_popup_graphs($entity, $vars) { @@ -376,8 +400,8 @@ function build_entity_measured_where($entity_type, $vars) { case 'port': case 'printersupply': - $measure_sql = generate_query_values($measured_type, $column_measured_type, NULL, OBS_DB_NO_LEADING_AND); - $measure_sql .= generate_query_values($entities, $column_measured_id); + $measure_sql = generate_query_values_ng($measured_type, $column_measured_type); + $measure_sql .= generate_query_values_and($entities, $column_measured_id); break; } if ($measure_sql) { $measure_array[] = $measure_sql; } @@ -388,7 +412,7 @@ function build_entity_measured_where($entity_type, $vars) //$value = (array)$value; // Select all without measured entities if (in_array('none', $value)) { - $measure_array[] = generate_query_values(1, $column_measured_id, 'NULL', OBS_DB_NO_LEADING_AND); + $measure_array[] = generate_query_values_ng(1, $column_measured_id); $value = array_diff($value, [ 'none' ]); } if (count($value)) @@ -410,8 +434,8 @@ function build_entity_measured_where($entity_type, $vars) $entities = dbFetchColumn($entity_sql); //$entities = dbFetchColumn($entity_sql, NULL, TRUE); //r($entities); - $measure_sql = generate_query_values($measured_type, $column_measured_type, NULL, OBS_DB_NO_LEADING_AND); - $measure_sql .= generate_query_values($entities, $column_measured_id); + $measure_sql = generate_query_values_ng($measured_type, $column_measured_type); + $measure_sql .= generate_query_values_and($entities, $column_measured_id); break; case 'printersupply': break; diff --git a/html/includes/entities/mempool.inc.php b/html/includes/entities/mempool.inc.php index 993fee43..0dd274f6 100644 --- a/html/includes/entities/mempool.inc.php +++ b/html/includes/entities/mempool.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -32,20 +32,20 @@ function build_mempool_query($vars) case "group": case "group_id": $values = get_group_entities($value); - $sql .= generate_query_values($values, 'mempools.mempool_id'); + $sql .= generate_query_values_and($values, 'mempools.mempool_id'); break; case 'device_group_id': case 'device_group': $values = get_group_entities($value, 'device'); - $sql .= generate_query_values($values, 'mempools.device_id'); + $sql .= generate_query_values_and($values, 'mempools.device_id'); break; case "device": case "device_id": - $sql .= generate_query_values($value, 'mempools.device_id'); + $sql .= generate_query_values_and($value, 'mempools.device_id'); break; case "descr": case "mempool_descr"; - $sql .= generate_query_values($value, 'mempool_descr', '%LIKE%'); + $sql .= generate_query_values_and($value, 'mempool_descr', '%LIKE%'); break; } } diff --git a/html/includes/entities/oid_entry.inc.php b/html/includes/entities/oid_entry.inc.php index 41228af8..194170e8 100644 --- a/html/includes/entities/oid_entry.inc.php +++ b/html/includes/entities/oid_entry.inc.php @@ -6,15 +6,14 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ function generate_oid_template_link($entry) { $url = generate_url(array('page' => 'customoid', 'oid_id' => $entry['oid_id'])); - $link = ''.$entry['oid_descr'].''; - return $link; + return ''.$entry['oid_descr'].''; } function build_oid_query($vars) @@ -33,21 +32,21 @@ function build_oid_query($vars) case "oid_descr": case "oid": case "oid_name": - $sql .= generate_query_values($value, $var); + $sql .= generate_query_values_and($value, $var); break; case "group": case "group_id": $values = get_group_entities($value); - $sql .= generate_query_values($values, 'oid_entry_id'); + $sql .= generate_query_values_and($values, 'oid_entry_id'); break; case 'device_group_id': case 'device_group': $values = get_group_entities($value, 'device'); - $sql .= generate_query_values($values, 'oids_entries.device_id'); + $sql .= generate_query_values_and($values, 'oids_entries.device_id'); break; case "device": case "device_id": - $sql .= generate_query_values($value, 'oids_entries.device_id'); + $sql .= generate_query_values_and($value, 'oids_entries.device_id'); break; } } @@ -97,7 +96,7 @@ function print_oid_table_header($vars, $entries) $cols['event'] = array('Event', 'style="width: 60px;"'); if ($entries[0]['oid_autodiscover'] == '0' && $vars['page'] === "customoid") { - $cols['actions'] = array('', 'style="width: 40px;"'); echo "derp"; + $cols['actions'] = array('', 'style="width: 40px;"'); } echo get_table_header($cols, $vars); @@ -112,7 +111,6 @@ function print_oid_table($vars) $entries = dbFetchRows($sql); $count = count($entries); - if (count($entries)) { echo generate_box_open(); diff --git a/html/includes/entities/p2pradio.inc.php b/html/includes/entities/p2pradio.inc.php index b6dcdb8c..dc1b9da5 100644 --- a/html/includes/entities/p2pradio.inc.php +++ b/html/includes/entities/p2pradio.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -23,16 +23,16 @@ function generate_p2pradio_query($vars) case "group": case "group_id": $values = get_group_entities($value); - $sql .= generate_query_values($values, 'radio_id'); + $sql .= generate_query_values_and($values, 'radio_id'); break; case 'device_group_id': case 'device_group': $values = get_group_entities($value, 'device'); - $sql .= generate_query_values($values, 'p2p_radios.device_id'); + $sql .= generate_query_values_and($values, 'p2p_radios.device_id'); break; case "device": case "device_id": - $sql .= generate_query_values($value, 'device_id'); + $sql .= generate_query_values_and($value, 'device_id'); break; } } diff --git a/html/includes/entities/port.inc.php b/html/includes/entities/port.inc.php index bbbb2818..f91eb7d6 100644 --- a/html/includes/entities/port.inc.php +++ b/html/includes/entities/port.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -14,7 +14,7 @@ * Build ports WHERE array * * This function returns an array of "WHERE" statements from a $vars array. - * The returned array can be implode()d and used on the ports table. + * The returned array can be imploded and used on the ports table. * Originally extracted from the /ports/ page * * @param array $vars @@ -27,20 +27,20 @@ function build_ports_where_array($vars) { if (!safe_empty($value)) { switch ($var) { case 'location': - $where[] = generate_query_values($value, $var); + $where[] = generate_query_values_and($value, $var); break; case 'device_id': - $where[] = generate_query_values($value, 'ports.device_id'); + $where[] = generate_query_values_and($value, 'ports.device_id'); break; case 'group': case 'group_id': $values = get_group_entities($value); - $where[] = generate_query_values($values, 'ports.port_id'); + $where[] = generate_query_values_and($values, 'ports.port_id'); break; case 'device_group_id': case 'device_group': $values = get_group_entities($value, 'device'); - $where[] = generate_query_values($values, 'ports.device_id'); + $where[] = generate_query_values_and($values, 'ports.device_id'); break; case 'disable': $var = 'disabled'; @@ -49,25 +49,26 @@ function build_ports_where_array($vars) { case 'ignore': case 'ifSpeed': case 'ifType': + case 'ifVlan': case 'port_id': - $where[] = generate_query_values($value, 'ports.'.$var); + $where[] = generate_query_values_and($value, 'ports.'.$var); break; case 'hostname': case 'ifAlias': case 'ifDescr': // FIXME, probably better always use port_label instead ifDescr for search - $where[] = generate_query_values($value, $var, '%LIKE%'); + $where[] = generate_query_values_and($value, $var, '%LIKE%'); break; case 'label': case 'port_label': - $where[] = generate_query_values($value, 'port_label', '%LIKE%'); + $where[] = generate_query_values_and($value, 'port_label', '%LIKE%'); break; case 'mac': case 'ifPhysAddress': $value = str_replace([ '.', '-', ':' ], '', $value); - $where[] = generate_query_values($value, 'ifPhysAddress', '%LIKE%'); + $where[] = generate_query_values_and($value, 'ifPhysAddress', '%LIKE%'); break; case 'port_descr_type': - $where[] = generate_query_values($value, $var, 'LIKE'); + $where[] = generate_query_values_and($value, $var, 'LIKE'); break; case 'errors': if (get_var_true($value)) { @@ -88,13 +89,13 @@ function build_ports_where_array($vars) { foreach ((array)$value as $state) { if ($state === "down") { $state_where[] = '`ifAdminStatus` = "up" AND `ifOperStatus` IN ("lowerLayerDown", "down")'; - //$state_where[] = generate_query_values('up', 'ifAdminStatus', NULL, FALSE) . generate_query_values(['down', 'lowerLayerDown'], 'ifOperStatus'); + //$state_where[] = generate_query_values_ng('up', 'ifAdminStatus') . generate_query_values_and(['down', 'lowerLayerDown'], 'ifOperStatus'); } elseif ($state === "up") { $state_where[] = '`ifAdminStatus` = "up" AND `ifOperStatus` IN ("up", "testing", "monitoring")'; - //$state_where[] = generate_query_values('up', 'ifAdminStatus', NULL, FALSE) . generate_query_values(['up', 'testing', 'monitoring'], 'ifOperStatus'); + //$state_where[] = generate_query_values_ng('up', 'ifAdminStatus') . generate_query_values_and(['up', 'testing', 'monitoring'], 'ifOperStatus'); } elseif ($state === "admindown" || $state === "shutdown") { $state_where[] = '`ifAdminStatus` = "down"'; - //$state_where[] = generate_query_values('down', 'ifAdminStatus', NULL, FALSE); + //$state_where[] = generate_query_values_ng('down', 'ifAdminStatus'); } } switch (count($state_where)) { @@ -110,12 +111,12 @@ function build_ports_where_array($vars) { break; case 'cbqos': if ($value && $value !== 'no') { - $where[] = generate_query_values($GLOBALS['cache']['ports']['cbqos'], 'ports.port_id'); + $where[] = generate_query_values_and($GLOBALS['cache']['ports']['cbqos'], 'ports.port_id'); } break; case 'mac_accounting': if ($value && $value !== 'no') { - $where[] = generate_query_values($GLOBALS['cache']['ports']['mac_accounting'], 'ports.port_id'); + $where[] = generate_query_values_and($GLOBALS['cache']['ports']['mac_accounting'], 'ports.port_id'); } break; } @@ -194,24 +195,26 @@ function generate_port_popup($port, $text = NULL, $type = NULL) $content = generate_device_popup_header($port); $content .= generate_port_popup_header($port); - $content .= '
'; - //$content .= generate_box_open(array('body-style' => 'width: 700px;')); - $graph_array['type'] = $port['graph_type']; - $graph_array['legend'] = "yes"; - $graph_array['height'] = "100"; - $graph_array['width'] = "275"; - $graph_array['to'] = $time['now']; - $graph_array['from'] = $time['day']; - $graph_array['id'] = $port['port_id']; - $content .= generate_graph_tag($graph_array); - $graph_array['from'] = $time['week']; - $content .= generate_graph_tag($graph_array); - $graph_array['from'] = $time['month']; - $content .= generate_graph_tag($graph_array); - $graph_array['from'] = $time['year']; - $content .= generate_graph_tag($graph_array); - $content .= "
"; - //$content .= generate_box_close(); + if($type != "none") { + $content .= '
'; + //$content .= generate_box_open(array('body-style' => 'width: 700px;')); + $graph_array['type'] = $port['graph_type']; + $graph_array['legend'] = "yes"; + $graph_array['height'] = "100"; + $graph_array['width'] = "275"; + $graph_array['to'] = $time['now']; + $graph_array['from'] = $time['day']; + $graph_array['id'] = $port['port_id']; + $content .= generate_graph_tag($graph_array); + $graph_array['from'] = $time['week']; + $content .= generate_graph_tag($graph_array); + $graph_array['from'] = $time['month']; + $content .= generate_graph_tag($graph_array); + $graph_array['from'] = $time['year']; + $content .= generate_graph_tag($graph_array); + $content .= "
"; + //$content .= generate_box_close(); + } return $content; } @@ -454,7 +457,7 @@ function generate_port_row($port, $vars = array()) if (!isset($cache['ports_option']['ipv4_addresses']) || in_array($port['port_id'], $cache['ports_option']['ipv4_addresses'])) { $sql = "SELECT * FROM `ipv4_addresses` WHERE `port_id` = ?"; // Do not exclude IPv4 link-local - $sql .= generate_query_values(array_diff($ignore_type, [ 'link-local' ]), 'ipv4_type', '!='); // Do not show ignored ip types + $sql .= generate_query_values_and(array_diff($ignore_type, [ 'link-local' ]), 'ipv4_type', '!='); // Do not show ignored ip types foreach (dbFetchRows($sql, array($port['port_id'])) as $ip) { $string .= $break . generate_popup_link('ip', $ip['ipv4_address'].'/'.$ip['ipv4_prefixlen'], NULL, 'small'); @@ -464,7 +467,7 @@ function generate_port_row($port, $vars = array()) if (!isset($cache['ports_option']['ipv6_addresses']) || in_array($port['port_id'], $cache['ports_option']['ipv6_addresses'])) { $sql = "SELECT * FROM `ipv6_addresses` WHERE `port_id` = ?"; - $sql .= generate_query_values($ignore_type, 'ipv6_type', '!='); // Do not show ignored ip types + $sql .= generate_query_values_and($ignore_type, 'ipv6_type', '!='); // Do not show ignored ip types foreach (dbFetchRows($sql, array($port['port_id'])) as $ip6) { $string .= $break . generate_popup_link('ip', $ip6['ipv6_address'].'/'.$ip6['ipv6_prefixlen'], NULL, 'small'); diff --git a/html/includes/entities/printersupply.inc.php b/html/includes/entities/printersupply.inc.php index 34ed790e..da767f67 100644 --- a/html/includes/entities/printersupply.inc.php +++ b/html/includes/entities/printersupply.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -23,28 +23,28 @@ function build_printersupplies_query($vars) case "group": case "group_id": $values = get_group_entities($value); - $sql .= generate_query_values($values, 'printersupplies.supply_id'); + $sql .= generate_query_values_and($values, 'printersupplies.supply_id'); break; case 'device_group_id': case 'device_group': $values = get_group_entities($value, 'device'); - $sql .= generate_query_values($values, 'printersupplies.device_id'); + $sql .= generate_query_values_and($values, 'printersupplies.device_id'); break; case "device": case "device_id": - $sql .= generate_query_values($value, 'printersupplies.device_id'); + $sql .= generate_query_values_and($value, 'printersupplies.device_id'); break; case "supply": case "supply_type"; - $sql .= generate_query_values($value, 'printersupplies.supply_type'); + $sql .= generate_query_values_and($value, 'printersupplies.supply_type'); break; case "colour": case "supply_colour"; - $sql .= generate_query_values($value, 'supply_colour'); + $sql .= generate_query_values_and($value, 'supply_colour'); break; case "descr": case "supply_descr"; - $sql .= generate_query_values($value, 'supply_descr', '%LIKE%'); + $sql .= generate_query_values_and($value, 'supply_descr', '%LIKE%'); break; } } diff --git a/html/includes/entities/processor.inc.php b/html/includes/entities/processor.inc.php index 284ec001..843e920e 100644 --- a/html/includes/entities/processor.inc.php +++ b/html/includes/entities/processor.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -27,20 +27,20 @@ function generate_processor_query($vars) case "group": case "group_id": $values = get_group_entities($value); - $sql .= generate_query_values($values, 'processor_id'); + $sql .= generate_query_values_and($values, 'processor_id'); break; case 'device_group_id': case 'device_group': $values = get_group_entities($value, 'device'); - $sql .= generate_query_values($values, 'processors.device_id'); + $sql .= generate_query_values_and($values, 'processors.device_id'); break; case "device": case "device_id": - $sql .= generate_query_values($value, 'processors.device_id'); + $sql .= generate_query_values_and($value, 'processors.device_id'); break; case "descr": case "processor_descr"; - $sql .= generate_query_values($value, 'processor_descr', '%LIKE%'); + $sql .= generate_query_values_and($value, 'processor_descr', '%LIKE%'); break; } } diff --git a/html/includes/entities/pseudowire.inc.php b/html/includes/entities/pseudowire.inc.php index a62575ac..ea80ae50 100644 --- a/html/includes/entities/pseudowire.inc.php +++ b/html/includes/entities/pseudowire.inc.php @@ -1,13 +1,12 @@ $value]); + $sql .= build_entity_measured_where('sensor', [ 'measured_state' => $value ]); break; case "metric": // old metric param not allow array @@ -153,19 +153,19 @@ function build_sensor_query($vars, $query_count = FALSE) { } case 'class': case "sensor_class": - $sql .= generate_query_values($value, 'sensor_class'); + $sql .= generate_query_values_and($value, 'sensor_class'); break; case "descr": case "sensor_descr": - $sql .= generate_query_values($value, 'sensors.sensor_descr', '%LIKE%'); + $sql .= generate_query_values_and($value, 'sensors.sensor_descr', '%LIKE%'); break; case "type": case "sensor_type": - $sql .= generate_query_values($value, 'sensor_type', '%LIKE%'); + $sql .= generate_query_values_and($value, 'sensor_type', '%LIKE%'); break; case "event": case "sensor_event": - $sql .= generate_query_values($value, 'sensor_event'); + $sql .= generate_query_values_and($value, 'sensor_event'); break; } } @@ -304,6 +304,126 @@ function print_sensor_table_header($vars) { echo('' . PHP_EOL); } +function generate_sensor_line($sensor, $vars) { + global $config; + + humanize_sensor($sensor); + + $graph_array = []; + $graph_array['to'] = get_time(); + $graph_array['id'] = $sensor['sensor_id']; + $graph_array['type'] = "sensor_graph"; + $graph_array['width'] = 80; + $graph_array['height'] = 20; + $graph_array['bg'] = 'ffffff00'; + $graph_array['from'] = get_time('day'); + $graph_array['style'] = 'margin-top: 5px'; + + if ($sensor['sensor_event'] && is_numeric($sensor['sensor_value'])) { + $mini_graph = generate_graph_tag($graph_array); + } else { + // Do not show "Draw Error" minigraph + $mini_graph = ''; + } + + /* + $sensor_tooltip = $sensor['event_descr']; + // Append value in alternative units to tooltip + if (isset($config['sensor_types'][$sensor['sensor_class']]['alt_units'])) { + foreach (value_to_units($sensor['sensor_value'], + $config['sensor_types'][$sensor['sensor_class']]['symbol'], + $sensor['sensor_class'], + $config['sensor_types'][$sensor['sensor_class']]['alt_units']) as $unit => $unit_value) { + if (is_numeric($unit_value)) { $sensor_tooltip .= "
{$unit_value}{$unit}"; } + } + } + */ + + //r($sensor); + $text = '' . $sensor['human_value'] . $sensor['sensor_symbol'] . ''; + + //$line = ''; + $line = ''; + //$btn_class = str_replace('label', 'btn', $sensor['event_class']); // FIXME Need button-outline-* class from bs4+ + if (get_var_true($vars['compact'])) { + $line .= ''; + $line .= ''; + + //r($line); + return $line; +} + +function get_compact_sensors_line($measured_class, $entry, $vars) { + + // order dom sensors always by temperature, voltage, current, dbm, power + $order = []; + if (safe_count($entry) > 0) { + $classes = array_keys($entry); + //r($types); + if ($measured_class === 'port') { + // always display all classes for dom (also if not exist) + $order = [ 'temperature', 'voltage', 'current', /* 'dbm', 'power' */ ]; + // or dbm or power + if (in_array('dbm', $classes, TRUE)) { + $order[] = 'dbm'; + } elseif (in_array('power', $classes, TRUE)) { + $order[] = 'power'; + } else { + $order[] = 'dbm'; + } + } else { + $order = array_intersect([ 'temperature', 'voltage', 'current', 'dbm', 'power' ], $classes); + } + $order = array_merge($order, array_diff($classes, $order)); + //r($order); + } + $line = ''; + foreach ($order as $class) { + if (!isset($entry[$class])) { + // Add empty columns for port entities (for correct align) + $line .= ''; + } + + foreach ($entry[$class] as $sensor) { + /* + $sensor['sensor_descr'] = trim(str_ireplace($rename_from, '', $sensor['sensor_descr']), ":- \t\n\r\0\x0B"); + if (empty($sensor['sensor_descr'])) { + // Some time sensor descriptions equals to entity name + $sensor['sensor_descr'] = nicecase($sensor['sensor_class']); + } + */ + + // Compact view per entity/lane + $line .= generate_sensor_line($sensor, $vars); + } + } + + return $line; +} + function print_sensor_row($sensor, $vars) { echo generate_sensor_row($sensor, $vars); @@ -404,7 +524,7 @@ function generate_sensor_row($sensor, $vars) $sensor['sensor_class'], $config['sensor_types'][$sensor['sensor_class']]['alt_units']) as $unit => $unit_value) { - if (is_numeric($unit_value)) { $sensor_tooltip .= "
${unit_value}${unit}"; } + if (is_numeric($unit_value)) { $sensor_tooltip .= "
{$unit_value}{$unit}"; } } } diff --git a/html/includes/entities/sla.inc.php b/html/includes/entities/sla.inc.php index 0a6cd1b5..408dc585 100644 --- a/html/includes/entities/sla.inc.php +++ b/html/includes/entities/sla.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2020 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -23,38 +23,38 @@ function generate_sla_query($vars) case "group": case "group_id": $values = get_group_entities($value); - $sql .= generate_query_values($values, 'slas.sla_id'); + $sql .= generate_query_values_and($values, 'slas.sla_id'); break; case 'device_group_id': case 'device_group': $values = get_group_entities($value, 'device'); - $sql .= generate_query_values($values, 'storage.device_id'); + $sql .= generate_query_values_and($values, 'storage.device_id'); break; case "device": case "device_id": - $sql .= generate_query_values($value, 'slas.device_id'); + $sql .= generate_query_values_and($value, 'slas.device_id'); break; case "id": case "sla_id": - $sql .= generate_query_values($value, 'slas.sla_id'); + $sql .= generate_query_values_and($value, 'slas.sla_id'); break; case "owner": - $sql .= generate_query_values($value, 'slas.sla_owner'); + $sql .= generate_query_values_and($value, 'slas.sla_owner'); break; case "target": case "sla_target": - $sql .= generate_query_values($value, 'slas.sla_target', '%LIKE%'); + $sql .= generate_query_values_and($value, 'slas.sla_target', '%LIKE%'); break; case "sla_tag": - $sql .= generate_query_values($value, 'slas.sla_tag'); + $sql .= generate_query_values_and($value, 'slas.sla_tag'); break; case "rtt_type": case "rtt_sense": - $sql .= generate_query_values($value, 'slas.'.$var); + $sql .= generate_query_values_and($value, 'slas.'.$var); break; case "event": case "rtt_event": - $sql .= generate_query_values($value, 'slas.rtt_event'); + $sql .= generate_query_values_and($value, 'slas.rtt_event'); break; } } diff --git a/html/includes/entities/status.inc.php b/html/includes/entities/status.inc.php index fff4f060..b373688d 100644 --- a/html/includes/entities/status.inc.php +++ b/html/includes/entities/status.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -74,26 +74,26 @@ function generate_status_query($vars, $query_count = FALSE) { case "group": case "group_id": $values = get_group_entities($value, 'status'); - $sql .= generate_query_values($values, 'status.status_id'); + $sql .= generate_query_values_and($values, 'status.status_id'); break; case 'device_group_id': case 'device_group': $values = get_group_entities($value, 'device'); - $sql .= generate_query_values($values, 'status.device_id'); + $sql .= generate_query_values_and($values, 'status.device_id'); break; case "device": case "device_id": - $sql .= generate_query_values($value, 'status.device_id'); + $sql .= generate_query_values_and($value, 'status.device_id'); break; case "id": case 'status_id': - $sql .= generate_query_values($value, 'status.status_id'); + $sql .= generate_query_values_and($value, 'status.status_id'); break; case "entity_id": - $sql .= generate_query_values($value, 'measured_entity'); + $sql .= generate_query_values_and($value, 'measured_entity'); break; case "entity_type": - $sql .= generate_query_values($value, 'measured_class'); + $sql .= generate_query_values_and($value, 'measured_class'); break; case 'entity_state': case "measured_state": @@ -101,23 +101,23 @@ function generate_status_query($vars, $query_count = FALSE) { break; case "class": case 'entPhysicalClass': - $sql .= generate_query_values($value, 'entPhysicalClass'); + $sql .= generate_query_values_and($value, 'entPhysicalClass'); break; case "event": case "status_event": - $sql .= generate_query_values($value, 'status_event'); + $sql .= generate_query_values_and($value, 'status_event'); break; case "status": case "status_name": - $sql .= generate_query_values($value, 'status_name'); + $sql .= generate_query_values_and($value, 'status_name'); break; case "descr": case "status_descr": - $sql .= generate_query_values($value, 'status_descr', '%LIKE%'); + $sql .= generate_query_values_and($value, 'status_descr', '%LIKE%'); break; case 'type': case "status_type": - $sql .= generate_query_values($value, 'status_type', '%LIKE%'); + $sql .= generate_query_values_and($value, 'status_type', '%LIKE%'); break; } } @@ -323,7 +323,7 @@ function generate_status_row($status, $vars) { $row .= '' . generate_entity_link('status', $status, $mini_graph, NULL, FALSE) . ''; if ($vars['tab'] !== "overview") { - $row .= '' . generate_tooltip_link('', format_uptime((get_time() - $status['status_last_change']), 'short-2') . ' ago', format_unixtime($status['status_last_change'])) . ' + $row .= '' . generate_tooltip_time($status['status_last_change'], 'ago') . ' ' . generate_tooltip_link('', $status['status_event'], $status['event_descr'], $status['event_class']) . ''; $table_cols++; $table_cols++; diff --git a/html/includes/entities/storage.inc.php b/html/includes/entities/storage.inc.php index 8c5aa73c..5621acbc 100644 --- a/html/includes/entities/storage.inc.php +++ b/html/includes/entities/storage.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -30,23 +30,23 @@ function generate_storage_query($vars) case "group": case "group_id": $values = get_group_entities($value); - $sql .= generate_query_values($values, 'storage.storage_id'); + $sql .= generate_query_values_and($values, 'storage.storage_id'); break; case 'device_group_id': case 'device_group': $values = get_group_entities($value, 'device'); - $sql .= generate_query_values($values, 'storage.device_id'); + $sql .= generate_query_values_and($values, 'storage.device_id'); break; case "device": case "device_id": - $sql .= generate_query_values($value, 'storage.device_id'); + $sql .= generate_query_values_and($value, 'storage.device_id'); break; case "descr": case "storage_descr"; - $sql .= generate_query_values($value, 'storage_descr', '%LIKE%'); + $sql .= generate_query_values_and($value, 'storage_descr', '%LIKE%'); break; case 'ignored': - $sql .= generate_query_values($value, 'storage.storage_ignore'); + $sql .= generate_query_values_and($value, 'storage.storage_ignore'); break; } } @@ -92,8 +92,7 @@ function generate_storage_query($vars) } -function print_storage_table($vars) -{ +function print_storage_table($vars) { global $cache, $config; @@ -101,13 +100,16 @@ function print_storage_table($vars) $sql = generate_storage_query($vars); - $storages = array(); + $storages = []; foreach (dbFetchRows($sql) as $storage) { if (isset($cache['devices']['id'][$storage['device_id']])) { $storage['hostname'] = $cache['devices']['id'][$storage['device_id']]['hostname']; $storage['html_row_class'] = $cache['devices']['id'][$storage['device_id']]['html_row_class']; + + // FIXME. Should be part of humanize_storage() + $storage['human_type'] = array_preg_replace($config['rewrites']['storage_type_regexp'], $storage['storage_type']); $storages[] = $storage; } } @@ -152,19 +154,19 @@ function print_storage_table_header($vars) } echo('' . PHP_EOL); - $cols = array( - array(NULL, 'class="state-marker"'), - 'device' => array('Device', 'style="width: 250px;"'), - 'mountpoint' => array('Mountpoint'), - 'size' => array('Size', 'style="width: 100px;"'), - 'used' => array('Used', 'style="width: 100px;"'), - 'free' => array('Free', 'style="width: 100px;"'), - array('', 'style="width: 100px;"'), - 'usage' => array('Usage %', 'style="width: 200px;"'), - ); + $cols = [ + [ NULL, 'class="state-marker"' ], + 'device' => [ 'Device', 'style="width: 250px;"' ], + 'mountpoint' => [ 'Mountpoint' ], + 'fstype' => [ 'FS Type', 'style="width: 90px;"' ], + 'size' => [ 'Size', 'style="width: 100px;"' ], + 'used' => [ 'Used', 'style="width: 100px;"' ], + 'free' => [ 'Free', 'style="width: 100px;"' ], + [ '', 'style="width: 100px;"' ], + 'usage' => [ 'Usage %', 'style="width: 200px;"' ], + ]; - if ($vars['page'] === "device") - { + if ($vars['page'] === "device") { unset($cols['device']); } @@ -182,10 +184,10 @@ function generate_storage_row($storage, $vars) { global $config; - $table_cols = 8; + $table_cols = 9; if ($vars['page'] !== "device" && $vars['popup'] != TRUE) { $table_cols++; } // Add a column for device. - if(isset($vars['graph_type']) && $vars['graph_type'] == "perc") + if(isset($vars['graph_type']) && $vars['graph_type'] === "perc") $graph_array = array(); $graph_array['to'] = $config['time']['now']; @@ -225,6 +227,7 @@ function generate_storage_row($storage, $vars) { if ($vars['page'] !== "device" && $vars['popup'] != TRUE) { $row .= ''; } $row .= ' + diff --git a/html/includes/entities/virtualmachine.inc.php b/html/includes/entities/virtualmachine.inc.php index fb1aff92..a7c4f567 100644 --- a/html/includes/entities/virtualmachine.inc.php +++ b/html/includes/entities/virtualmachine.inc.php @@ -1,13 +1,12 @@ < / s c r i p t > // javascript:alert("Hello world");/ // + //
' . PHP_EOL . '
' . PHP_EOL . @@ -744,32 +735,23 @@ function pagination(&$vars, $total, $return_vars = FALSE) '
' . PHP_EOL . '
"; //$values = array('' => array('name')) - foreach ($pagesizes as $pagesize) - { - $value = generate_url($vars, array('pagesize' => $pagesize, 'pageno' => floor($start / $pagesize))); - $name = ($pagesize == $GLOBALS['config']['web_pagesize'] ? "[ $pagesize ]" : $pagesize); - $values[$value] = array('name' => $name, 'class' => 'text-center'); + foreach ($pagesizes as $pagesize) { + $value = generate_url($vars, [ 'pagesize' => $pagesize, 'pageno' => floor(fdiv($start, $pagesize)) ]); + $name = $pagesize == $GLOBALS['config']['web_pagesize'] ? "[ $pagesize ]" : $pagesize; + $values[$value] = [ 'name' => $name, 'class' => 'text-center' ]; } - $element = array('type' => 'select', - 'class' => 'pagination', - 'id' => 'pagesize', - 'name' => '# '.$per_page, - 'width' => '90px', - 'onchange' => "window.open(this.options[this.selectedIndex].value,'_top')", - 'value' => $per_page, - 'data-style' => 'box', - 'values' => $values); + $element = [ + 'type' => 'select', + 'class' => 'pagination', + 'id' => 'pagesize', + 'name' => '# '.$per_page, + 'width' => '90px', + 'onchange' => "window.open(this.options[this.selectedIndex].value,'_top')", + 'value' => $per_page, + 'data-style' => 'box', + 'values' => $values + ]; $pagination.= '
@@ -1130,6 +1104,28 @@ function generate_popup_link($type, $text = NULL, $vars = array(), $class = NULL return ''.$text.''; } +function generate_tooltip_time($timestamp, $text = '') { + if (is_numeric($timestamp) && $timestamp > OBS_MIN_UNIXTIME) { + // Unixtime + $timediff = get_time() - $timestamp; + $timetext = format_uptime($timediff, "short-3"); + if (!safe_empty($text)) { + $timetext .= " $text"; + } + + return generate_tooltip_link('', $timetext, format_unixtime($timestamp), NULL); + } + + // Timestamp + $timediff = get_time() - strtotime($timestamp); + $timetext = format_uptime($timediff, "short-3"); + if (!safe_empty($text)) { + $timetext .= " $text"; + } + + return generate_tooltip_link('', $timetext, format_timestamp($timestamp), NULL); +} + /** * Generate mouseover links with static tooltip from URL, link text, contents and a class. * @@ -1146,21 +1142,19 @@ function generate_popup_link($type, $text = NULL, $vars = array(), $class = NULL * @return string */ // TESTME needs unit testing -function generate_tooltip_link($url, $text, $contents = '', $class = NULL, $attribs = [], $escape = FALSE) -{ +function generate_tooltip_link($url, $text, $contents = '', $class = NULL, $attribs = [], $escape = FALSE) { global $config, $link_iter; $link_iter++; - $href = (strlen($url) ? 'href="' . $url . '"' : ''); + $href = !safe_empty($url) ? 'href="' . $url . '"' : ''; if ($escape) { $text = escape_html($text); } $attribs['class'] = array_merge((array)$class, (array)$attribs['class']); // Allow the Grinch to disable popups and destroy Christmas. - $allow_mobile = (in_array(detect_browser_type(), array('mobile', 'tablet')) ? $config['web_mouseover_mobile'] : TRUE); - if ($config['web_mouseover'] && strlen($contents) && $allow_mobile) - { + $allow_mobile = !in_array(detect_browser_type(), [ 'mobile', 'tablet' ]) || $config['web_mouseover_mobile']; + if ($config['web_mouseover'] && $allow_mobile && !safe_empty($contents)) { $attribs['style'] = 'cursor: pointer;'; $attribs['data-rel'] = 'tooltip'; $attribs['data-tooltip'] = $contents; @@ -1387,26 +1381,29 @@ function print_graph_popup($graph_array) // TESTME needs unit testing // DOCME needs phpdoc block -function permissions_cache($user_id) -{ - $permissions = array(); +function permissions_cache($user_id) { + + $cache_key = 'permissions_'.$GLOBALS['config']['auth_mechanism'].$user_id; + $cache_item = get_cache_item($cache_key); + if (ishit_cache_item($cache_item)) { + return get_cache_data($cache_item); + } + + $permissions = []; // Get permissions from user-specific and role tables. $permission_where = '`user_id` = ? AND `auth_mechanism` = ?'; $permission_params = [ $user_id, $GLOBALS['config']['auth_mechanism'] ]; $entity_permissions = dbFetchRows("SELECT * FROM `entity_permissions` WHERE " . $permission_where, $permission_params); $roles_entity_permissions = dbFetchRows("SELECT * FROM `roles_entity_permissions` LEFT JOIN `roles_users` USING (`role_id`) WHERE " . $permission_where, $permission_params); - foreach (array_merge((array)$entity_permissions, (array)$roles_entity_permissions) as $entity) - { + foreach (array_merge((array)$entity_permissions, (array)$roles_entity_permissions) as $entity) { // Set access to ro if it's not in the defined list. $access = (in_array($entity['access'], array('ro', 'rw')) ? $entity['access'] : 'ro'); - switch ($entity['entity_type']) - { + switch ($entity['entity_type']) { case "group": // this is a group, so expand its members into an array $group = get_group_by_id($entity['entity_id']); - foreach (get_group_entities($entity['entity_id']) as $group_entity_id) - { + foreach (get_group_entities($entity['entity_id']) as $group_entity_id) { $permissions[$group['entity_type']][$group_entity_id] = $access; } //break; // And also store self group permission in cache @@ -1425,20 +1422,22 @@ function permissions_cache($user_id) // Alerts // FIXME - this seems like it would be slow on very large installs - $alert = array(); - foreach (dbFetchRows('SELECT `alert_table_id`, `device_id`, `entity_id`, `entity_type` FROM `alert_table`') as $alert_table_entry) - { + $alert = []; + foreach (dbFetchRows('SELECT `alert_table_id`, `device_id`, `entity_id`, `entity_type` FROM `alert_table`') as $alert_table_entry) { //r($alert_table_entry); - if (is_entity_permitted($alert_table_entry['entity_id'], $alert_table_entry['entity_type'], $alert_table_entry['device_id'], $permissions)) - { + if (is_entity_permitted($alert_table_entry['entity_id'], $alert_table_entry['entity_type'], $alert_table_entry['device_id'], $permissions)) { $alert[$alert_table_entry['alert_table_id']] = TRUE; } } - if (count($alert)) - { + if (count($alert)) { $permissions['alert'] = $alert; } + set_cache_item($cache_item, $permissions); + + // Clear expired cache + del_cache_expired(); + return $permissions; } @@ -1882,11 +1881,11 @@ function get_locations($filter = array()) { case 'location_city': // Check geo params only when GEO enabled globally if ($GLOBALS['config']['geocoding']['enable']) { - $where_array[$var] = generate_query_values($value, $var); + $where_array[$var] = generate_query_values_and($value, $var); } break; case 'location': - $where_array[$var] = generate_query_values($value, $var); + $where_array[$var] = generate_query_values_and($value, $var); break; } } @@ -2209,13 +2208,16 @@ function generate_query_permitted($type_array = [ 'device' ], $options = []) { if (!isset($options['port_null']) || !$options['port_null']) { //$query_permitted[] = "($column != '' AND $column IS NOT NULL)"; $query_permitted[] = "$column IS NOT NULL"; - } elseif (!$user_limited) { + } elseif (!$user_limited && safe_count($query_permitted)) { // FIXME. derp code, need rewrite - $query_permitted[] = safe_count($query_permitted) ? "OR $column IS NULL" : "$column IS NULL"; + //$query_permitted[] = safe_count($query_permitted) ? "OR $column IS NULL" : "$column IS NULL"; + $query_permitted[] = "OR $column IS NULL"; } $query_permitted = implode(" AND ", (array)$query_permitted); - $query_part[] = str_replace(" AND OR ", ' OR ', $query_permitted); + if (!safe_empty($query_permitted)) { + $query_part[] = str_replace(" AND OR ", ' OR ', $query_permitted); + } unset($query_permitted); break; @@ -2384,7 +2386,7 @@ function load_user_config(&$load_config, $user_id) { if (!isset($config_variable[$item['pref']]['useredit']) || !$config_variable[$item['pref']]['useredit']) { // Load only permitted settings - print_debug("User [$user_id] setting '${item['pref']}' not permitted by definitions."); + print_debug("User [$user_id] setting '{$item['pref']}' not permitted by definitions."); continue; } @@ -2628,11 +2630,10 @@ function get_smokeping_files($rdebug = 0) if ($rdebug) { echo('- Recursing through ' . $config['smokeping']['dir'] . '
'); } - if (isset($config['smokeping']['master_hostname'])) - { + if (isset($config['smokeping']['master_hostname'])) { $master_hostname = $config['smokeping']['master_hostname']; } else { - $master_hostname = $config['own_hostname']; + $master_hostname = $config['own_hostname'] ?: get_localhost(); } if (is_dir($config['smokeping']['dir'])) diff --git a/html/includes/graphs/bgp/auth.inc.php b/html/includes/graphs/bgp/auth.inc.php index 4e51557a..9f803839 100644 --- a/html/includes/graphs/bgp/auth.inc.php +++ b/html/includes/graphs/bgp/auth.inc.php @@ -1,5 +1,4 @@ $rrd_filename, 'descr' => $port['hostname'] ."-". $port['ifDescr'], 'descr_in' => device_name($port, TRUE), - 'descr_out' => short_ifname($port['ifDescr'], NULL, FALSE) ]; // Options sets for skip htmlentities + 'descr_out' => short_ifname($port['port_label'], NULL, FALSE) ]; // Options sets for skip htmlentities } } diff --git a/html/includes/graphs/device/bits.inc.php b/html/includes/graphs/device/bits.inc.php index 4ea8cd34..123c0911 100644 --- a/html/includes/graphs/device/bits.inc.php +++ b/html/includes/graphs/device/bits.inc.php @@ -15,7 +15,7 @@ $ds_in = "INOCTETS"; $ds_out = "OUTOCTETS"; -$graph_return = array('descr' => 'Device total traffic in bits/sec.'); +$graph_return['descr'] = 'Device total traffic in bits/sec.'; // init $i = 0; diff --git a/html/includes/graphs/device/processor.inc.php b/html/includes/graphs/device/processor.inc.php index 225a0cac..0660ca58 100644 --- a/html/includes/graphs/device/processor.inc.php +++ b/html/includes/graphs/device/processor.inc.php @@ -1,5 +1,4 @@ +// EOF diff --git a/html/includes/graphs/device/storage.inc.php b/html/includes/graphs/device/storage.inc.php index 243fd0c9..986b5d6a 100644 --- a/html/includes/graphs/device/storage.inc.php +++ b/html/includes/graphs/device/storage.inc.php @@ -15,18 +15,22 @@ $scale_max = "100"; include_once($config['html_dir']."/includes/graphs/common.inc.php"); -if($width > 500) +if($width > 350) { - $descr_len = 22; + $padding = 45; + $text_width = 7; } else { - $descr_len = 12; + $padding = 39; + $text_width = 6; } -$descr_len += round(($width - 250) / 8); +$legend_len = ($vars['width'] + $padding) / $text_width; +$descr_len = $legend_len - 31; $iter = 0; $colours = 'mixed-10c'; -$rrd_options .= " COMMENT:'".str_pad('Size Used %used', $descr_len+31, ' ', STR_PAD_LEFT)."\\l'"; -//$rrd_options .= " COMMENT:' Size Used %age\\l'"; +$rrd_options .= " COMMENT:'".str_pad('Size Used % Used', $legend_len, ' ', STR_PAD_LEFT)."\\l'"; +$graph_return['legend_lines'] = 1; + foreach (dbFetchRows("SELECT * FROM storage where device_id = ?", array($device['device_id'])) as $storage) { @@ -47,7 +51,14 @@ foreach (dbFetchRows("SELECT * FROM storage where device_id = ?", array($device[ $rrd_options .= " GPRINT:".$storage['storage_id']."used:LAST:%6.2lf%sB"; $rrd_options .= " GPRINT:".$storage['storage_id']."perc:LAST:%5.2lf%%\\l"; $iter++; + $graph_return['legend_lines']++; + $graph_return['rrds'][] = $rrd; + } else { + $graph_return['missing_rrds'][] = $rrd; } } + + + // EOF diff --git a/html/includes/graphs/generic_data.inc.php b/html/includes/graphs/generic_data.inc.php index 1a9d7669..9bf03737 100644 --- a/html/includes/graphs/generic_data.inc.php +++ b/html/includes/graphs/generic_data.inc.php @@ -1,5 +1,4 @@ $ds) $cmd_def .= " CDEF:".$ds_name."_max=".$ds_name; } + //$graph_return['rrds'][$ds['file']][] = $ds_name; + if (!empty($ds['cdef'])) { $ds_name = $ds_name."_c"; @@ -217,6 +225,7 @@ foreach ($graph_def['ds'] as $ds_name => $ds) } } $cmd_graph .= " COMMENT:'\\l'"; + $graph_return['legend_lines']++; if ($ds['line']) { if (is_numeric($ds['line'])) { diff --git a/html/includes/graphs/generic_duplex.inc.php b/html/includes/graphs/generic_duplex.inc.php index 66dbaca8..26db2629 100644 --- a/html/includes/graphs/generic_duplex.inc.php +++ b/html/includes/graphs/generic_duplex.inc.php @@ -184,7 +184,7 @@ $rrd_options .= " HRULE:0#999999"; // $midnight = strtotime('today midnight'); // for ($i = 1; $i <= 2; $i++) // { -// $rrd_options .= " VRULE:${midnight}#FF0000"; +// $rrd_options .= " VRULE:{$midnight}#FF0000"; // $midnight -= 86400; // } //} diff --git a/html/includes/graphs/generic_multi_bits.inc.php b/html/includes/graphs/generic_multi_bits.inc.php index ea65aaba..5d186bff 100644 --- a/html/includes/graphs/generic_multi_bits.inc.php +++ b/html/includes/graphs/generic_multi_bits.inc.php @@ -117,7 +117,7 @@ if ($i) if ($vars['previous'] == "yes") { - $rrd_options .= " AREA:inbitsX#9999966:"; + $rrd_options .= " AREA:inbitsX#99999966:"; $rrd_options .= " AREA:doutbitsX#99999966:"; } diff --git a/html/includes/graphs/generic_multi_separated.inc.php b/html/includes/graphs/generic_multi_separated.inc.php index 5780339f..672d0324 100644 --- a/html/includes/graphs/generic_multi_separated.inc.php +++ b/html/includes/graphs/generic_multi_separated.inc.php @@ -16,6 +16,8 @@ $graph_return['valid_options'][] = "previous"; $graph_return['valid_options'][] = "total"; $graph_return['valid_options'][] = "trend"; +$graph_return['legend_lines'] = 0; + // Here we scale the number of numerical columns shown to make sure we keep the text. if ($width > 600) { @@ -74,6 +76,9 @@ if ($legend != 'no') if (in_array("max", $data_show)) { $rrd_options .= " COMMENT:' Max'"; } if (in_array("tot", $data_show)) { $rrd_options .= " COMMENT:' Total'"; } $rrd_options .= " COMMENT:'\\l'"; + + $graph_return['legend_lines']++; + } $i = 0; @@ -150,18 +155,20 @@ foreach ($rrd_list as $rrd) if (in_array("min", $data_show)) { $rrd_options .= " GPRINT:inbits".$i.":MIN:%6.2lf%s"; } if (in_array("max", $data_show)) { $rrd_options .= " GPRINT:inbits".$i.":MAX:%6.2lf%s"; } if (in_array("tot", $data_show)) { $rrd_options .= " GPRINT:totinB".$i.":%6.2lf%s".$total_units; } - $rrd_options .= " COMMENT:'\\l'"; + $graph_return['legend_lines']++; + + $rrd_optionsb .= " AREA:outbits".$i."_neg#" . $colour_out . ":".$stack; $rrd_options .= " HRULE:999999999999999#" . $colour_out . ":'" . rrdtool_escape($rrd['descr_out'], $descr_len - 3) . " Tx'"; - if (in_array("lst", $data_show)) { $rrd_options .= " GPRINT:outbits".$i.":LAST:%6.2lf%s"; } if (in_array("avg", $data_show)) { $rrd_options .= " GPRINT:outbits".$i.":AVERAGE:%6.2lf%s"; } if (in_array("min", $data_show)) { $rrd_options .= " GPRINT:outbits".$i.":MIN:%6.2lf%s"; } if (in_array("max", $data_show)) { $rrd_options .= " GPRINT:outbits".$i.":MAX:%6.2lf%s"; } if (in_array("tot", $data_show)) { $rrd_options .= " GPRINT:totoutB".$i.":%6.2lf%s".$total_units; } - $rrd_options .= " COMMENT:'\\l'"; + $graph_return['legend_lines']++; + $i++; $iter++; } @@ -208,6 +215,7 @@ if (in_array("tot", $data_show)) $rrd_options .= " VDEF:tot=octets,TOTAL"; $rrd_options .= " COMMENT:' \\l'"; + $graph_return['legend_lines']++; $rrd_options .= " HRULE:999999999999999#FFFFFF:'" . rrdtool_escape("Total", $descr_len - 3) . " Rx'"; if (in_array("lst", $data_show)) { $rrd_options .= " GPRINT:inbits:LAST:%6.2lf%s"; } @@ -216,6 +224,7 @@ if (in_array("tot", $data_show)) if (in_array("max", $data_show)) { $rrd_options .= " GPRINT:inbits:MAX:%6.2lf%s"; } if (in_array("tot", $data_show)) { $rrd_options .= " GPRINT:totin:%6.2lf%s".$total_units; } $rrd_options .= " COMMENT:'\\l'"; + $graph_return['legend_lines']++; $rrd_options .= " HRULE:999999999999999#FFFFFF:'" . rrdtool_escape("", $descr_len - 3) . " Tx'"; if (in_array("lst", $data_show)) { $rrd_options .= " GPRINT:outbits:LAST:%6.2lf%s"; } @@ -224,6 +233,7 @@ if (in_array("tot", $data_show)) if (in_array("max", $data_show)) { $rrd_options .= " GPRINT:outbits:MAX:%6.2lf%s"; } if (in_array("tot", $data_show)) { $rrd_options .= " GPRINT:totout:%6.2lf%s".$total_units; } $rrd_options .= " COMMENT:'\\l'"; + $graph_return['legend_lines']++; $rrd_options .= " HRULE:999999999999999#FFFFFF:'" . rrdtool_escape("", $descr_len - 4) . " Agg'"; if (in_array("lst", $data_show)) { $rrd_options .= " GPRINT:bits:LAST:%6.2lf%s"; } @@ -232,6 +242,7 @@ if (in_array("tot", $data_show)) if (in_array("max", $data_show)) { $rrd_options .= " GPRINT:bits:MAX:%6.2lf%s"; } if (in_array("tot", $data_show)) { $rrd_options .= " GPRINT:tot:%6.2lf%s".$total_units; } $rrd_options .= " COMMENT:'\\l'"; + $graph_return['legend_lines']++; if ($vars['trend']) { @@ -251,6 +262,7 @@ if (in_array("tot", $data_show) && $vars['previous'] == "yes") $rrd_options .= " VDEF:totoutX=outBX,TOTAL"; $rrd_options .= " VDEF:totX=octetsX,TOTAL"; $rrd_options .= " COMMENT:' \\l'"; + $graph_return['legend_lines']++; $rrd_options .= " HRULE:999999999999999#AAAAAA:'" . rrdtool_escape("Prev Total", $descr_len - 3) . " Rx'"; if (in_array("lst", $data_show)) { $rrd_options .= " GPRINT:inbitsX:LAST:%6.2lf%s"; } @@ -259,6 +271,7 @@ if (in_array("tot", $data_show) && $vars['previous'] == "yes") if (in_array("max", $data_show)) { $rrd_options .= " GPRINT:inbitsX:MAX:%6.2lf%s"; } if (in_array("tot", $data_show)) { $rrd_options .= " GPRINT:totinX:%6.2lf%s".$total_units; } $rrd_options .= " COMMENT:'\\l'"; + $graph_return['legend_lines']++; $rrd_options .= " HRULE:999999999999999#AAAAAA:'" . rrdtool_escape("", $descr_len - 3) . " Tx'"; if (in_array("lst", $data_show)) { $rrd_options .= " GPRINT:outbitsX:LAST:%6.2lf%s"; } @@ -267,6 +280,7 @@ if (in_array("tot", $data_show) && $vars['previous'] == "yes") if (in_array("max", $data_show)) { $rrd_options .= " GPRINT:outbitsX:MAX:%6.2lf%s"; } if (in_array("tot", $data_show)) { $rrd_options .= " GPRINT:totoutX:%6.2lf%s".$total_units; } $rrd_options .= " COMMENT:'\\l'"; + $graph_return['legend_lines']++; $rrd_options .= " HRULE:999999999999999#AAAAAA:'" . rrdtool_escape("", $descr_len - 4) . " Agg'"; if (in_array("lst", $data_show)) { $rrd_options .= " GPRINT:bitsX:LAST:%6.2lf%s"; } @@ -275,6 +289,7 @@ if (in_array("tot", $data_show) && $vars['previous'] == "yes") if (in_array("max", $data_show)) { $rrd_options .= " GPRINT:bitsX:MAX:%6.2lf%s"; } if (in_array("tot", $data_show)) { $rrd_options .= " GPRINT:totX:%6.2lf%s".$total_units; } $rrd_options .= " COMMENT:'\\l'"; + $graph_return['legend_lines']++; } diff --git a/html/includes/graphs/generic_simplex.inc.php b/html/includes/graphs/generic_simplex.inc.php index 15daa372..3ed828b4 100644 --- a/html/includes/graphs/generic_simplex.inc.php +++ b/html/includes/graphs/generic_simplex.inc.php @@ -25,14 +25,15 @@ $graph_return['valid_options'][] = "trend"; include($config['html_dir']."/includes/graphs/common.inc.php"); -$unit_text = str_pad(truncate($unit_text,18,''),18); -$line_text = str_pad(truncate($line_text,12,''),12); +// Fix length before escaping for layout purposes +$unit_text = rrdtool_escape(str_pad(truncate($unit_text,17,''),17)); +$line_text = rrdtool_escape(str_pad(truncate($line_text,11,''),11)); if (isset($unit_integer) && $unit_integer) { - $ds_format = '"%6.0lf "'; //NOTE. max value 999999 + $ds_format = '"%6.0lf"'; //NOTE. max value 999999 } else { - $ds_format = '"%6.2lf%s"'; + $ds_format = '"%5.1lf%s"'; } if ($multiplier) @@ -98,13 +99,13 @@ if ($vars['previous'] == "yes") if ($graph_max) { $rrd_options .= " CDEF:" . $ds . "_minmax=" . $ds . "_max," . $ds . "_min,-"; $rrd_options .= " AREA:" . $ds . "_min#ffffff00"; - $rrd_options .= " AREA:" . $ds . "_minmax#" . $colour_line . "60:STACK"; + $rrd_options .= " AREA:" . $ds . "_minmax#" . $colour_line . "30:STACK"; } else { $rrd_options .= " AREA:".$ds."#".$colour_area.":"; } //} -$rrd_options .= " COMMENT:'".$unit_text."Now Avg Max "; +$rrd_options .= " COMMENT:'".$unit_text."Now Avg Min Max"; if ($percentile) { @@ -119,7 +120,7 @@ $rrd_options .= " GPRINT:".$ds.":AVERAGE:".$ds_format; // if ($print_min || TRUE) // { -// $rrd_options .= " GPRINT:".$ds."_min:MIN:%6.2lf%s"; + $rrd_options .= " GPRINT:".$ds."_min:MIN:".$ds_format; // } $rrd_options .= " GPRINT:".$ds."_max:MAX:".$ds_format; diff --git a/html/includes/graphs/graph.inc.php b/html/includes/graphs/graph.inc.php index 8e928239..77269953 100644 --- a/html/includes/graphs/graph.inc.php +++ b/html/includes/graphs/graph.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage graphs - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -43,7 +43,7 @@ if (isset($vars['format']) && array_key_exists($vars['format'], $config['graph_f $graphfile = $config['temp_dir'] . "/" . strgen() . "." . $extension; -if (OBS_DEBUG) { print_vars($graphtype); } +if (OBS_DEBUG) { print_vars($vars); print_vars($graphtype); } if (isset($graphtype['type']) && isset($graphtype['subtype'])) { $type = $graphtype['type']; @@ -76,22 +76,26 @@ if (preg_match(OBS_PATTERN_RRDTIME, $vars['to'])) { $to = $vars['to']; }// if (preg_match(OBS_PATTERN_RRDTIME, $vars['from'])) { $from = $vars['from']; }// else { $from = $config['time']['day']; } if (isset($vars['period']) && is_numeric($vars['period'])) { - $to = time(); - $from = time() - $vars['period']; + $to = get_time(); + $from = get_time() - $vars['period']; $period = $vars['period']; -} elseif(preg_match('/[\-]*\d+[s|w|m|d|y|h]/', $vars['from'])) { +} elseif (preg_match('/[\-]*\d+[s|w|m|d|y|h]/', $vars['from'])) { // It seems we have AT-style/timespec. Just pass it through (some features will break because we can't calculate period) $from = $vars['from']; - if(preg_match('/[\-]*\d+[s|w|m|d|y|h]/', $vars['to'])) { $to = $vars['to']; } else { $to = 'NOW'; } + if (preg_match('/[\-]*\d+[s|w|m|d|y|h]/', $vars['to'])) { + $to = $vars['to']; + } else { + $to = 'now'; + } } else { - $from = (isset($vars['from'])) ? $vars['from'] : time() - 86400; - $to = (isset($vars['to'])) ? $vars['to'] : time(); + $from = (isset($vars['from']) && is_numeric($vars['from'])) ? $vars['from'] : get_time() - 86400; + $to = (isset($vars['to']) && is_numeric($vars['to'])) ? $vars['to'] : time(); if ($from < 0) { $from = $to + $from; } $period = $to - $from; } // Set prev_from & prev_to if we have a period -if(isset($period)) { +if (isset($period)) { $prev_from = $from - $period; $prev_to = $from; } @@ -100,41 +104,62 @@ $graph_include = FALSE; $definition_include = FALSE; //print_message("Graph type: $type, subtype: $subtype"); -if (is_file($config['html_dir'] . "/includes/graphs/$type/$subtype.inc.php")) -{ +if (is_file($config['html_dir'] . "/includes/graphs/$type/$subtype.inc.php")) { $graph_include = $config['html_dir'] . "/includes/graphs/$type/$subtype.inc.php"; -} -elseif (is_array($config['graph_types'][$type][$subtype]['ds'])) -{ +} elseif (is_array($config['graph_types'][$type][$subtype]['ds'])) { // Init tags array $tags = []; // Additional include with define some graph variables like $unit_text, $graph_title // Currently only for indexed definitions if ($config['graph_types'][$type][$subtype]['index'] && - is_file($config['html_dir'] . "/includes/graphs/$type/definition.inc.php")) - { + is_file($config['html_dir'] . "/includes/graphs/$type/definition.inc.php")) { $definition_include = $config['html_dir'] . "/includes/graphs/$type/definition.inc.php"; } $graph_include = $config['html_dir'] . "/includes/graphs/generic_definition.inc.php"; -} -elseif (is_file($config['html_dir'] . "/includes/graphs/$type/graph.inc.php")) -{ +} elseif (is_file($config['html_dir'] . "/includes/graphs/$type/graph.inc.php")) { $graph_include = $config['html_dir'] . "/includes/graphs/$type/graph.inc.php"; } -if ($graph_include) -{ +if ($graph_include) { include($config['html_dir'] . "/includes/graphs/$type/auth.inc.php"); - if (isset($auth) && $auth) - { - if ($definition_include) - { + if (isset($auth) && $auth) { + if ($definition_include) { include_once($definition_include); } - include($graph_include); + + // Requested a rigid height graph, probably for the dashboard. + // If we don't know the legend height, turn off legend. + // If we know the height and it won't fit, turn it off. + + if ( !(isset($vars['legend']) && $vars['legend'] == 'no') && + (isset($vars['rigid_height']) && $vars['rigid_height'] == 'yes') ) { + $line_height = ($width > 350 ? 14 : 12); // Set line height based on font size chosen by width + if (!isset($graph_return['legend_lines'])) { // Don't know legend length + print_debug('no legend height'); + $vars['legend'] = 'no'; + } + else if (($graph_return['legend_lines'] * $line_height) > ($height - 100)) { // Legend too long + print_debug('legend too tall: ' . $graph_return['legend_lines'] * $line_height); + $vars['legend'] = 'no'; + } + else { // Legend fits + $height = $height - ($graph_return['legend_lines'] * $line_height); + } + } + + $rrd_options .= ' --start ' . rrdtool_escape($from) . + ' --end ' . rrdtool_escape($to) . + ' --width ' . rrdtool_escape($width) . + ' --height ' . rrdtool_escape($height) . ' '; + + if ($vars['legend'] === 'no') { + $rrd_options .= ' -g'; + $legend = 'no'; + } + } } elseif(!isset($vars['command_only'])) { graph_error('no '. $type.'_'.$subtype.''); // Graph Template Missing diff --git a/html/includes/graphs/legend.inc.php b/html/includes/graphs/legend.inc.php index 748594d7..9be44273 100644 --- a/html/includes/graphs/legend.inc.php +++ b/html/includes/graphs/legend.inc.php @@ -65,6 +65,9 @@ if ($legend != 'no') if (in_array("max", $data_show)) { $rrd_options .= " COMMENT:' Max'"; } if (in_array("tot", $data_show)) { $rrd_options .= " COMMENT:' Total'"; } $rrd_options .= " COMMENT:'\\l'"; + + $graph_return['legend_lines']++; + } // EOF diff --git a/html/includes/graphs/multi-oid-entry/auth.inc.php b/html/includes/graphs/multi-oid-entry/auth.inc.php new file mode 100644 index 00000000..c9114a29 --- /dev/null +++ b/html/includes/graphs/multi-oid-entry/auth.inc.php @@ -0,0 +1,61 @@ +5 +// FIXME - do special handling of descriptions if all oid are identical or all devices are identical +// remove device/oid from descr if all identical +// arrange device/oid into aligned columns if the graph is wide enough + +if (!is_array($vars['id'])) { $vars['id'] = array($vars['id']); } + +$is_permitted = FALSE; + +$oids = []; +$rrd_list = []; + +foreach ($vars['id'] as $oid_entry_id) { + + $sql = "SELECT *"; + $sql .= " FROM `oids_entries`"; + $sql .= " LEFT JOIN `oids` USING(`oid_id`)"; + $sql .= " LEFT JOIN `devices` USING(`device_id`)"; + $sql .= " WHERE `oid_entry_id` = ?"; + + $oid = dbFetchRow($sql, array($oid_entry_id)); + if (is_numeric($oid['device_id']) && ($auth || device_permitted($oid['device_id']))) { + $oids[] = $oid; + $is_permitted = TRUE; + + $rrd_file = get_rrd_path($oid, "oid-" . $oid['oid'] . "-" . $oid['oid_type'] . ".rrd"); + if (rrd_is_file($rrd_file, TRUE)) { + $rrd_list[] = [ 'filename' => $rrd_file, + 'descr' => $oid['hostname'] . ' ' . $oid['oid_name'], + 'ds' => 'value']; + } + + } else { + // Bail on first rejection + $is_permitted = FALSE; + } +} + +if ($auth || $is_permitted || $_SESSION['userlevel'] >= 5) { + $title_array = array(); + $title_array[] = array('text' => 'Multiple OIDs'); + $title_array[] = array('text' => safe_count($vars['id']) . ' Entries'); + $auth = TRUE; +} + +unset($is_permitted); + +// EOF \ No newline at end of file diff --git a/html/includes/graphs/multi-oid-entry/line.inc.php b/html/includes/graphs/multi-oid-entry/line.inc.php new file mode 100644 index 00000000..1fb0f8fb --- /dev/null +++ b/html/includes/graphs/multi-oid-entry/line.inc.php @@ -0,0 +1,25 @@ + escape_html($port['port_label']) . (strlen($port['ifAlias']) ? " (".escape_html($port['ifAlias']).")" : ''), 'url' => generate_url(array('page' => 'device', 'device' => $device['device_id'], 'tab' => 'port', 'port' => $port['port_id']))); $graph_title = device_name($device, TRUE) . " :: " . $port['port_label_short']; + + // check if the port has an alias available and add it to the title + if(!empty($port['ifAlias'])) { + $graph_title = $graph_title . " :: " . $port['ifAlias']; + } + $rrd_filename = get_port_rrdfilename($port, NULL, TRUE); if ($vars['type'] == 'port_bits') diff --git a/html/includes/graphs/sensor/airflow.inc.php b/html/includes/graphs/sensor/airflow.inc.php deleted file mode 100644 index cbaf46cb..00000000 --- a/html/includes/graphs/sensor/airflow.inc.php +++ /dev/null @@ -1,30 +0,0 @@ - $dash['dash_name'], 'url' => generate_url(array('page' => "dashboard", 'dash' => $dash['dash_id'])), 'icon' => $config['icon']['overview']); + } + } + + $entries[] = array('divider' => TRUE); + if ($_SESSION['userlevel'] > 7) { - - $dashboards = dbFetchRows("SELECT * FROM `dashboards`"); - - $entries = array(); - - if (safe_count($dashboards)) - { - //$navbar['observium']['dash']['text'] = "Dashboards"; - foreach ($dashboards as $dash) - { - $entries[] = array('text' => $dash['dash_name'], 'url' => generate_url(array('page' => "dashboard", 'dash' => $dash['dash_id'])), 'icon' => $config['icon']['overview']); - } - } - - $entries[] = array('divider' => TRUE); - - $entries[] = array('title' => 'Create Dashboard', 'url' => generate_url(array('page' => 'dashboard_add')), 'icon' => $config['icon']['plus']); - } $navbar['observium']['entries'][] = array('title' => 'Dashboard', 'url' => generate_url(array('page' => 'dashboard')), 'icon' => $config['icon']['overview'], 'entries' => $entries); @@ -106,7 +103,7 @@ $menu_start = utime(); $ids[] = $group['group_id']; } } - foreach (dbFetchRows("SELECT COUNT(*) AS `count`, `group_id` FROM `group_table` WHERE 1" . generate_query_values($ids, 'group_id') . " GROUP BY `group_id`") as $entry) { + foreach (dbFetchRows("SELECT COUNT(*) AS `count`, `group_id` FROM `group_table` WHERE " . generate_query_values_ng($ids, 'group_id') . " GROUP BY `group_id`") as $entry) { $groups_count[$entry['group_id']] = $entry['count']; } unset($ids); @@ -204,15 +201,14 @@ $menu_start = utime(); } $navbar['observium']['entries'][] = array('title' => 'Network Map', 'url' => generate_url(array('page' => 'map')), 'icon' => $config['icon']['netmap']); - + $navbar['observium']['entries'][] = array('title' => 'Network Traffic Map', 'url' => generate_url(array('page' => 'map_traffic')), 'icon' => $config['icon']['map']); $navbar['observium']['entries'][] = array('title' => 'Event Log', 'url' => generate_url(array('page' => 'eventlog')), 'icon' => $config['icon']['eventlog']); $navbar['observium']['entries'][] = array('divider' => TRUE); - if ($_SESSION['userlevel'] >= 7) - { + if ($_SESSION['userlevel'] >= 7) { // Print Contacts $counts['contacts'] = dbFetchCell("SELECT COUNT(*) FROM `alert_contacts`"); @@ -220,31 +216,30 @@ $menu_start = utime(); $navbar['observium']['entries'][] = array('divider' => TRUE); } - if (OBSERVIUM_EDITION !== 'community' && $_SESSION['userlevel'] >= 5) - { + if (OBSERVIUM_EDITION !== 'community' && $_SESSION['userlevel'] >= 5) { // Custom OIDs $oids = dbFetchRows("SELECT `oids`.*, COUNT(*) AS `count` FROM `oids` JOIN `oids_entries` ON `oids`.`oid_id` = `oids_entries`.`oid_id` WHERE 1 GROUP BY `oids`.`oid_id`"); $oid_count = safe_count($oids); - foreach ($oids AS $oid) - { - $oids_menu[] = array('title' => $oid['oid_descr'], 'url' => generate_url(array('page' => 'customoid', 'oid_id' => $oid['oid_id'])), 'count' => $oid['count'], 'icon' => $config['icon']['customoid']); + $oids_menu = []; + foreach ($oids as $oid) { + $oids_menu[] = [ 'title' => $oid['oid_descr'], 'url' => generate_url([ 'page' => 'customoid', 'oid_id' => $oid['oid_id'] ]), 'count' => $oid['count'], 'icon' => $config['icon']['customoid'] ]; } - $navbar['observium']['entries'][] = array('title' => 'Custom OIDs', 'url' => generate_url(array('page' => 'customoids')), 'count' => $oid_count, 'icon' => $config['icon']['customoid'], 'entries' => $oids_menu); + $navbar['observium']['entries'][] = [ 'title' => 'Custom OIDs', 'url' => generate_url([ 'page' => 'customoids' ]), 'count' => $oid_count, 'icon' => $config['icon']['customoid'], 'entries' => $oids_menu ]; //$navbar['observium']['entries'][] = array('divider' => TRUE); - $navbar['observium']['entries'][] = array('title' => 'Probes', 'url' => generate_url(array('page' => 'probes')), 'icon' => $config['icon']['status']); - $navbar['observium']['entries'][] = array('divider' => TRUE); + // Probes + $navbar['observium']['entries'][] = [ 'title' => 'Probes', 'url' => generate_url([ 'page' => 'probes' ]), 'icon' => $config['icon']['status'] ]; + $navbar['observium']['entries'][] = [ 'divider' => TRUE ]; } $navbar['observium']['entries'][] = array('title' => 'Hardware Inventory', 'url' => generate_url(array('page' => 'inventory')), 'icon' => $config['icon']['inventory']); - if ($cache['packages']['count']) - { + if ($cache['packages']['count']) { $navbar['observium']['entries'][] = array('title' => 'Software Packages', 'url' => generate_url(array('page' => 'packages')), 'icon' => $config['icon']['packages']); } @@ -568,12 +563,12 @@ $menu_start = utime(); //r($cache['sensor_types']); - $menu_items[0] = array('fanspeed', 'humidity', 'temperature', 'airflow'); - $menu_items[1] = array('current', 'voltage', 'power', 'apower', 'rpower', 'frequency'); + $menu_items[0] = [ 'temperature', 'humidity', 'fanspeed', 'airflow' ]; + $menu_items[1] = [ 'current', 'voltage', 'power', 'apower', 'rpower', 'frequency' ]; $menu_items[2] = array_diff(array_keys((array)$cache['sensors']['types']), $menu_items[0], $menu_items[1]); - foreach ($menu_items as $items) { - if (is_array($items)) { sort($items); } + foreach ($menu_items as $key => $items) { + if ($key > 1 && is_array($items)) { sort($items); } // Do not sort first basic health entities foreach ($items as $item) { @@ -753,7 +748,7 @@ $menu_start = utime(); echo(' '); } @@ -992,7 +991,9 @@ $(function() { $('#suggestions').fadeOut(); // Hide the suggestions box } else { key_count_global++; - setTimeout("lookupwait(" + key_count_global + ",\"" + inputString + "\")", 300); // Added timeout 0.3s before send query + // Added timeout 0.3s before send query + // Prevent use quotes in query string, for do not use XSS attacks + setTimeout("lookupwait(" + key_count_global + ",\"" + inputString.replace(/"/g, '\\x22').replace(/'/g, '\\x27') + "\")", 300); } key_press_time = Date.now() } diff --git a/html/includes/notifications.inc.php b/html/includes/notifications.inc.php index 26ec3159..1737488b 100644 --- a/html/includes/notifications.inc.php +++ b/html/includes/notifications.inc.php @@ -23,6 +23,7 @@ $alerts_item = get_cache_item('alerts'); if (!ishit_cache_item($notifications_item) || !ishit_cache_item($alerts_item)) { // Generate/collect notifications/alerts + if ($_SESSION['userlevel'] > 7) { $latest = []; $latest['version'] = get_obs_attrib('latest_ver'); @@ -39,17 +40,6 @@ if (!ishit_cache_item($notifications_item) || !ishit_cache_item($alerts_item)) { ]; } - - if (version_compare(PHP_VERSION, OBS_MIN_PHP_VERSION, '<')) { - $notifications[] = array('text' => '

Your PHP version is too old.

- Your currently installed PHP version ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION . ' - is older than the required minimum. - Please upgrade your version of PHP to prevent possible incompatibilities and security problems.
- Currently recommended version(s): 7.2.x and newer.', - 'severity' => 'danger', - 'unixtime' => $config['time']['now']); - } - //if (!function_exists('hash_exists')) //{ // $alerts[] = array('text' => 'The PHP `hash` module is missing This will cause editing and other forms to fail. Please install it.', 'severity' => 'danger'); @@ -63,8 +53,7 @@ if (!ishit_cache_item($notifications_item) || !ishit_cache_item($alerts_item)) { } // Warning about web_url config, only for ssl - if (is_ssl() && preg_match('/^http:/', $config['web_url'])) - { + if (is_ssl() && preg_match('/^http:/', $config['web_url'])) { $notifications[] = array('text' => 'Setting \'web_url\' for "External Web URL" not set or incorrect, please update on ' . generate_link('Global Settings Edit', array('page' => 'settings', 'section' => 'wui')) . ' page.', 'severity' => 'warning', 'unixtime' => $config['time']['now']); } @@ -94,15 +83,6 @@ if (!ishit_cache_item($notifications_item) || !ishit_cache_item($alerts_item)) { 'text' => $entry['message'], 'severity' => $entry['severity']); } - - // Warning about obsolete config on some pages - if (OBS_DEBUG || - in_array($vars['tab'], array('data', 'perf', 'edit', 'showtech')) || - in_array($vars['page'], array('pollerlog', 'settings', 'preferences'))) - { - // FIXME move to notification center? - print_obsolete_config(); - } } if (isset($config['alerts']['suppress']) && $config['alerts']['suppress']) { @@ -142,6 +122,53 @@ if (!ishit_cache_item($notifications_item) || !ishit_cache_item($alerts_item)) { $alerts = array_merge(get_cache_data($alerts_item), $alerts); } +// Admin level notifications on settings/perf pages +if ($_SESSION['userlevel'] >= 10 && (in_array($vars['tab'], [ 'data', 'perf', 'edit', 'showtech' ]) || + in_array($vars['page'], [ 'about', 'pollerlog', 'settings', 'preferences' ]))) { + + if (version_compare(PHP_VERSION, OBS_MIN_PHP_VERSION, '<')) { + $notifications[] = array('text' => '

Your PHP version is too old.

+ Your currently installed PHP version ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION . ' + is older than the required minimum. + Please upgrade your version of PHP to prevent possible incompatibilities and security problems.
+ Currently recommended version(s): 7.2.x and newer.', + 'severity' => 'danger', + 'unixtime' => $config['time']['now']); + $alerts[] = [ + 'title' => 'PHP version is old', + 'text' => 'Your currently installed PHP version ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION . + " is older than the recommended minimum 7.2.x.", + 'severity' => 'alert' + ]; + } + + // Same for MySQL/MariaDB + $versions = get_versions(); + if ($versions['mysql_old']) { + $mysql_recommented = $versions['mysql_name'] === 'MariaDB' ? OBS_MIN_MARIADB_VERSION : OBS_MIN_MYSQL_VERSION; + + $notifications[] = array('text' => '

Your '.$versions['mysql_name'].' version is old.

+ Your currently installed '.$versions['mysql_name'].' version ' . $versions['mysql_version'] . ' + is older than the recommended minimum. + Please upgrade your version of '.$versions['mysql_name'].' to prevent possible incompatibilities and security problems.
+ Currently recommended version is '.$mysql_recommented.' and newer.', + 'severity' => 'warning', + 'unixtime' => $config['time']['now']); + $alerts[] = [ + 'title' => $versions['mysql_name'].' version is old', + 'text' => 'Your currently installed '.$versions['mysql_name'].' version ' . $versions['mysql_version'] . + " is older than the recommended minimum $mysql_recommented.", + 'severity' => 'warning' + ]; + } + + // Warning about obsolete config on some pages + if (OBS_DEBUG) { + // FIXME move to notification center? + print_obsolete_config(); + } + +} // Sort by unixtime $notifications = array_sort_by($notifications, 'unixtime', SORT_DESC, SORT_NUMERIC); diff --git a/html/includes/port-sort-select.inc.php b/html/includes/port-sort-select.inc.php index c360182d..083857d3 100644 --- a/html/includes/port-sort-select.inc.php +++ b/html/includes/port-sort-select.inc.php @@ -57,6 +57,9 @@ switch ($vars['sort']) { case 'mac': $select .= ',`ifPhysAddress`'; break; + case 'mtu': + $select .= ',`ifMtu`'; + break; case 'device': $select .= ',`devices`.`hostname`'; break; diff --git a/html/includes/port-sort.inc.php b/html/includes/port-sort.inc.php index c743c771..dc0b82d4 100644 --- a/html/includes/port-sort.inc.php +++ b/html/includes/port-sort.inc.php @@ -64,6 +64,9 @@ switch ($vars['sort']) { case 'media': $ports = array_sort_by($ports, 'ifType', $sort_order, SORT_STRING); break; + case 'mtu': + $ports = array_sort_by($ports, 'ifMtu', $sort_order, SORT_NUMERIC); + break; case 'descr': $ports = array_sort_by($ports, 'ifAlias', $sort_order, SORT_STRING); break; diff --git a/html/includes/print/addresses.inc.php b/html/includes/print/addresses.inc.php index 788d2f91..59a3e7af 100644 --- a/html/includes/print/addresses.inc.php +++ b/html/includes/print/addresses.inc.php @@ -1,5 +1,4 @@ ' . PHP_EOL; $string .= '
' . PHP_EOL; - if ($events['short']) - { - $string .= ' ' . PHP_EOL; + if ($events['short']) { + $string .= ' ' . PHP_EOL; } else { $string .= ' ' . PHP_EOL; @@ -217,26 +224,26 @@ function get_alert_log($vars) switch ($var) { // case 'alert_entry': -// $where .= generate_query_values($value, 'alert_table_id'); +// $where .= generate_query_values_and($value, 'alert_table_id'); // break; case 'log_type': - $where .= generate_query_values($value, 'log_type'); + $where .= generate_query_values_and($value, 'log_type'); break; case 'alert_test_id': - $where .= generate_query_values($value, 'alert_test_id'); + $where .= generate_query_values_and($value, 'alert_test_id'); break; case 'device': case 'device_id': - $where .= generate_query_values($value, 'device_id'); + $where .= generate_query_values_and($value, 'device_id'); break; case 'entity_id': - $where .= generate_query_values($value, 'entity_id'); + $where .= generate_query_values_and($value, 'entity_id'); break; case 'entity_type': - $where .= generate_query_values($value, 'entity_type'); + $where .= generate_query_values_and($value, 'entity_type'); break; case 'message': - $where .= generate_query_values($value, 'message', '%LIKE%'); + $where .= generate_query_values_and($value, 'message', '%LIKE%'); break; case 'timestamp_from': $where .= ' AND `timestamp` >= ?'; diff --git a/html/includes/print/arptable.inc.php b/html/includes/print/arptable.inc.php index 88732330..e6d5651b 100644 --- a/html/includes/print/arptable.inc.php +++ b/html/includes/print/arptable.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2020 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -38,33 +38,32 @@ function print_arptable($vars) { case 'device': case 'device_id': - $where .= generate_query_values($value, 'device_id'); + $where .= generate_query_values_and($value, 'device_id'); break; case 'port': case 'port_id': - $where .= generate_query_values($value, 'I.port_id'); + $where .= generate_query_values_and($value, 'I.port_id'); break; case 'ip_version': - $where .= generate_query_values($value, 'ip_version'); + $where .= generate_query_values_and($value, 'ip_version'); break; case 'address': - if (isset($vars['searchby']) && $vars['searchby'] == 'ip') + if (isset($vars['searchby']) && $vars['searchby'] === 'ip') { $value = trim($value); - if (strpos($value, ':') !== FALSE) - { - if (Net_IPv6::checkIPv6($value)) + if (str_contains($value, ':')) { + if (get_ip_version($value) === 5) { - $value = Net_IPv6::uncompress($value, TRUE); + $value = ip_uncompress($value); } else { // FIXME. Need another conversion ("2001:b08:b08" -> "2001:0b08:0b08") -- mike } } - $where .= generate_query_values($value, 'ip_address', '%LIKE%'); + $where .= generate_query_values_and($value, 'ip_address', '%LIKE%'); } else { // MAC Addresses - $value = str_replace(array(':', ' ', '-', '.', '0x'), '', $value); - $where .= generate_query_values($value, 'mac_address', '%LIKE%'); + $value = str_replace([ ':', ' ', '-', '.', '0x' ], '', $value); + $where .= generate_query_values_and($value, 'mac_address', '%LIKE%'); } break; } diff --git a/html/includes/print/authlog.inc.php b/html/includes/print/authlog.inc.php index 76bd68d2..629e9983 100644 --- a/html/includes/print/authlog.inc.php +++ b/html/includes/print/authlog.inc.php @@ -1,5 +1,4 @@ element based on the contents of the $header array, modified by the current request $vars + * + * @param array $header Array with table header definition including columns and classes. + * @param array $vars Array with current selected column ID and/or variables for generate column link + * @return string $string + */ + +function generate_table_header($header = [], $vars = []) { + + // Store current $vars sort variables + $sort = $vars['sort']; + $sort_order = strtolower($vars['sort_order']); + if (!in_array($sort_order, array('asc', 'desc', 'reset'))) { + $sort_order = 'asc'; + } + + // Reset current $vars sort variables + unset($vars['sort'], $vars['sort_order']); + + $output = ''; + + $output .= ' ' . PHP_EOL; + + //r($header); + + // Loop each column generating a ' . PHP_EOL; + } + + $output .= ' ' . PHP_EOL; + $output .= ' ' . PHP_EOL; + + return $output; + + +} + +function generate_table_header_field($field_id, $field, $vars, $sort, $sort_order) +{ + + if(empty($field)) { // No label, generate empty column header. + $return = ''; + } elseif ( is_numeric($field_id) && !is_array($field)) { // Label without id, generate simple column header + $return = $field; + } else { + if(!is_array($field)) { $field = [ 'label' => $field ]; } + if(!isset($field['label'])) { $field['label'] = $field[0]; } + + if($sort == $field_id) { + $field['label'] = ''.$field['label'].''; + if($sort_order == 'asc') { + $new_vars = [ 'sort' => $field_id, 'sort_order' => 'desc' ]; + $field['caret'] = ' '; + } else { + $new_vars = [ 'sort' => NULL, 'sort_order' => NULL ]; + $field['caret'] = ' '; + } + } else { + $new_vars = [ 'sort' => $field_id ]; + } + $return = ''.$field['label'].$field['caret'].''; + + // Generate slash separated links for subfields + if(isset($field['subfields'])) + { + foreach($field['subfields'] as $subfield_id => $subfield) + { + //r($subfield); r($subfield_id); + $subfields[] = generate_table_header_field($subfield_id, $subfield, $vars, $sort, $sort_order); + } + $return .= ' ['.implode(" / ", $subfields).']'; + } + } + + return $return; + +} + /** * Helper function for generate table header with sort links * This used in other print_* functions diff --git a/html/includes/print/dot1xtable.inc.php b/html/includes/print/dot1xtable.inc.php index 05285f77..43f93190 100644 --- a/html/includes/print/dot1xtable.inc.php +++ b/html/includes/print/dot1xtable.inc.php @@ -1,5 +1,4 @@ ' . PHP_EOL; if ($events['short']) { - $string .= ' ' . PHP_EOL; + $string .= ' ' . PHP_EOL; } else { $string .= ' ' . PHP_EOL; @@ -215,22 +214,22 @@ function get_events_array($vars) { case 'device': case 'device_id': - $where .= generate_query_values($value, 'device_id'); + $where .= generate_query_values_and($value, 'device_id'); break; case 'port': case 'entity': case 'entity_id': - $where .= generate_query_values($value, 'entity_id'); + $where .= generate_query_values_and($value, 'entity_id'); break; case 'severity': - $where .= generate_query_values($value, 'severity'); + $where .= generate_query_values_and($value, 'severity'); break; case 'type': case 'entity_type': - $where .= generate_query_values($value, 'entity_type'); + $where .= generate_query_values_and($value, 'entity_type'); break; case 'message': - $where .= generate_query_values($value, 'message', '%LIKE%'); + $where .= generate_query_values_and($value, 'message', '%LIKE%'); break; case 'timestamp_from': $where .= ' AND `timestamp` >= ?'; @@ -243,8 +242,8 @@ function get_events_array($vars) case "group": case "group_id": $values = get_group_entities($value); - $where .= generate_query_values($values, 'entity_id'); - $where .= generate_query_values(get_group_entity_type($value), 'entity_type'); + $where .= generate_query_values_and($values, 'entity_id'); + $where .= generate_query_values_and(get_group_entity_type($value), 'entity_type'); break; } } diff --git a/html/includes/print/fdbtable.inc.php b/html/includes/print/fdbtable.inc.php index 74866176..902de0c4 100644 --- a/html/includes/print/fdbtable.inc.php +++ b/html/includes/print/fdbtable.inc.php @@ -18,6 +18,7 @@ * */ function print_fdbtable($vars) { + //r($vars); $entries = get_fdbtable_array($vars); if (!$entries['count']) { @@ -27,8 +28,13 @@ function print_fdbtable($vars) { } $list = array('device' => FALSE, 'port' => FALSE); - if (!isset($vars['device']) || empty($vars['device']) || $vars['page'] === 'search') { $list['device'] = TRUE; } - if (!isset($vars['port']) || empty($vars['port']) || $vars['page'] === 'search') { $list['port'] = TRUE; } + + + + if (!isset($vars['device']) || is_array($vars['device']) || empty($vars['device']) || $vars['page'] === 'search') { $list['device'] = TRUE; } + if (!isset($vars['port']) || is_array($vars['port']) || empty($vars['port']) || $vars['page'] === 'search') { $list['port'] = TRUE; } + + //r($list); $string = generate_box_open(); @@ -119,50 +125,54 @@ function get_fdbtable_array($vars) { // Do not show deleted entries by default $vars['deleted'] = 0; } - //r($vars); + foreach ($vars as $var => $value) { - if ($value != '') { - switch ($var) { - case 'device': - case 'device_id': - $where .= generate_query_values($value, 'F.device_id'); - break; - case 'port': - case 'port_id': - $where .= generate_query_values($value, 'F.port_id'); - break; - case 'interface': - case 'port_name': - $where .= generate_query_values($value, 'I.ifDescr', 'LIKE%'); + + // Skip empty variables (and array with empty first entry) when building query + if ($value == '' || (is_array($value) && count($value) == 1 && $value[0] == '')) { continue; } + + switch ($var) { + case 'device': + case 'device_id': + $where .= generate_query_values_and($value, 'F.device_id'); + break; + case 'port': + case 'port_id': + $where .= generate_query_values_and($value, 'F.port_id'); + break; + case 'interface': + case 'port_name': + $where .= generate_query_values_and($value, 'I.ifDescr', 'LIKE%'); + $join_ports = TRUE; + break; + case 'trunk': + if (get_var_true($value)) { + $where .= " AND (`I`.`ifTrunk` IS NOT NULL AND `I`.`ifTrunk` != '')"; $join_ports = TRUE; - break; - case 'trunk': - if (get_var_true($value)) { - $where .= " AND (`I`.`ifTrunk` IS NOT NULL AND `I`.`ifTrunk` != '')"; - $join_ports = TRUE; - } elseif (in_array($value, [ 'none', 'no', '0' ])) { - $where .= " AND (`I`.`ifTrunk` IS NULL OR `I`.`ifTrunk` = '')"; - $join_ports = TRUE; - } - break; - case 'vlan_id': - $where .= generate_query_values($value, 'F.vlan_id'); - break; - case 'vlan_name': - $where .= generate_query_values($value, 'V.vlan_name'); - break; - case 'address': - if (str_contains_array($value, [ '*', '?' ])) { - $like = 'LIKE'; - } else { - $like = '%LIKE%'; - } - $where .= generate_query_values(str_replace([ ':', ' ', '-', '.', '0x' ],'', $value), 'F.mac_address', $like); - break; - case 'deleted': - $where .= ' AND `deleted` = ?'; - $params[] = $value; - } + } + else if (in_array($value, ['none', 'no', '0'])) { + $where .= " AND (`I`.`ifTrunk` IS NULL OR `I`.`ifTrunk` = '')"; + $join_ports = TRUE; + } + break; + case 'vlan_id': + $where .= generate_query_values_and($value, 'F.vlan_id'); + break; + case 'vlan_name': + $where .= generate_query_values_and($value, 'V.vlan_name'); + break; + case 'address': + if (str_contains_array($value, ['*', '?'])) { + $like = 'LIKE'; + } + else { + $like = '%LIKE%'; + } + $where .= generate_query_values_and(str_replace([':', ' ', '-', '.', '0x'], '', $value), 'F.mac_address', $like); + break; + case 'deleted': + $where .= ' AND `deleted` = ?'; + $params[] = $value; } } @@ -206,6 +216,9 @@ function get_fdbtable_array($vars) { $query .= $sort; $query .= " LIMIT $start,$pagesize"; + //r($query); + //r($params); + // Query addresses //$array['entries'] = dbFetchRows($query, $params, TRUE); $array['entries'] = dbFetchRows($query, $params); diff --git a/html/includes/print/inventory.inc.php b/html/includes/print/inventory.inc.php index 514de8f3..4048115f 100644 --- a/html/includes/print/inventory.inc.php +++ b/html/includes/print/inventory.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -28,31 +28,31 @@ function generate_inventory_query($vars) { { case 'device': case 'device_id': - $where .= generate_query_values($value, 'device_id'); + $where .= generate_query_values_and($value, 'device_id'); break; case 'os': - $where .= generate_query_values($value, 'os'); + $where .= generate_query_values_and($value, 'os'); $select[] = 'devices.os'; $devices = TRUE; break; case 'parts': case 'entPhysicalModelName': - $where .= generate_query_values($value, 'entPhysicalModelName', 'LIKE'); + $where .= generate_query_values_and($value, 'entPhysicalModelName', 'LIKE'); break; case 'serial': case 'entPhysicalSerialNum': - $where .= generate_query_values($value, 'entPhysicalSerialNum', '%LIKE%'); + $where .= generate_query_values_and($value, 'entPhysicalSerialNum', '%LIKE%'); break; case 'description': case 'entPhysicalDescr': - $where .= generate_query_values($value, 'entPhysicalDescr', '%LIKE%'); + $where .= generate_query_values_and($value, 'entPhysicalDescr', '%LIKE%'); break; case 'class': case 'entPhysicalClass': - $where .= generate_query_values($value, 'entPhysicalClass', '%LIKE%'); + $where .= generate_query_values_and($value, 'entPhysicalClass', '%LIKE%'); break; case 'deleted': - $where .= generate_query_values($value, 'deleted', 'NOT NULL'); + $where .= generate_query_values_and($value, 'deleted', 'NOT NULL'); break; } } @@ -371,15 +371,15 @@ relay // vendor + model + hw $ent_model = ''; - if ($ent['entPhysicalModelName'] && !in_array($ent['entPhysicalModelName'], [ 'N/A' ])) { - if ($ent['entPhysicalMfgName'] && !in_array($ent['entPhysicalMfgName'], [ 'N/A' ])) { + if ($ent['entPhysicalModelName'] && is_valid_param($ent['entPhysicalModelName'], 'hardware')) { + if ($ent['entPhysicalMfgName'] && is_valid_param($ent['entPhysicalMfgName'], 'vendor')) { $ent_model .= $ent['entPhysicalMfgName']; } $ent_model .= ' ' . $ent['entPhysicalModelName']; - if ($ent['entPhysicalHardwareRev'] && !in_array($ent['entPhysicalHardwareRev'], [ 'N/A' ])) { - $ent_model .= " ${ent['entPhysicalHardwareRev']}"; + if ($ent['entPhysicalHardwareRev'] && is_valid_param($ent['entPhysicalHardwareRev'], 'revision')) { + $ent_model .= " " . $ent['entPhysicalHardwareRev']; } $ent_model = trim($ent_model); } diff --git a/html/includes/print/logalert.inc.php b/html/includes/print/logalert.inc.php index b2b88661..7a0e9594 100644 --- a/html/includes/print/logalert.inc.php +++ b/html/includes/print/logalert.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2020 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -113,17 +113,17 @@ function get_logalert_log($vars) switch ($var) { case 'la_id': - $where .= generate_query_values($value, 'la_id'); + $where .= generate_query_values_and($value, 'la_id'); break; case 'device': case 'device_id': - $where .= generate_query_values($value, 'device_id'); + $where .= generate_query_values_and($value, 'device_id'); break; case 'program': - $where .= generate_query_values($value, 'program', '%LIKE%'); + $where .= generate_query_values_and($value, 'program', '%LIKE%'); break; case 'message': - $where .= generate_query_values($value, 'message', '%LIKE%'); + $where .= generate_query_values_and($value, 'message', '%LIKE%'); break; case 'timestamp_from': $where .= ' AND `timestamp` >= ?'; diff --git a/html/includes/print/mac_addresses.inc.php b/html/includes/print/mac_addresses.inc.php index 876d359a..0b048eea 100644 --- a/html/includes/print/mac_addresses.inc.php +++ b/html/includes/print/mac_addresses.inc.php @@ -1,5 +1,4 @@ ' . generate_menu_link($entry['url'], ' ' . $entry['title'], $entry['count'], 'label', NULL, $entry['alert_count']) . PHP_EOL); + echo(str_pad('',($level-1)*2) . '
' . generate_device_link($storage) . ''.generate_entity_link('storage', $storage).''.$storage['human_type'].' '.$total.' '.$used.' '.$free.''; - $timediff = $GLOBALS['config']['time']['now'] - strtotime($entry['timestamp']); - $string .= generate_tooltip_link('', format_uptime($timediff, "short-3"), format_timestamp($entry['timestamp']), NULL) . ''; + $string .= generate_tooltip_time($entry['timestamp']) . ''; $string .= format_timestamp($entry['timestamp']) . '
element + foreach($header AS $id => $col) + { + + //if (in_array($id, ['class', 'group', 'style'])) { continue; } // skip html metadata + + if ($id === 'class' || $id === 'style') { continue; } // skip html data + + $fields = []; // Empty array for fields + + if(empty($col) || !is_array($col)) { $col = [ $id => $col ]; } // If col is not an array, make it one + + if($id == 'state-marker') { $col['class'] = 'state-marker'; } // Hard code handling of state-marker + + // Loop each field and generate an element + foreach ($col as $field_id => $field) { + + if ($field_id === 'class' || $field_id === 'style' || $field_id == 'subfields') { continue; } // skip html data + + $header_field = generate_table_header_field($field_id, $field, $vars, $sort, $sort_order); + + if(strlen($header_field) > 0) { + $fields[] = $header_field; + } + + } + $output .= ' '; + $output .= implode(' / ', $fields); + $output .= '
'; - $timediff = $GLOBALS['config']['time']['now'] - strtotime($entry['timestamp']); - $string .= generate_tooltip_link('', format_uptime($timediff, "short-3"), format_timestamp($entry['timestamp']), NULL) . ''; + $string .= generate_tooltip_time($entry['timestamp']) . ''; $string .= format_timestamp($entry['timestamp']) . '
' . PHP_EOL; + + $cols = [ + [ NULL, 'class="state-marker"' ], + [ NULL, 'style="width: 1px;"' ], + 'device' => [ 'Local address', 'style="width: 150px;"' ], + 'local_as' => [ 'Local AS / VRF', 'style="width: 110px;"' ], + [ NULL, 'style="width: 20px;"' ], + 'peer_ip' => [ 'Peer address', 'style="width: 150px;"' ], + 'peer_as' => [ 'Remote AS', 'style="width: 90px;"' ], + 'type' => [ 'Type', 'style="width: 50px;"' ], + [ 'Family', 'style="width: 50px;"' ], + 'state' => 'State', + 'uptime' => 'Uptime / Updates', + ]; + //if (!$list['device']) { unset($cols['device']); } + $string .= get_table_header($cols, $vars); + + $string .= ' ' . PHP_EOL; + + foreach ($entries['entries'] as $peer) { + $local_dev = device_by_id_cache($peer['device_id']); + $local_as = ($list['device'] ? ' (AS' . $peer['human_local_as'] . ')' : ''); + $local_name = generate_device_link_short($local_dev, [ 'tab' => 'routing', 'proto' => 'bgp' ], 18); + $local_ip = generate_device_link($local_dev, $peer['human_localip'] . $local_as, [ 'tab' => 'routing', 'proto' => 'bgp' ]); + $peer_as = 'AS' . $peer['human_remote_as']; + if ($peer['peer_device_id']) { + $peer_dev = device_by_id_cache($peer['peer_device_id']); + $peer_name = generate_device_link_short($peer_dev, [ 'tab' => 'routing', 'proto' => 'bgp' ], 18); + } else { + $peer_name = $peer['reverse_dns']; + } + $peer_ip = generate_entity_link("bgp_peer", $peer, $peer['human_remoteip']); + $peer_afis = &$entries['afisafi'][$peer['device_id']][$peer['bgpPeer_id']]; + $peer_afis_html = []; + + // Generate AFI/SAFI labels + foreach ($peer_afis as $peer_afi) { + // $peer_afi_html = ''; + if (isset($GLOBALS['config']['routing_afis_name'][$peer_afi['afi']])) { + $afi_num = $GLOBALS['config']['routing_afis_name'][$peer_afi['afi']]; + $afi_class = $GLOBALS['config']['routing_afis'][$afi_num]['class']; + } else { + $afi_class = 'default'; + } + + if (isset($GLOBALS['config']['routing_safis_name'][$peer_afi['safi']])) { + // Named SAFI + $safi_num = $GLOBALS['config']['routing_safis_name'][$peer_afi['safi']]; + $safi_class = $GLOBALS['config']['routing_safis'][$safi_num]['class']; + + } elseif (isset($GLOBALS['config']['routing_safis'][$peer_afi['safi']])) { + // Numeric SAFI + $safi_num = $peer_afi['safi']; + $peer_afi['safi'] = $GLOBALS['config']['routing_safis'][$safi_num]['name']; + $safi_class = $GLOBALS['config']['routing_safis'][$safi_num]['class']; + } else { + $safi_class = 'default'; + } + + $peer_afi_items = [ + [ 'event' => $afi_class, 'text' => $peer_afi['afi'] ], + [ 'event' => $safi_class, 'text' => $peer_afi['safi'] ], + ]; + $peer_afi_html = get_label_group($peer_afi_items); + //r($peer_afi_html); + $peer_afis_html[] = $peer_afi_html; } - // Entries have been returned. Print the table. - $list = array('device' => FALSE); - if ($vars['page'] !== 'device') { - $list['device'] = TRUE; + $string .= ' ' . PHP_EOL; + $string .= ' ' . PHP_EOL; + $string .= ' ' . PHP_EOL; + $string .= ' ' . PHP_EOL; + $string .= ' ' . PHP_EOL; + $string .= ' ' . PHP_EOL . ' ' . PHP_EOL; + } elseif ($list['graph']) { + // Empty row for correct view class table-striped-two + $string .= ' ' . PHP_EOL; } + } - // Print - echo $string; + $string .= ' ' . PHP_EOL; + $string .= '
' . $local_ip . '
' . $local_name . '
AS' . $peer['human_local_as'] . ''; + if (!safe_empty($peer['virtual_name'])) { + $vitual_type = isset($GLOBALS['config']['os'][$local_dev['os']]['snmp']['virtual_type']) ? nicecase($GLOBALS['config']['os'][$local_dev['os']]['snmp']['virtual_type']) : 'VRF'; + $string .= '
'.$vitual_type.': '.$peer['virtual_name'].''; } - - switch ($vars['graph']) { - case 'prefixes_ipv4unicast': - case 'prefixes_ipv4multicast': - case 'prefixes_ipv4vpn': - case 'prefixes_ipv6unicast': - case 'prefixes_ipv6multicast': - case 'macaccounting_bits': - case 'macaccounting_pkts': - case 'updates': - $table_class = 'table-striped-two'; - $list['graph'] = TRUE; - break; - default: - $table_class = 'table-striped'; - $list['graph'] = FALSE; - } - - $string = generate_box_open(); - - $string .= '' . PHP_EOL; - - $cols = array( - array(NULL, 'class="state-marker"'), - array(NULL, 'style="width: 1px;"'), - 'device' => array('Local address', 'style="width: 150px;"'), - 'local_as' => [ 'Local AS / VRF', 'style="width: 110px;"' ], - array(NULL, 'style="width: 20px;"'), - 'peer_ip' => array('Peer address', 'style="width: 150px;"'), - 'peer_as' => [ 'Remote AS', 'style="width: 90px;"' ], - 'type' => array('Type', 'style="width: 50px;"'), - array('Family', 'style="width: 50px;"'), - 'state' => 'State', - 'uptime' => 'Uptime / Updates', - ); - //if (!$list['device']) { unset($cols['device']); } - $string .= get_table_header($cols, $vars); - - $string .= ' ' . PHP_EOL; - - foreach ($entries['entries'] as $peer) - { - $local_dev = device_by_id_cache($peer['device_id']); - $local_as = ($list['device'] ? ' (AS' . $peer['human_local_as'] . ')' : ''); - $local_name = generate_device_link_short($local_dev, [ 'tab' => 'routing', 'proto' => 'bgp' ], 18); - $local_ip = generate_device_link($local_dev, $peer['human_localip'] . $local_as, array('tab' => 'routing', 'proto' => 'bgp')); - $peer_as = 'AS' . $peer['human_remote_as']; - if ($peer['peer_device_id']) { - $peer_dev = device_by_id_cache($peer['peer_device_id']); - $peer_name = generate_device_link_short($peer_dev, [ 'tab' => 'routing', 'proto' => 'bgp' ], 18); - } else { - $peer_name = $peer['reverse_dns']; - } - $peer_ip = generate_entity_link("bgp_peer", $peer, $peer['human_remoteip']); - $peer_afis = &$entries['afisafi'][$peer['device_id']][$peer['bgpPeer_id']]; - $peer_afis_html = array(); - - // Generate AFI/SAFI labels - foreach ($peer_afis as $peer_afi) - { -// $peer_afi_html = ''; - if (isset($GLOBALS['config']['routing_afis_name'][$peer_afi['afi']])) - { - $afi_num = $GLOBALS['config']['routing_afis_name'][$peer_afi['afi']]; - $afi_class = $GLOBALS['config']['routing_afis'][$afi_num]['class']; - } else { - $afi_class = 'default'; - } - - if (isset($GLOBALS['config']['routing_safis_name'][$peer_afi['safi']])) - { - // Named SAFI - $safi_num = $GLOBALS['config']['routing_safis_name'][$peer_afi['safi']]; - $safi_class = $GLOBALS['config']['routing_safis'][$safi_num]['class']; - } - else if (isset($GLOBALS['config']['routing_safis'][$peer_afi['safi']])) - { - // Numeric SAFI - $safi_num = $peer_afi['safi']; - $peer_afi['safi'] = $GLOBALS['config']['routing_safis'][$safi_num]['name']; - $safi_class = $GLOBALS['config']['routing_safis'][$safi_num]['class']; - } else { - $safi_class = 'default'; - } - -// $peer_afi_html .= '' . $peer_afi['afi'] . ''; -// $peer_afi_html .= '' . $peer_afi['safi'] . ''; -// $peer_afi_html .= ''; - - $peer_afi_items = [ - ['event' => $afi_class, 'text' => $peer_afi['afi']], - ['event' => $safi_class, 'text' => $peer_afi['safi']], - ]; - $peer_afi_html = get_label_group($peer_afi_items); - //r($peer_afi_html); - $peer_afis_html[] = $peer_afi_html; - } - - $string .= ' ' . PHP_EOL; - $string .= ' ' . PHP_EOL; - $string .= ' ' . PHP_EOL; - $string .= ' ' . PHP_EOL; - $string .= ' ' . PHP_EOL; - $string .= ' ' . PHP_EOL; - $string .= ' ' . PHP_EOL; - $string .= ' ' . PHP_EOL; - $string .= ' ' . PHP_EOL; - $string .= ' ' . PHP_EOL; - $string .= ' ' . PHP_EOL; - $string .= ' ' . PHP_EOL; + $string .= ' ' . PHP_EOL; + $string .= ' ' . PHP_EOL; + $string .= ' ' . PHP_EOL; + $string .= ' ' . PHP_EOL; + $string .= ' ' . PHP_EOL; + $string .= ' ' . PHP_EOL; + $string .= ' ' . PHP_EOL; - $string .= ' ' . PHP_EOL; + $string .= ' ' . PHP_EOL; - // Graphs - $peer_graph = FALSE; - switch ($vars['graph']) { - case 'prefixes_ipv4unicast': - case 'prefixes_ipv4multicast': - case 'prefixes_ipv4vpn': - case 'prefixes_ipv6unicast': - case 'prefixes_ipv6multicast': - $afisafi = preg_replace('/prefixes_(ipv[46])(\w+)/', '$1.$2', $vars['graph']); // prefixes_ipv6unicast ->> ipv6.unicast - if (isset($peer_afis[$afisafi]) && $peer['bgpPeer_id']) - { - $graph_array['type'] = 'bgp_' . $vars['graph']; - $graph_array['id'] = $peer['bgpPeer_id']; - $peer_graph = TRUE; - } - break; - case 'updates': - if ($peer['bgpPeer_id']) - { - $graph_array['type'] = 'bgp_updates'; - $graph_array['id'] = $peer['bgpPeer_id']; - $peer_graph = TRUE; - } - break; - case 'macaccounting_bits': - case 'macaccounting_pkts': - //FIXME. I really still not know it works or not? -- mike - // This part copy-pasted from old code as is - $acc = dbFetchRow("SELECT * FROM `mac_accounting` AS M + // Graphs + $peer_graph = FALSE; + switch ($vars['graph']) { + case 'prefixes_ipv4unicast': + case 'prefixes_ipv4multicast': + case 'prefixes_ipv4vpn': + case 'prefixes_ipv6unicast': + case 'prefixes_ipv6multicast': + $afisafi = preg_replace('/prefixes_(ipv[46])(\w+)/', '$1.$2', $vars['graph']); // prefixes_ipv6unicast ->> ipv6.unicast + if (isset($peer_afis[$afisafi]) && $peer['bgpPeer_id']) { + $graph_array['type'] = 'bgp_' . $vars['graph']; + $graph_array['id'] = $peer['bgpPeer_id']; + $peer_graph = TRUE; + } + break; + + case 'updates': + if ($peer['bgpPeer_id']) { + $graph_array['type'] = 'bgp_updates'; + $graph_array['id'] = $peer['bgpPeer_id']; + $peer_graph = TRUE; + } + break; + + case 'macaccounting_bits': + case 'macaccounting_pkts': + // FIXME. I really still not know it works or not? -- mike + // This part copy-pasted from old code as is + $acc = dbFetchRow("SELECT * FROM `mac_accounting` AS M LEFT JOIN `ip_mac` AS I ON M.mac = I.mac_address LEFT JOIN `ports` AS P ON P.port_id = M.port_id LEFT JOIN `devices` AS D ON D.device_id = P.device_id WHERE I.ip_address = ?", array($peer['bgpPeerRemoteAddr'])); - $database = get_rrd_path($device, "cip-" . $acc['ifIndex'] . "-" . $acc['mac'] . ".rrd"); - if (is_array($acc) && is_file($database)) - { - $peer_graph = TRUE; - $graph_array['id'] = $acc['ma_id']; - $graph_array['type'] = $vars['graph']; - } - break; - } - - if ($peer_graph) { - $graph_array['to'] = get_time(); - $string .= ' ' . PHP_EOL; - $string .= ' ' . PHP_EOL . ' ' . PHP_EOL; - } - elseif ($list['graph']) - { - // Empty row for correct view class table-striped-two - $string .= ' ' . PHP_EOL; + $database = get_rrd_path($device, "cip-" . $acc['ifIndex'] . "-" . $acc['mac'] . ".rrd"); + if (is_array($acc) && is_file($database)) { + $peer_graph = TRUE; + $graph_array['id'] = $acc['ma_id']; + $graph_array['type'] = $vars['graph']; } + break; } - $string .= ' ' . PHP_EOL; - $string .= '
' . $local_ip . '
' . $local_name . '
AS' . $peer['human_local_as'] . ''; - if (!safe_empty($peer['virtual_name'])) { - $vitual_type = isset($GLOBALS['config']['os'][$local_dev['os']]['snmp']['virtual_type']) ? nicecase($GLOBALS['config']['os'][$local_dev['os']]['snmp']['virtual_type']) : 'VRF'; - $string .= '
'.$vitual_type.': '.$peer['virtual_name'].''; - } - $string .= '
' . $peer_ip . '
' . $peer_name . '
' . $peer_as . '
' . $peer['astext'] . '
' . $peer['peer_type'] . '' . implode('
', $peer_afis_html) . '
' . $peer['bgpPeerAdminStatus'] . '
' . $peer['bgpPeerState'] . '
' . format_uptime($peer['bgpPeerFsmEstablishedTime']) . '
+ $string .= '
' . $peer_ip . '
' . $peer_name . '
' . $peer_as . '
' . $peer['astext'] . '
' . $peer['peer_type'] . '' . implode('
', $peer_afis_html) . '
' . $peer['bgpPeerAdminStatus'] . '
' . $peer['bgpPeerState'] . '
' . format_uptime($peer['bgpPeerFsmEstablishedTime']) . '
Updates: ' . format_si($peer['bgpPeerInUpdates']) . ' ' . format_si($peer['bgpPeerOutUpdates']) . '
' . PHP_EOL; - - $string .= generate_graph_row($graph_array); - - $string .= '
'; + if ($peer_graph) { + $graph_array['to'] = get_time(); + $string .= '
' . PHP_EOL; - $string .= generate_box_close(); + $string .= generate_graph_row($graph_array); - // Print pagination header - if ($entries['pagination_html']) - { - $string = $entries['pagination_html'] . $string . $entries['pagination_html']; + $string .= '
'; + + $string .= generate_box_close(); + + // Print pagination header + if ($entries['pagination_html']) { + $string = $entries['pagination_html'] . $string . $entries['pagination_html']; + } + + // Print + echo $string; } @@ -240,156 +227,172 @@ function print_bgp_peer_table($vars) { * pagination, pageno, pagesize * device, type, adminstatus, state */ -function get_bgp_array($vars) -{ - $array = []; +function get_bgp_array($vars) { + $array = []; - // With pagination? (display page numbers in header) - $array['pagination'] = (isset($vars['pagination']) && $vars['pagination']); - pagination($vars, 0, TRUE); // Get default pagesize/pageno - $array['pageno'] = $vars['pageno']; - $array['pagesize'] = $vars['pagesize']; - $start = $array['pagesize'] * $array['pageno'] - $array['pagesize']; - $pagesize = $array['pagesize']; + // With pagination? (display page numbers in header) + //$array['pagination'] = (isset($vars['pagination']) && $vars['pagination']); + $array['pagination'] = TRUE; + pagination($vars, 0, TRUE); // Get default pagesize/pageno + $array['pageno'] = $vars['pageno']; + $array['pagesize'] = $vars['pagesize']; + $start = $array['pagesize'] * $array['pageno'] - $array['pagesize']; + $pagesize = $array['pagesize']; - // Require cached IDs from html/includes/cache-data.inc.php - $cache_bgp = &$GLOBALS['cache']['bgp']; + // Require cached IDs from html/includes/cache-data.inc.php + $cache_bgp = &$GLOBALS['cache']['bgp']; - // Begin query generate - $param = array(); - $where = ' WHERE 1 '; - foreach ($vars as $var => $value) { - if ($value != '') { - switch ($var) { - case "group": - case "group_id": - $values = get_group_entities($value); - $where .= generate_query_values($values, 'bgpPeer_id'); - break; - case 'device': - case 'device_id': - $where .= generate_query_values($value, 'device_id'); - break; - case 'peer': - case 'peer_id': - $where .= generate_query_values($value, 'peer_device_id'); - break; - case 'local_ip': - $where .= generate_query_values(ip_uncompress($value), 'bgpPeerLocalAddr'); - break; - case 'peer_ip': - $where .= generate_query_values(ip_uncompress($value), 'bgpPeerRemoteAddr'); - break; - case 'local_as': - $where .= generate_query_values(bgp_asdot_to_asplain($value), 'local_as'); - break; - case 'peer_as': - $where .= generate_query_values(bgp_asdot_to_asplain($value), 'bgpPeerRemoteAs'); - break; - case 'type': - if ($value === 'external' || $value === 'ebgp') { - $where .= generate_query_values($cache_bgp['external'], 'bgpPeer_id'); - } elseif ($value === 'internal' || $value === 'ibgp') { - $where .= generate_query_values($cache_bgp['internal'], 'bgpPeer_id'); - } - break; - case 'adminstatus': - if ($value === 'stop') { - $where .= generate_query_values($cache_bgp['start'], 'bgpPeer_id', '!='); // NOT IN - } elseif ($value === 'start') { - $where .= generate_query_values($cache_bgp['start'], 'bgpPeer_id'); - } - break; - case 'state': - if ($value === 'down') { - $where .= generate_query_values($cache_bgp['up'], 'bgpPeer_id', '!='); // NOT IN - } elseif ($value === 'up') { - $where .= generate_query_values($cache_bgp['up'], 'bgpPeer_id'); - } - break; - } - } - } + // Begin query generate + $param = []; + $where = []; + foreach ($vars as $var => $value) { + if (!safe_empty($value)) { + switch ($var) { + case "group": + case "group_id": + $values = get_group_entities($value); + $where[] = generate_query_values_ng($values, 'bgpPeer_id'); + break; - // Show peers only for permitted devices - $query_permitted = generate_query_values($cache_bgp['permitted'], 'bgpPeer_id'); + case 'device': + case 'device_id': + $where[] = generate_query_values_ng($value, 'device_id'); + break; - $query = 'FROM `bgpPeers`'; - $query_count = 'SELECT COUNT(*) ' . $query . $where . $query_permitted; // Use only bgpPeer_id and device_id in query! + case 'peer': + case 'peer_id': + $where[] = generate_query_values_ng($value, 'peer_device_id'); + break; - $query .= ' JOIN `devices` USING (`device_id`) '; + case 'local_ip': + $where[] = generate_query_values_ng(ip_uncompress($value), 'bgpPeerLocalAddr'); + break; - //$query .= ' LEFT JOIN `bgpPeers-state` AS S ON `bgpPeer_id` = S.`bgpPeer_id`'; - //$query .= ' LEFT JOIN `devices` AS D ON `device_id` = D.`device_id`'; - $query .= $where . $query_permitted; + case 'peer_ip': + $where[] = generate_query_values_ng(ip_uncompress($value), 'bgpPeerRemoteAddr'); + break; - $query = 'SELECT `hostname`, `bgpLocalAs`, bgpPeers.* ' . $query; - - $sort_dir = $vars['sort_order'] === 'desc' ? ' DESC' : ''; + case 'local_as': + $where[] = generate_query_values_ng(bgp_asdot_to_asplain($value), 'local_as'); + break; - switch($vars['sort']) { - case "device": - $sort = " ORDER BY `hostname`".$sort_dir; - break; + case 'peer_as': + if (is_string($value) && preg_match_all('/AS(?[\d\.]+):/', $value, $matches)) { + //r($matches); + $value = $matches['as']; + } + $where[] = generate_query_values_ng(bgp_asdot_to_asplain($value), 'bgpPeerRemoteAs'); + break; - case "local_as": - $sort = " ORDER BY `local_as`$sort_dir, `virtual_name`$sort_dir"; - break; + case 'type': + if ($value === 'external' || $value === 'ebgp') { + $where[] = generate_query_values_ng($cache_bgp['external'], 'bgpPeer_id'); + } elseif ($value === 'internal' || $value === 'ibgp') { + $where[] = generate_query_values_ng($cache_bgp['internal'], 'bgpPeer_id'); + } + break; - case "peer_ip": - $sort = " ORDER BY `bgpPeerRemoteAddr`".$sort_dir; - break; - - case "peer_as": - $sort = " ORDER BY `bgpPeerRemoteAs`".$sort_dir; - break; + case 'adminstatus': + if ($value === 'stop') { + $where[] = generate_query_values_ng($cache_bgp['start'], 'bgpPeer_id', '!='); // NOT IN + } elseif ($value === 'start') { + $where[] = generate_query_values_ng($cache_bgp['start'], 'bgpPeer_id'); + } + break; case 'state': - $sort = " ORDER BY `bgpPeerAdminStatus`".$sort_dir.", `bgpPeerState`".$sort_dir; - break; - - case 'uptime': - $sort = " ORDER BY `bgpPeerFsmEstablishedTime`".$sort_dir; - break; - - default: - $sort = " ORDER BY `hostname`".$sort_dir.", `bgpPeerRemoteAs`".$sort_dir.", `bgpPeerRemoteAddr`".$sort_dir; + if ($value === 'down') { + $where[] = generate_query_values_ng($cache_bgp['up'], 'bgpPeer_id', '!='); // NOT IN + } elseif ($value === 'up') { + $where[] = generate_query_values_ng($cache_bgp['up'], 'bgpPeer_id'); + } + break; + } } + } - $query .= $sort; - $query .= " LIMIT $start,$pagesize"; + // Show peers only for permitted devices + if ($_SESSION['userlevel'] < 5) { + $where[] = generate_query_values_ng($cache_bgp['permitted'], 'bgpPeer_id'); + } elseif (!$GLOBALS['config']['web_show_disabled'] && $GLOBALS['cache']['devices']['stat']['disabled']) { + // Exclude disabled devices for Global Read+ + $where[] = generate_query_values_ng($GLOBALS['cache']['devices']['disabled'], 'device_id', '!='); + } - $peer_devices = array(); - // Query BGP - foreach (dbFetchRows($query, $param) as $entry) - { - humanize_bgp($entry); + if (!safe_empty($where)) { + $where = 'WHERE ' . implode(' AND ', $where); + } else { + $where = ''; + } + //r($where); - // Collect peer devices for AFI/SAFI - $peer_devices[$entry['device_id']] = 1; + $query_count = 'SELECT COUNT(*) FROM `bgpPeers` ' . $where; // Use only bgpPeer_id and device_id in query! + $array['count'] = dbFetchCell($query_count, $param); + //$array['count'] = dbFetchCell($query_count, $param, TRUE); - $array['entries'][] = $entry; + // Pagination + $array['pagination_html'] = pagination($vars, $array['count']); + + $query = 'SELECT `hostname`, `bgpLocalAs`, `bgpPeers`.*'; + $query .= ' FROM `bgpPeers`'; + $query .= ' JOIN `devices` USING (`device_id`) '; + $query .= $where; + + $sort_dir = $vars['sort_order'] === 'desc' ? ' DESC' : ''; + + switch($vars['sort']) { + case "device": + $sort = " ORDER BY `hostname`".$sort_dir; + break; + + case "local_as": + $sort = " ORDER BY `local_as`$sort_dir, `virtual_name`$sort_dir"; + break; + + case "peer_ip": + $sort = " ORDER BY `bgpPeerRemoteAddr`".$sort_dir; + break; + + case "peer_as": + $sort = " ORDER BY `bgpPeerRemoteAs`".$sort_dir; + break; + + case 'state': + $sort = " ORDER BY `bgpPeerAdminStatus`".$sort_dir.", `bgpPeerState`".$sort_dir; + break; + + case 'uptime': + $sort = " ORDER BY `bgpPeerFsmEstablishedTime`".$sort_dir; + break; + + default: + $sort = " ORDER BY `hostname`".$sort_dir.", `bgpPeerRemoteAs`".$sort_dir.", `bgpPeerRemoteAddr`".$sort_dir; + } + + $query .= $sort; + $query .= " LIMIT $start,$pagesize"; + + $peer_devices = []; + // Query BGP + foreach (dbFetchRows($query, $param) as $entry) { + humanize_bgp($entry); + + // Collect peer devices for AFI/SAFI + $peer_devices[$entry['device_id']] = 1; + + $array['entries'][] = $entry; + } + + // Query AFI/SAFI + if (!safe_empty($peer_devices)) { + $query_afi = 'SELECT * FROM `bgpPeers_cbgp` WHERE 1' . generate_query_values_and(array_keys($peer_devices), 'device_id'); + + foreach (dbFetchRows($query_afi) as $entry) { + $array['afisafi'][$entry['device_id']][$entry['bgpPeer_id']][$entry['afi'] . '.' . $entry['safi']] = [ 'afi' => $entry['afi'], 'safi' => $entry['safi'] ]; } + } - // Query AFI/SAFI - if (count($peer_devices)) - { - $query_afi = 'SELECT * FROM `bgpPeers_cbgp` WHERE 1' . generate_query_values(array_keys($peer_devices), 'device_id'); - foreach (dbFetchRows($query_afi) as $entry) - { - $array['afisafi'][$entry['device_id']][$entry['bgpPeer_id']][$entry['afi'] . '.' . $entry['safi']] = array('afi' => $entry['afi'], 'safi' => $entry['safi']); - } - } - - // Query BGP peers count - if ($array['pagination']) { - $array['count'] = dbFetchCell($query_count, $param); - $array['pagination_html'] = pagination($vars, $array['count']); - } else { - $array['count'] = safe_count($array['entries']); - } - - return $array; + return $array; } // EOF diff --git a/html/includes/print/rows.inc.php b/html/includes/print/rows.inc.php index 6e59ad1d..79a27dbf 100644 --- a/html/includes/print/rows.inc.php +++ b/html/includes/print/rows.inc.php @@ -6,7 +6,7 @@ * * @package observium * @subpackage web - * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2021 Observium Limited + * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2022 Observium Limited * */ @@ -26,39 +26,54 @@ function generate_box_open($args = []) { if (isset($args['title'])) { $return .= '
'.PHP_EOL; if (isset($args['url'])) { $return .= ''; } - if (isset($args['icon'])) { $return .= ''; } + if (isset($args['icon'])) { $return .= get_icon($args['icon']); } $return .= '<' . (isset($args['title-element']) ? $args['title-element'] : 'h3').' class="box-title"'; $return .= isset($args['title-style']) ? ' style="'.$args['title-style'].'"' : ''; $return .= '>'; - $return .= $args['title'].''.PHP_EOL; + $return .= escape_html($args['title']).''.PHP_EOL; if (isset($args['url'])) { $return .= ''; } if (isset($args['header-controls']) && is_array($args['header-controls']['controls'])) { $return .= '
'; foreach($args['header-controls']['controls'] as $control) { - if (isset($control['anchor']) && $control['anchor'] == TRUE) { + $anchor = (isset($control['anchor']) && $control['anchor']) || + (isset($control['config']) && !empty($control['config'])); + if ($anchor) { $return .= ' "ajax_settings('".$control['config']."', '".$control['value']."');" ]; + } } else { //$return .= ' onclick="return false;"'; } + // Additional class $return .= ' class="btn btn-box-tool'; - if (isset($control['class'])) { $return .= ' '.$control['class']; } + if (isset($control['class'])) { + $return .= ' ' . escape_html($control['class']); + } $return .= '"'; - if (isset($control['data'])) { $return .= ' '.$control['data']; } + // Additional params (raw string or array with params + if (isset($control['data'])) { + $params = is_array($control['data']) ? generate_html_attribs($control['data']) : $control['data']; + $return .= ' '.$params; + } $return .= '>'; - if (isset($control['icon'])) { $return .= ' '; } + if (isset($control['icon'])) { $return .= get_icon($control['icon']).' '; } if (isset($control['text'])) { $return .= $control['text']; } - if (isset($control['anchor']) && $control['anchor'] == TRUE) { + if ($anchor) { $return .= ''; } else { $return .= ''; @@ -455,7 +470,7 @@ SCRIPT; foreach ($content as $key => $value) { echo('
'.PHP_EOL); $item = [ - 'id' => "${htmlname}[key][]", + 'id' => "{$htmlname}[key][]", 'name' => 'Key', //'width' => '500px', 'class' => 'input-large', @@ -470,7 +485,7 @@ SCRIPT; } echo(generate_form_element($item)); $item = [ - 'id' => "${htmlname}[value][]", + 'id' => "{$htmlname}[value][]", 'name' => 'Value', //'width' => '500px', 'class' => 'input-xlarge', @@ -509,9 +524,9 @@ SCRIPT; // https://metallurgical.github.io/jquery-metal-clone/ register_html_resource('js', 'jquery.metalClone.js'); // jquery.metalClone.min.js register_html_resource('css', 'metalClone.css'); - $clone_target = "${htmlname}_clone_row"; - $clone_button = "${htmlname}[add]"; - $clone_remove = "${htmlname}[remove]"; + $clone_target = "{$htmlname}_clone_row"; + $clone_button = "{$htmlname}[add]"; + $clone_remove = "{$htmlname}[remove]"; $remove_text = ''; //'Remove'; if ($readonly || (bool)$locked) { $clone_disabled = 'disabled: \'1\','; @@ -531,26 +546,26 @@ SCRIPT; //console.log(element); var regex = /(metalElement\d{0,})/g; var eclass = element.attr('class'); - var others = \$('[id=${clone_target}]').not(element); + var others = \$('[id={$clone_target}]').not(element); $.each(others, function () { \$(this).addClass(eclass); // Add button icon - //console.log(\$(this).find('#${clone_button}')); - \$(this).find('[id=\"${clone_button}\"]').prepend(' ').prepend(\$('', { class: '${icon_add}' })); + //console.log(\$(this).find('#{$clone_button}')); + \$(this).find('[id=\"{$clone_button}\"]').prepend(' ').prepend(\$('', { class: '{$icon_add}' })); // Remove button \$(this).append(\$('