From: Bruno PrĂ©mont Date: Tue, 10 Feb 2009 20:38:23 +0000 (+0100) Subject: contrib/php-collection: Save/load graph list and fix HTTPS handling. X-Git-Tag: collectd-4.6.0~19^2^2 X-Git-Url: https://git.octo.it/?a=commitdiff_plain;h=b2491d8cc416955fb0df16b74a28f218a2dedc01;p=collectd.git contrib/php-collection: Save/load graph list and fix HTTPS handling. Hi, An update to the graphing interface. (incremental patch attached) This fixes security complaint by a few browsers when page is accessed via HTTPS and also makes sure the graphs and lists will load if HTTP and HTTPS paths differ. Thanks to Mullet- for spotting this issue. In addition to the fix above this patch adds support for saving current graph list to a cookie and appending graph list read from cookie to the currently displayed list. A future extension would be to allow saving/loading named graph lists so multiple list can coexist (pretty useful when monitoring multiple servers/services) Bruno --- diff --git a/contrib/php-collection/browser.js b/contrib/php-collection/browser.js index 9fcdbabe..6f4d8ec8 100644 --- a/contrib/php-collection/browser.js +++ b/contrib/php-collection/browser.js @@ -37,6 +37,8 @@ function toggleDiv(divID) { } } +var req = null; + // DHTML helper code to asynchronous loading of content function loadXMLDoc(url, query) { if (window.XMLHttpRequest) { @@ -57,12 +59,13 @@ function loadXMLDoc(url, query) { } // DHTML new-content dispatcher -function processReqChange() { +function processReqChange(evt) { if (req.readyState == 4) { if (req.status == 200) { - response = req.responseXML.documentElement; - method = response.getElementsByTagName('method')[0].firstChild.data; - result = response.getElementsByTagName('result')[0]; + var response = req.responseXML.documentElement; + var method = response.getElementsByTagName('method')[0].firstChild.data; + var result = response.getElementsByTagName('result')[0]; + req = null; eval(method + '(result)'); } } @@ -265,9 +268,9 @@ function RefreshButtons() { } var nextGraphId = 1; +var graphList = new Array(); function GraphAppend() { - var graphs = document.getElementById('graphs'); var host_list = document.getElementById('host_list'); var host = host_list.selectedIndex >= 0 ? host_list.options[host_list.selectedIndex].value : '/'; var plugin_list = document.getElementById('plugin_list'); @@ -278,6 +281,15 @@ function GraphAppend() { var type = type_list.selectedIndex >= 0 ? type_list.options[type_list.selectedIndex].value : '/'; var tinst_list = document.getElementById('tinst_list'); var tinst = tinst_list.selectedIndex >= 0 ? tinst_list.options[tinst_list.selectedIndex].value : '/'; + var time_list = document.getElementById('timespan'); + var timespan = time_list.selectedIndex >= 0 ? time_list.options[time_list.selectedIndex].value : ''; + var tinyLegend = document.getElementById('tinylegend').checked; + var logarithmic = document.getElementById('logarithmic').checked + GraphDoAppend(host, plugin, pinst, type, tinst, timespan, tinyLegend, logarithmic); +} + +function GraphDoAppend(host, plugin, pinst, type, tinst, timespan, tinyLegend, logarithmic) { + var graphs = document.getElementById('graphs'); if (host != '/' && plugin != '/' && pinst != '/' && type != '/') { var graph_id = 'graph_'+nextGraphId++; @@ -292,14 +304,15 @@ function GraphAppend() { graph_title = type+(tinst.length > 0 ? '-'+tinst : '')+' of '+plugin+(pinst.length > 0 ? '-'+pinst : '')+' plugin for '+host; graph_src += '&type_instance='+encodeURIComponent(tinst); } - if (document.getElementById('logarithmic').checked) + if (logarithmic) graph_src += '&logarithmic=1'; - if (document.getElementById('tinylegend').checked) + if (tinyLegend) graph_src += '&tinylegend=1'; - if (document.getElementById('timespan').selectedIndex >= 0) - graph_src += '×pan='+encodeURIComponent(document.getElementById('timespan').options[document.getElementById('timespan').selectedIndex].value); + if (timespan) + graph_src += '×pan='+encodeURIComponent(timespan); var now = new Date(); graph_src += '&ts='+now.getTime(); + graphList.push(graph_id+' '+encodeURIComponent(graph_alt)+(logarithmic ? '&logarithmic=1' : '')+(tinyLegend ? '&tinylegend=1' : '')+'×pan='+encodeURIComponent(timespan)); // Graph container newGraph = document.createElement('div'); @@ -372,6 +385,7 @@ function GraphDropAll() { graphs.removeChild(graphs.childNodes[childCnt]); else if (graphs.childNodes[childCnt].id == 'nograph') graphs.childNodes[childCnt].style.display = 'block'; + graphList = new Array(); RefreshButtons(); } @@ -413,6 +427,14 @@ function GraphRemove(graph) { RefreshButtons(); if (graphs.getElementsByTagName('div').length == 1) document.getElementById('nograph').style.display = 'block'; + + var myList = Array(); + for (i = 0; i < graphList.length; i++) + if (graphList[i].substring(0, graph.length) == graph && graphList[i].charAt(graph.length) == ' ') + continue; + else + myList.push(graphList[i]); + graphList = myList; } } @@ -434,6 +456,15 @@ function GraphMoveUp(graph) { } else prevGraph = graphs.childNodes[i]; } + for (i = 0; i < graphList.length; i++) + if (graphList[i].substring(0, graph.length) == graph && graphList[i].charAt(graph.length) == ' ') { + if (i > 0) { + var tmp = graphList[i-1]; + graphList[i-1] = graphList[i]; + graphList[i] = tmp; + } + break; + } } function GraphMoveDown(graph) { @@ -454,5 +485,94 @@ function GraphMoveDown(graph) { break; } } + for (i = 0; i < graphList.length; i++) + if (graphList[i].substring(0, graph.length) == graph && graphList[i].charAt(graph.length) == ' ') { + if (i+1 < graphList.length) { + var tmp = graphList[i+1]; + graphList[i+1] = graphList[i]; + graphList[i] = tmp; + } + break; + } +} + +function GraphListFromCookie() { + if (document.cookie.length > 0) { + cookies = document.cookie.split('; '); + for (i = 0; i < cookies.length; i++) + if (cookies[i].substring(0, 9) == 'graphLst=') + return cookies[i].substring(9).split('/'); + } + return new Array(); +} + +function GraphSave() { + if (graphList.length > 0) { + // Save graph list to cookie + var str = ''; + for (i = 0; i < graphList.length; i++) { + var g = graphList[i].indexOf(' '); + if (i > 0) + str += '/'; + str += graphList[i].substring(g+1); + } + + document.cookie = 'graphLst='+str; + if (GraphListFromCookie().length == 0) + alert("Failed to save graph list to cookie."); + else + alert("Successfully saved current graph list."); + } else { + document.cookie = 'graphLst=; expires='+new Date().toGMTString(); + alert("Cleared saved graph list."); + } +} + +function GraphLoad() { + // Load graph list from cookie + var grLst = GraphListFromCookie(); + for (i = 0; i < grLst.length; i++) { + var host = ''; + var plugin = ''; + var pinst = ''; + var type = ''; + var tinst = ''; + var timespan = ''; + var logarithmic = false; + var tinyLegend = false; + var graph = grLst[i].split('&'); + for (j = 0; j < graph.length; j++) + if (graph[j] == 'logarithmic=1') + logarithmic = true; + else if (graph[j] == 'tinylegend=1') + tinyLegend = true; + else if (graph[j].substring(0, 9) == 'timespan=') + timespan = decodeURIComponent(graph[j].substring(9)); + graph = decodeURIComponent(graph[0]).split('/'); + host = graph[0]; + if (graph.length > 1) { + var g = graph[1].indexOf('-'); + if (g >= 0) { + plugin = graph[1].substring(0, g); + pinst = graph[1].substring(g+1); + } else + plugin = graph[1]; + } + if (graph.length > 2) { + var g = graph[2].indexOf('-'); + if (g >= 0) { + type = graph[2].substring(0, g); + tinst = graph[2].substring(g+1); + } else + type = graph[2]; + } + + if (host && plugin && type) + GraphDoAppend(host, plugin, pinst, type, tinst, timespan, tinyLegend, logarithmic); + } + if (grLst.length == 0) + alert("No list found for loading."); + else if (grLst.length != graphList.length) + alert("Could not load all graphs, probably damaged cookie."); } diff --git a/contrib/php-collection/functions.php b/contrib/php-collection/functions.php index f4d07e0a..9fb6116f 100644 --- a/contrib/php-collection/functions.php +++ b/contrib/php-collection/functions.php @@ -75,7 +75,8 @@ function collectd_list_hosts() { if ($dent != '.' && $dent != '..' && is_dir($datadir.'/'.$dent) && preg_match(REGEXP_HOST, $dent)) $hosts[] = $dent; closedir($d); - } + } else + error_log('Failed to open datadir: '.$datadir); $hosts = array_unique($hosts); usort($hosts, 'collectd_compare_host'); return $hosts; diff --git a/contrib/php-collection/index.php b/contrib/php-collection/index.php index 93f1fcf5..1f788fc9 100644 --- a/contrib/php-collection/index.php +++ b/contrib/php-collection/index.php @@ -58,6 +58,7 @@ function build_page() { print(''."\n"); print(''."\n"); } + $url_base = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https://' : 'http://').$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/'; ?> Collectd graph viewer @@ -65,7 +66,8 @@ function build_page() { - +
@@ -135,12 +137,52 @@ var graph_url = ' - + + +
-
Please use above graph selection tool to add graphs to this area.
+
Please use above graph selection tool to add graphs to this area.Config error: $config["datadirs"] is not set

'; + else if (!is_array($config['datadirs'])) + echo '

Config error: $config["datadirs"] is not an array

'; + else if (count($config['datadirs']) == 0) + echo '

Config error: $config["datadirs"] is empty

'; + else foreach ($config['datadirs'] as $datadir) + if (!is_dir($datadir)) + echo '

Config error: $config["datadirs"], '.htmlspecialchars($datadir).' does not exist

'; + if (!isset($config['rrd_width'])) + echo '

Config error: $config["rrd_width"] is not set

'; + else if (10 > (int)$config['rrd_width']) + echo '

Config error: $config["rrd_width"] is invalid. Integer >= 10 expected

'; + if (!isset($config['rrd_height'])) + echo '

Config error: $config["rrd_height"] is not set

'; + else if (10 > (int)$config['rrd_height']) + echo '

Config error: $config["rrd_height"] is invalid. Integer >= 10 expected

'; + if (!isset($config['rrd_opts'])) + echo '

Config error: $config["rrd_opts"] is not set

'; + else if (!is_array($config['rrd_opts'])) + echo '

Config error: $config["rrd_opts"] is not an array

'; + if (!isset($config['timespan'])) + echo '

Config error: $config["timespan"] is not set

'; + else if (!is_array($config['timespan'])) + echo '

Config error: $config["timespan"] is not an array

'; + else if (count($config['timespan']) == 0) + echo '

Config error: $config["timespan"] is empty

'; + else foreach ($config['timespan'] as &$timespan) + if (!is_array($timespan) || !isset($timespan['name']) || !isset($timespan['label']) || !isset($timespan['seconds']) || 10 > (int)$timespan['seconds']) + echo '

Config error: $config["timespan"], invalid entry found

'; + if (!is_null($config['collectd_sock']) && strncmp('unix://', $config['collectd_sock'], 7) != 0) + echo '

Config error: $config["collectd_sock"] is not valid

'; + if (!defined('RRDTOOL')) + echo '

Config error: RRDTOOL is not defined

'; + else if (!is_executable(RRDTOOL)) + echo '

Config error: RRDTOOL ('.htmlspecialchars(RRDTOOL).') is not executable

'; + ?>