$item)
{
$path = $config['html_dir'].'/includes/entities/'.$entity_type.'.inc.php';
if (is_file($path)) { include($path); }
}
/**
* Used for replace some strings at end of run all html scripts
*
* @param string $buffer HTML buffer from ob_start()
* @return string Changed buffer
*/
function html_callback($buffer) {
global $config;
// Do not disclose version to unauthorized requests
$version_param = $_SESSION['authenticated'] ? '?v=' . OBSERVIUM_VERSION : '';
// Install registered CSS/JS links
$types = array(
'css' => ' ' . PHP_EOL,
'style' => ' ' . PHP_EOL,
'js' => ' ' . PHP_EOL,
'script' => ' ' . PHP_EOL,
'meta' => ' ' . PHP_EOL,
);
foreach ($types as $type => $string)
{
$uptype = strtoupper($type);
if (isset($GLOBALS['cache_html']['resources'][$type]))
{
$$type = '' . PHP_EOL;
foreach (array_unique($GLOBALS['cache_html']['resources'][$type]) as $content) // Do not use global $cache variable, because it is reset before flush ob_cache
{
if (is_array($content))
{
// for meta
foreach($content as $param => $value)
{
$string = str_replace('%%STRING_'.$param.'%%', $value, $string);
}
$$type .= $string;
} else {
$$type .= str_replace('%%STRING%%', $content, $string);
}
}
$$type .= ' ' . PHP_EOL;
$buffer = str_replace('' . PHP_EOL, $$type, $buffer);
} else {
// Clean template string
$buffer = str_replace('', '', $buffer);
}
}
// Replace page title as specified by the page modules
if (!is_array($GLOBALS['cache_html']['title']))
{
// Title not set by any page, fall back to nicecase'd page name:
if ($GLOBALS['vars']['page'] && $_SESSION['authenticated'])
{
$GLOBALS['cache_html']['title'] = array(nicecase($GLOBALS['vars']['page']));
} else {
// HALP. Likely main page, doesn't need anything else...
$GLOBALS['cache_html']['title'] = array();
}
}
// If suffix is set, put it in the back
if ($config['page_title_suffix']) { $GLOBALS['cache_html']['title'][] = $config['page_title_suffix']; }
// If prefix is set, put it in front
if ($config['page_title_prefix']) { array_unshift($GLOBALS['cache_html']['title'], $config['page_title_prefix']); }
// Build title with separators
$title = implode($config['page_title_separator'], $GLOBALS['cache_html']['title']);
/*
// Replace title placeholder by actual title
$buffer = str_replace('##TITLE##', escape_html($title), $buffer);
// Page panel
$buffer = str_replace('##PAGE_PANEL##', $GLOBALS['cache_html']['page_panel'], $buffer);
// UI Alerts
//$buffer = str_replace('##UI_ALERTS##', $GLOBALS['ui_alerts'], $buffer);
$buffer = str_replace('##UI_ALERTS##', implode(PHP_EOL, $GLOBALS['cache_html']['ui_alerts']), $buffer);
*/
$replace = [
// Replace title placeholder by actual title
'##TITLE##' => escape_html($title),
// Page panel
'##PAGE_PANEL##' => $GLOBALS['cache_html']['page_panel'],
// UI Alerts
//'##UI_ALERTS##' => $GLOBALS['ui_alerts'],
'##UI_ALERTS##' => implode(PHP_EOL, (array)$GLOBALS['cache_html']['ui_alerts']),
];
//$buffer = array_str_replace($replace, $buffer, TRUE);
// Return modified HTML page source
return array_str_replace($replace, $buffer, TRUE);
}
/**
* Parse $_GET, $_POST and REQUEST_URI into $vars array
*
* @param array|string $vars_order Request variables order (POST, URI, GET)
* @param boolean $auth this var or ($_SESSION['authenticated']) used for allow to use var_decode()
* @return array array of vars
*/
function get_vars($vars_order = [], $auth = FALSE) {
if (is_string($vars_order)) {
$vars_order = explode(' ', $vars_order);
} elseif (empty($vars_order) || !is_array($vars_order)) {
$vars_order = [ 'POST', 'URI', 'GET' ]; // Default order
}
// Content-Type=>application/x-www-form-urlencoded
$content_type = isset($_SERVER['HTTP_CONTENT_TYPE']) ? $_SERVER['HTTP_CONTENT_TYPE'] : $_SERVER['CONTENT_TYPE'];
// https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20Injection
// XSS script regex
//
STATE;
return $state;
}
/**
* Generate Percentage Bar
*
* This function generates an Observium percentage bar from a supplied array of arguments.
* It is possible to draw a bar that does not work at all,
* So care should be taken to make sure values are valid.
*
* @param array $args
* @return string
*/
// TESTME needs unit testing
function percentage_bar($args)
{
if (strlen($args['bg'])) { $style .= 'background-color:'.$args['bg'].';'; }
if (strlen($args['border'])) { $style .= 'border-color:'.$args['border'].';'; }
if (strlen($args['width'])) { $style .= 'width:'.$args['width'].';'; }
if (strlen($args['text_c'])) { $style_b .= 'color:'.$args['text_c'].';'; }
$total = '0';
$output = '
";
$url = generate_ap_url($args);
if (port_permitted($args['interface_id'], $args['device_id'])) {
return overlib_link($url, $text, $content, $class, $escape);
}
return $text;
}
/**
* Returns TRUE if the device is marked as ignored in the cache.
*
* @param $device_id
*
* @return bool
*/
function device_is_ignored($device_id) {
return isset($GLOBALS['cache']['devices']['ignored']) && in_array($device_id, $GLOBALS['cache']['devices']['ignored'], TRUE);
}
// TESTME needs unit testing
// DOCME needs phpdoc block
function generate_ap_url($ap, $vars=array())
{
return generate_url(array('page' => 'device', 'device' => $ap['device_id'], 'tab' => 'accesspoint', 'ap' => $ap['accesspoint_id']), $vars);
}
/**
* Generate SQL WHERE string with check permissions and ignores for device_id, port_id and other
*
* Note, this function uses comparison operator IN. Max number of values in the IN list
* is limited by the 'max_allowed_packet' option (default: 1048576)
*
* Usage examples:
* generate_query_permitted()
* ' AND `device_id` IN (1,4,8,33) AND `device_id` NOT IN (66) AND (`device_id` != '' AND `device_id` IS NOT NULL) '
* generate_query_permitted(array('device'), array('device_table' => 'D'))
* ' AND `D`.`device_id` IN (1,4,8,33) AND `D`.`device_id` NOT IN (66) AND (`D`.`device_id` != '' AND `D`.`device_id` IS NOT NULL) '
* generate_query_permitted(array('device', 'port'), array('port_table' => 'I')) ==
* ' AND `device_id` IN (1,4,8,33) AND `device_id` NOT IN (66) AND (`device_id` != '' AND `device_id` IS NOT NULL)
* AND `I`.`port_id` IN (1,4,8,33) AND `I`.`port_id` NOT IN (66) AND (`I`.`port_id` != '' AND `I`.`port_id` IS NOT NULL) '
* generate_query_permitted(array('device', 'port'), array('port_table' => 'I', 'hide_ignored' => TRUE))
* This additionaly exclude all ignored devices and ports
*
* @uses html/includes/cache-data.inc.php
* @global integer $_SESSION['userlevel']
* @global boolean $GLOBALS['config']['web_show_disabled']
* @global array $GLOBALS['permissions']
* @global array $GLOBALS['cache']['devices']
* @global array $GLOBALS['cache']['ports']
* @global string $GLOBALS['vars']['page']
* @param array|string $type_array Array with permission types, currently allowed 'devices', 'ports'
* @param array $options Options for each permission type: device_table, port_table, hide_ignored, hide_disabled
* @return string
*/
// TESTME needs unit testing
function generate_query_permitted($type_array = [ 'device' ], $options = []) {
if (!is_array($type_array)) {
$type_array = [ $type_array ];
}
$user_limited = $_SESSION['userlevel'] < 5;
$page = $GLOBALS['vars']['page'];
// If device IDs stored in SESSION use it (used in ajax)
//if (!isset($GLOBALS['cache']['devices']) && isset($_SESSION['cache']['devices']))
//{
// $GLOBALS['cache']['devices'] = $_SESSION['cache']['devices'];
//}
if (!isset($GLOBALS['permissions'])) {
// Note, this function must used after load permissions list!
print_error("Function ".__FUNCTION__."() on page '$page' called before include cache-data.inc.php or something wrong with caching permissions. Please report this to developers!");
}
// Use option hide_disabled if passed or use config
$options['hide_disabled'] = (isset($options['hide_disabled']) ? (bool)$options['hide_disabled'] : !$GLOBALS['config']['web_show_disabled']);
//$query_permitted = '';
$query_part = [];
foreach ($type_array as $type) {
switch ($type) {
// Devices permission query
case 'device':
case 'devices':
$column = '`device_id`';
$query_permitted = [];
if (isset($options['device_table'])) { $column = '`'.$options['device_table'].'`.'.$column; }
// Show only permitted devices
if ($user_limited) {
if (safe_count($GLOBALS['permissions']['device'])) {
$query_permitted[] = " $column IN (".
implode(',', array_keys($GLOBALS['permissions']['device'])).
')';
} else {
// Exclude all entries, because there is no permitted devices
$query_permitted[] = ' 0';
}
}
// Also don't show ignored and disabled devices (except on 'device' and 'devices' pages)
$devices_excluded = [];
if (strpos($page, 'device') !== 0) {
if ($options['hide_ignored'] && safe_count($GLOBALS['cache']['devices']['ignored'])) {
$devices_excluded = array_merge($devices_excluded, $GLOBALS['cache']['devices']['ignored']);
}
if ($options['hide_disabled'] && safe_count($GLOBALS['cache']['devices']['disabled'])) {
$devices_excluded = array_merge($devices_excluded, $GLOBALS['cache']['devices']['disabled']);
}
}
if (count($devices_excluded)) {
// Set query with excluded devices
$query_permitted[] = " $column NOT IN (".
implode(',', array_unique($devices_excluded)).
')';
}
// At the end excluded entries with empty/null device_id (wrong entries)
//$query_permitted[] = " ($column != '' AND $column IS NOT NULL)";
$query_permitted[] = " $column IS NOT NULL"; // Note: SELECT '' = 0; is TRUE
$query_part[] = implode(" AND ", $query_permitted);
unset($query_permitted);
break;
// Ports permission query
case 'port':
case 'ports':
$column = '`port_id`';
if (isset($options['port_table'])) {
$column = '`'.$options['port_table'].'`.'.$column;
}
// If port IDs stored in SESSION use it (used in ajax)
//if (!isset($GLOBALS['cache']['ports']) && isset($_SESSION['cache']['ports']))
//{
// $GLOBALS['cache']['ports'] = $_SESSION['cache']['ports'];
//}
// Show only permitted ports
if ($user_limited) {
if (safe_count($GLOBALS['permissions']['port'])) {
$query_permitted[] = " $column IN (" .
implode(',', array_keys($GLOBALS['permissions']['port'])) .
')';
} else {
// Exclude all entries, because there is no permitted ports
$query_permitted[] = '0';
}
}
$ports_excluded = array();
// Don't show ports with disabled polling.
if (safe_count($GLOBALS['cache']['ports']['poll_disabled'])) {
$ports_excluded = array_merge($ports_excluded, $GLOBALS['cache']['ports']['poll_disabled']);
//foreach ($GLOBALS['cache']['ports']['poll_disabled'] as $entry)
//{
// $ports_excluded[] = $entry;
//}
//$ports_excluded = array_unique($ports_excluded);
}
// Don't show deleted ports (except on 'deleted-ports' page)
if ($page !== 'deleted-ports' && safe_count($GLOBALS['cache']['ports']['deleted'])) {
$ports_excluded = array_merge($ports_excluded, $GLOBALS['cache']['ports']['deleted']);
//foreach ($GLOBALS['cache']['ports']['deleted'] as $entry)
//{
// $ports_excluded[] = $entry;
//}
//$ports_excluded = array_unique($ports_excluded);
}
if ($page !== 'device' && !in_array('device', $type_array)) {
// Don't show ports for disabled devices (except on 'device' page or if 'device' permissions already queried)
if ($options['hide_disabled'] && !$user_limited && safe_count($GLOBALS['cache']['ports']['device_disabled'])) {
$ports_excluded = array_merge($ports_excluded, $GLOBALS['cache']['ports']['device_disabled']);
//foreach ($GLOBALS['cache']['ports']['device_disabled'] as $entry)
//{
// $ports_excluded[] = $entry;
//}
//$ports_excluded = array_unique($ports_excluded);
}
// Don't show ports for ignored devices (except on 'device' page)
if ($options['hide_ignored'] && safe_count($GLOBALS['cache']['ports']['device_ignored'])) {
$ports_excluded = array_merge($ports_excluded, $GLOBALS['cache']['ports']['device_ignored']);
//foreach ($GLOBALS['cache']['ports']['device_ignored'] as $entry)
//{
// $ports_excluded[] = $entry;
//}
//$ports_excluded = array_unique($ports_excluded);
}
}
// Don't show ignored ports (only on some pages!)
if (($page === 'overview' || $options['hide_ignored']) && safe_count($GLOBALS['cache']['ports']['ignored'])) {
$ports_excluded = array_merge($ports_excluded, $GLOBALS['cache']['ports']['ignored']);
//foreach ($GLOBALS['cache']['ports']['ignored'] as $entry)
//{
// $ports_excluded[] = $entry;
//}
//$ports_excluded = array_unique($ports_excluded);
}
unset($entry);
if (count($ports_excluded)) {
// Set query with excluded ports
$query_permitted[] = $column . " NOT IN (".
implode(',', array_unique($ports_excluded)).
')';
}
// At the end excluded entries with empty/null port_id (wrong entries)
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 && safe_count($query_permitted)) {
// FIXME. derp code, need rewrite
//$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);
if (!safe_empty($query_permitted)) {
$query_part[] = str_replace(" AND OR ", ' OR ', $query_permitted);
}
unset($query_permitted);
break;
case 'sensor':
case 'sensors':
// For sensors
// FIXME -- this is easily generifyable, just use translate_table_array()
$column = '`sensor_id`';
if (isset($options['sensor_table'])) { $column = '`'.$options['sensor_table'].'`.'.$column; }
// If IDs stored in SESSION use it (used in ajax)
//if (!isset($GLOBALS['cache']['sensors']) && isset($_SESSION['cache']['sensors']))
//{
// $GLOBALS['cache']['sensors'] = $_SESSION['cache']['sensors'];
//}
// Show only permitted entities
if ($user_limited)
{
if (safe_count($GLOBALS['permissions']['sensor'])) {
$query_permitted .= " $column IN (";
$query_permitted .= implode(',', array_keys($GLOBALS['permissions']['sensor']));
$query_permitted .= ')';
} else {
// Exclude all entries, because there are no permitted entities
$query_permitted .= '0';
}
$query_part[] = $query_permitted;
unset($query_permitted);
}
break;
case 'alert':
case 'alerts':
// For generic alert
$column = '`alert_table_id`';
// Show only permitted entities
if ($user_limited)
{
if (safe_count($GLOBALS['permissions']['alert'])) {
$query_permitted .= " $column IN (";
$query_permitted .= implode(',', array_keys($GLOBALS['permissions']['alert']));
$query_permitted .= ')';
} else {
// Exclude all entries, because there are no permitted entities
$query_permitted .= '0';
}
$query_part[] = $query_permitted;
unset($query_permitted);
}
break;
case 'bill':
case 'bills':
// For bills
break;
}
}
if (count($query_part))
{
//r($query_part);
if ($user_limited)
{
// Limited user must use OR for include multiple entities
$query_permitted = " AND ((".implode(") OR (", $query_part)."))";
} else {
// Unlimited used must use AND for exclude multiple hidden entities
$query_permitted = " AND ((".implode(") AND (", $query_part)."))";
}
}
$query_permitted .= ' ';
//r($query_permitted);
return $query_permitted;
}
// TESTME needs unit testing
// DOCME needs phpdoc block
function dashboard_exists($dash_id)
{
return dbExist('dashboards', '`dash_id` = ?', [ $dash_id ]);
//return count(dbFetchRow("SELECT * FROM `dashboards` WHERE `dash_id` = ?", array($dash_id)));
}
// TESTME needs unit testing
// DOCME needs phpdoc block
function get_user_prefs($user_id) {
$prefs = array();
foreach (dbFetchRows("SELECT * FROM `users_prefs` WHERE `user_id` = ?", array($user_id)) as $entry) {
$prefs[$entry['pref']] = $entry;
}
return $prefs;
}
// TESTME needs unit testing
// DOCME needs phpdoc block
function get_user_pref($user_id, $pref) {
if ($entry = dbFetchRow("SELECT `value` FROM `users_prefs` WHERE `user_id` = ? AND `pref` = ?", array($user_id, $pref))) {
return $entry['value'];
}
return NULL;
}
// TESTME needs unit testing
// DOCME needs phpdoc block
function set_user_pref($user_id, $pref, $value) {
//if (dbFetchCell("SELECT COUNT(*) FROM `users_prefs` WHERE `user_id` = ? AND `pref` = ?", array($user_id, $pref)))
if (dbExist('users_prefs', '`user_id` = ? AND `pref` = ?', array($user_id, $pref))) {
$id = dbUpdate(array('value' => $value), 'users_prefs', '`user_id` = ? AND `pref` = ?', array($user_id, $pref));
} else {
$id = dbInsert(array('user_id' => $user_id, 'pref' => $pref, 'value' => $value), 'users_prefs');
}
return $id;
}
// TESTME needs unit testing
// DOCME needs phpdoc block
function del_user_pref($user_id, $pref) {
return dbDelete('users_prefs', "`user_id` = ? AND `pref` = ?", array($user_id, $pref));
}
// Load configuration from user SQL into supplied variable (pass by reference!)
function load_user_config(&$load_config, $user_id) {
global $config;
/*
$config_defined = get_defined_settings(); // defined in config.php
// Override some whitelisted definitions from config.php
foreach ($config_defined as $key => $definition) {
//if (is_null($config['definitions_whitelist'])) { print_error("NULL on $key"); } else { print_warning("ARRAY on $key"); }
if (in_array($key, $GLOBALS['config']['definitions_whitelist']) && // Always use global config here!
is_array($definition) && is_array($config[$key]))
{
// Fix mib definitions for dumb users, who copied old defaults.php
// where mibs was just MIB => 1,
// This definition should be array
// Fetch first element and validate that this is array
if ($key === 'mibs' && !is_array(array_shift(array_values($definition)))) { continue; }
$config[$key] = array_replace_recursive($config[$key], $definition);
}
}
*/
if (!$prefs = dbFetchRows("SELECT * FROM `users_prefs` WHERE `user_id` = ? AND `pref` NOT IN (?, ?)", [ $user_id, 'atom_key', 'api_key' ])) {
// No user prefs set
return FALSE;
}
// Always use global config here!
include($config['install_dir'] . '/includes/config-variables.inc.php');
// Same format as in global config!
// User prefs always override global config
//foreach (dbFetchRows("SELECT * FROM `config`") as $item) {
foreach ($prefs as $item) {
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.");
continue;
}
// Convert boo|bee|baa config value into $config['boo']['bee']['baa']
$tree = explode('|', $item['pref']);
//if (array_key_exists($tree[0], $config_defined)) { continue; } // This complete skip option if first level key defined in $config
// Unfortunately, I don't know of a better way to do this...
// Perhaps using array_map() ? Unclear... hacky. :[
// FIXME use a loop with references! (cf. nested location menu)
switch (count($tree)) {
case 1:
//if (isset($config_defined[$tree[0]])) { continue; } // Note, false for null values
//if (array_key_exists($tree[0], $config_defined)) { break; }
$load_config[$tree[0]] = safe_unserialize($item['value']);
//r($load_config[$tree[0]]);
//r($_SESSION);
break;
case 2:
//if (isset($config_defined[$tree[0]][$tree[1]])) { break; } // Note, false for null values
$load_config[$tree[0]][$tree[1]] = safe_unserialize($item['value']);
break;
case 3:
//if (isset($config_defined[$tree[0]][$tree[1]][$tree[2]])) { break; } // Note, false for null values
$load_config[$tree[0]][$tree[1]][$tree[2]] = safe_unserialize($item['value']);
break;
case 4:
//if (isset($config_defined[$tree[0]][$tree[1]][$tree[2]][$tree[3]])) { break; } // Note, false for null values
$load_config[$tree[0]][$tree[1]][$tree[2]][$tree[3]] = safe_unserialize($item['value']);
break;
case 5:
//if (isset($config_defined[$tree[0]][$tree[1]][$tree[2]][$tree[3]][$tree[4]])) { break; } // Note, false for null values
$load_config[$tree[0]][$tree[1]][$tree[2]][$tree[3]][$tree[4]] = safe_unserialize($item['value']);
break;
default:
print_error("Too many array levels for SQL configuration parser!");
}
}
}
function process_sql_vars($vars) {
global $config;
// Always use global config here!
include($config['install_dir'] . '/includes/config-variables.inc.php');
$deletes = array();
$sets = array();
$errors = array();
$set_attribs = array(); // set obs_attribs
// Submit button pressed
foreach ($vars as $varname => $value) {
if (str_starts($varname, 'varset_')) {
$varname = substr($varname, 7);
$sqlname = str_replace('__', '|', $varname);
$sqlset = get_var_true($value); // value sets in sql
$content = $vars[$varname];
$confname = '$config[\'' . implode("']['",explode('|',$sqlname)) . '\']';
$section = $config_variable[$sqlname]['section'];
if ($vars[$varname . '_custom']) {
$ok = FALSE;
if (isset($config_variable[$sqlname]['edition']) && $config_variable[$sqlname]['edition'] != OBSERVIUM_EDITION) {
// Skip variables not allowed for current Observium edition
continue;
}
if (isset($config_sections[$section]['edition']) && $config_sections[$section]['edition'] != OBSERVIUM_EDITION) {
// Skip sections not allowed for current Observium edition
continue;
}
// Split enum|foo|bar into enum foo|bar
list($vartype, $varparams) = explode('|', $config_variable[$sqlname]['type'], 2);
$params = array();
// If a callback function is defined, use this to fill params.
if ($config_variable[$sqlname]['params_call'] && function_exists($config_variable[$sqlname]['params_call'])) {
$params = call_user_func($config_variable[$sqlname]['params_call']);
// Else if the params are defined directly, use these.
} elseif (is_array($config_variable[$sqlname]['params'])) {
$params = $config_variable[$sqlname]['params'];
} elseif (!empty($varparams)) {
// Else use parameters specified in variable type (e.g. enum|1|2|5|10)
foreach (explode('|', $varparams) as $param) {
$params[$param] = array('name' => nicecase($param));
}
}
switch ($vartype) {
case 'int':
case 'integer':
case 'float':
if (is_numeric($content)) {
$ok = TRUE;
} else {
$errors[] = $config_variable[$sqlname]['name'] . " ($confname) should be of numeric type. Setting '" . escape_html($content) . "' ignored.";
}
break;
case 'bool':
case 'boolean':
switch ($content) {
case 'on':
case '1':
$content = 1;
$ok = TRUE;
break;
case 'off': // Won't actually happen. When "unchecked" the field is simply not transmitted...
case '0':
case '': // ... which we catch here.
$content = 0;
$ok = TRUE;
break;
default:
$ok = FALSE;
$errors[] = $config_variable[$sqlname]['name'] . " ($confname) should be of type bool. Setting '" . escape_html($content) . "' ignored.";
}
break;
case 'enum':
if (!array_key_exists($content, $params)) {
$ok = FALSE;
$errors[] = $config_variable[$sqlname]['name'] . " ($confname) should be one of " . implode(', ', $params) . ". Setting '" . escape_html($content) . "' ignored.";
} else {
$ok = TRUE;
}
break;
case 'enum-array':
//r($content);
//r($params);
foreach ($content as $value) {
// Check all values
if (!array_key_exists($value, $params)) {
$ok = FALSE;
$errors[] = $config_variable[$sqlname]['name'] . " ($confname) all values should be one of this list " . implode(', ', $params) . ". Settings '" . implode(', ', $content) . "' ignored.";
break;
}
$ok = TRUE;
}
break;
case 'enum-key-value':
//r($content);
//r($params);
if (isset($content['key'], $content['value'])) {
$tmp = $content;
$content = [];
foreach ($tmp['key'] as $i => $key) {
if (safe_empty($key) && safe_empty($tmp['value'][$i])) { continue; } // skip empty key-value pair
$content[$key] = $tmp['value'][$i];
}
$ok = TRUE;
//r($content);
}
break;
case 'enum-freeinput':
//r($content);
//r($params);
// FIXME, need validate values
if (is_null($content)) {
// Empty array allowed, for override defaults
$content = array();
$ok = TRUE;
}
foreach ($content as $value) {
$ok = TRUE;
}
break;
case 'password':
case 'string':
$ok = TRUE;
break;
default:
$ok = FALSE;
$errors[] = $config_variable[$sqlname]['name'] . " ($confname) is of unknown type (" . $config_variable[$sqlname]['type'] . ")";
break;
}
if ($ok) {
$sets[$sqlname] = $content;
// Set an obs_attrib, example for syslog trigger
//r($config_variable[$sqlname]);
if (isset($config_variable[$sqlname]['set_attrib']) && strlen($config_variable[$sqlname]['set_attrib'])) {
$set_attribs[$config_variable[$sqlname]['set_attrib']] = $config['time']['now'];
}
}
} elseif ($sqlset) {
$deletes[] = $sqlname;
// Set an obs_attrib, example for syslog trigger
//r($config_variable[$sqlname]);
if (isset($config_variable[$sqlname]['set_attrib']) && strlen($config_variable[$sqlname]['set_attrib'])) {
$set_attribs[$config_variable[$sqlname]['set_attrib']] = $config['time']['now'];
}
}
}
}
return [ 'sets' => $sets, 'set_attribs' => $set_attribs, 'deletes' => $deletes, 'errors' => $errors ];
}
/**
* Convert amqp|conn|host into returning value of $arrayvar['amqp']['conn']['host']
*
* @param string $sqlname Variable name
* @param array $arrayvar Array where to see param
* @param Boolean $try_isset If True, return isset($sqlname) check, else return variable content
* @return mixed
*/
function sql_to_array($sqlname, $arrayvar, $try_isset = TRUE) {
list($key, $pop_sqlname) = explode('|', $sqlname, 2);
if (!is_array($arrayvar)) { return FALSE; }
$isset = array_key_exists($key, $arrayvar);
if (safe_empty($pop_sqlname)) {
// Reached the variable, return its content, or FALSE if it's not set
if ($try_isset) {
return $isset;
}
return $isset ? $arrayvar[$key] : NULL;
}
if ($isset) {
// Recurse to lower level
return sql_to_array($pop_sqlname, $arrayvar[$key], $try_isset);
}
return FALSE;
}
// TESTME needs unit testing
// DOCME needs phpdoc block
function get_smokeping_files($rdebug = 0)
{
global $config;
$smokeping_files = array();
if ($rdebug) { echo('- Recursing through ' . $config['smokeping']['dir'] . ' '); }
if (isset($config['smokeping']['master_hostname'])) {
$master_hostname = $config['smokeping']['master_hostname'];
} else {
$master_hostname = $config['own_hostname'] ?: get_localhost();
}
if (is_dir($config['smokeping']['dir']))
{
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($config['smokeping']['dir'])) as $file)
{
if (basename($file) != "." && basename($file) != ".." && strstr($file, ".rrd"))
{
if ($rdebug) { echo('- Found file ending in ".rrd": ' . basename($file) . ' '); }
if (strstr($file, "~"))
{
list($target,$slave) = explode("~", basename($file,".rrd"));
if ($rdebug) { echo('- Determined to be a slave file for target ' . $target . ' '); }
$target = str_replace($config['smokeping']['split_char'], ".", $target);
if ($config['smokeping']['suffix']) { $target = $target.$config['smokeping']['suffix']; if ($rdebug) { echo('- Suffix is configured, target is now ' . $target . ' '); } }
$smokeping_files['incoming'][$target][$slave] = $file;
$smokeping_files['outgoing'][$slave][$target] = $file;
} else {
$target = basename($file,".rrd");
if ($rdebug) { echo('- Determined to be a local file, for target ' . $target . ' '); }
$target = str_replace($config['smokeping']['split_char'], ".", $target);
if ($rdebug) { echo('- After replacing configured split_char ' . $config['smokeping']['split_char'] . ' by . target is ' . $target . ' '); }
if ($config['smokeping']['suffix']) { $target = $target.$config['smokeping']['suffix']; if ($rdebug) { echo('- Suffix is configured, target is now ' . $target . ' '); } }
$smokeping_files['incoming'][$target][$master_hostname] = $file;
$smokeping_files['outgoing'][$master_hostname][$target] = $file;
}
}
}
} else {
if ($rdebug) { echo("- Smokeping RRD directory not found: " . $config['smokeping']['dir']); }
}
return $smokeping_files;
}
/**
* Darkens or lightens a colour
* Found via http://codepad.org/MTGLWVd0
*
* First argument is the colour in hex, second argument is how dark it should be 1=same, 2=50%
*
* @return string
* @param string $rgb
* @param int $darker
*/
function darken_color($rgb, $darker=2)
{
if (strpos($rgb, '#') !== FALSE)
{
$hash = '#';
$rgb = str_replace('#', '', $rgb);
} else {
$hash = '';
}
$len = strlen($rgb);
if ($len == 6) {} // Passed RGB
else if ($len == 8)
{
// Passed RGBA, remove alpha channel
$rgb = substr($rgb, 0, 6);
} else {
$rgb = FALSE;
}
if ($rgb === FALSE) { return $hash.'000000'; }
$darker = ($darker > 1) ? $darker : 1;
list($R16, $G16, $B16) = str_split($rgb, 2);
$R = sprintf("%02X", floor(hexdec($R16) / $darker));
$G = sprintf("%02X", floor(hexdec($G16) / $darker));
$B = sprintf("%02X", floor(hexdec($B16) / $darker));
return $hash.$R.$G.$B;
}
function json_output($status, $message)
{
header("Content-type: application/json; charset=utf-8");
echo safe_json_encode([ "status" => $status, "message" => $message ]);
exit();
}
/**
* Register an HTML resource
*
* Registers resource for use later (will be re-inserted via output buffer handler)
* CSS and JS files default to the css/ and js/ directories respectively.
* Scripts are inserted literally as passed in $name.
*
* @param string $type Type of resource (css/js/script)
* @param string $content Filename or script content or array (for meta)
*/
// TESTME needs unit testing
function register_html_resource($type, $content)
{
// If no path specified, default to subdirectory of resource type (for CSS and JS only)
$type = strtolower($type);
if (in_array($type, array('css', 'js')) && strpos($content, '/') === FALSE)
{
$content = $type . '/' . $content;
}
// Insert into global variable, used in html callback function
$GLOBALS['cache_html']['resources'][$type][] = $content;
}
/**
* Register an HTML title section
*
* Registers title section for use in the html tag.
* Calls can be stacked, and will be concatenated later by the HTML callback function.
*
* @param string $title Section title content
*/
// TESTME needs unit testing
function register_html_title($title)
{
$GLOBALS['cache_html']['title'][] = $title;
}
/**
* Register an HTML alert block displayed in top of page.
*
* @param string $text Alert message
* @param string $title Alert title if passed
* @param string $severity Severity in list: info, danger, warning, success, recovery, suppressed, delay, disabled
*/
function register_html_alert($text, $title = NULL, $severity = 'info') {
// FIXME handle severity parameter with colour or icon?
$ui_alerts = '
';
if (!safe_empty($title)) {
$ui_alerts .= '
' . $title . '
';
}
$ui_alerts .= $text . '
';
$GLOBALS['cache_html']['ui_alerts'][] = $ui_alerts;
}
/**
* Register an HTML panel section
*
* Registers left panel section.
* Calls can be stacked, and will be concatenated later by the HTML callback function.
*
* @param string $html Section panel content
*/
// TESTME needs unit testing
function register_html_panel($html = '') {
$GLOBALS['cache_html']['page_panel'] = $html;
}
/**
* Redirect to specified URL
*
* @param string $url Redirecting URL
*/
function redirect_to_url($url)
{
if (safe_empty($url) || $url === '#') { return; } // Empty url, do not redirect
$parse = parse_url($url);
//r($url);
if (!isset($parse['scheme']) && !str_starts($url, '/')) {
// When this is not full url or not started with /
$url = '/' . $url;
}
if (headers_sent()) {
// HTML headers already sent, use JS than
register_html_resource('script', "location.href='$url'");
} else {
// Just use headers
header('Location: '.$url);
}
}
function generate_colour_gradient($start_colour, $end_colour, $steps) {
if($steps < 4) { $steps = 4; }
$FromRGB['r'] = hexdec(substr($start_colour, 0, 2));
$FromRGB['g'] = hexdec(substr($start_colour, 2, 2));
$FromRGB['b'] = hexdec(substr($start_colour, 4, 2));
$ToRGB['r'] = hexdec(substr($end_colour, 0, 2));
$ToRGB['g'] = hexdec(substr($end_colour, 2, 2));
$ToRGB['b'] = hexdec(substr($end_colour, 4, 2));
$StepRGB['r'] = ($FromRGB['r'] - $ToRGB['r']) / ($steps - 1);
$StepRGB['g'] = ($FromRGB['g'] - $ToRGB['g']) / ($steps - 1);
$StepRGB['b'] = ($FromRGB['b'] - $ToRGB['b']) / ($steps - 1);
$GradientColors = array();
for($i = 0; $i < $steps; $i++) {
$RGB['r'] = floor($FromRGB['r'] - ($StepRGB['r'] * $i));
$RGB['g'] = floor($FromRGB['g'] - ($StepRGB['g'] * $i));
$RGB['b'] = floor($FromRGB['b'] - ($StepRGB['b'] * $i));
$HexRGB['r'] = sprintf('%02x', ($RGB['r']));
$HexRGB['g'] = sprintf('%02x', ($RGB['g']));
$HexRGB['b'] = sprintf('%02x', ($RGB['b']));
$GradientColors[] = implode(NULL, $HexRGB);
}
$GradientColors = array_filter($GradientColors, "c_len");
return $GradientColors;
}
function c_len($val){
return (strlen($val) == 6 ? true : false );
}
function adjust_colour_brightness($hex, $steps) {
// Steps should be between -255 and 255. Negative = darker, positive = lighter
$steps = max(-255, min(255, $steps));
// Normalize into a six character long hex string
$hex = str_replace('#', '', $hex);
if (strlen($hex) == 3) {
$hex = str_repeat(substr($hex,0,1), 2).str_repeat(substr($hex,1,1), 2).str_repeat(substr($hex,2,1), 2);
}
// Split into three parts: R, G and B
$color_parts = str_split($hex, 2);
$return ='';
foreach ($color_parts as $color) {
$color = hexdec($color); // Convert to decimal
$color = max(0,min(255,$color + $steps)); // Adjust color
$return .= str_pad(dechex($color), 2, '0', STR_PAD_LEFT); // Make two char hex code
}
return $return;
}
/**
* Highlight (or replace with specific strings) part of string.
* Optionally can search full words of search strings.
*
* @param string $text Text where need highlight search string
* @param array $search Search array. Can be string, simple array or array with 'search', 'replace' pairs
* @param string $replace Default is just
* @param bool $words If True search full words
*
* @return string
*/
function html_highlight($text, $search = [], $replace = '', $words = FALSE) {
if (empty($replace)) {
// Default is highlight as danger class
$replace = $words ? '$1' : '$0';
}
$entries = [];
foreach ((array)$search as $entry) {
if (isset($entry['search'])) {
if (!isset($entry['replace'])) {
$entry['replace'] = $replace;
}
$text = html_highlight($text, $entry['search'], $entry['replace'], $words);
continue;
}
if (strlen($entry) == 0) { continue; }
$entry = preg_quote($entry, '%');
// allow limited regex patterns in search strings (currently only for interfaces links)
//$patterns = [ '\\\\d\+' => '\d+', ];
$entries[] = str_replace('\\\\d\+', '\d+', $entry);
}
if (!count($entries)) { return $text; }
$search_pattern = '(' . implode('|', $entries) . ')';
if ($words) {
// Search full words
$search_pattern = str_replace('(?:', '(', OBS_PATTERN_START) .
$search_pattern .
str_replace('(?:', '(', OBS_PATTERN_END);
// append start and end in pattern search
$replace = '$1' . $replace . '$3';
} else {
// Search any search string
$search_pattern = '%' . $search_pattern . '%i';
}
return preg_replace($search_pattern, $replace, $text);
}
/**
* Silly class to assign and remember a unique class for a type.
*
* @param string $type
* @param string $group
*
* @return string
*/
function get_type_class($type, $group = "unknown") {
global $cache;
if (isset($cache['type_class'][$group][$type])) {
return $cache['type_class'][$group][$type]['class'];
}
$classes = [ 'primary', 'success', 'warning', 'error', 'suppressed' ];
if (isset($cache['type_class'][$group]['NEXT'])) {
$next = $cache['type_class'][$group]['NEXT'];
} else {
$next = 0;
}
$cache['type_class'][$group][$type]['class'] = $classes[$next];
if (isset($classes[$next+1])) {
$next++;
} else {
$next = 0;
}
$cache['type_class'][$group]['NEXT'] = $next;
return $cache['type_class'][$group][$type]['class'];
}
/**
* Silly class to return a label using persistent class for a certain string/type within a given group
*
* @param string $type
* @param string $group
*
* @return string
*/
function get_type_class_label($type, $group = "unknown") {
return ''.$type.'';
}
// EOF