diff --git a/lib/WeatherMapLink.class.php b/lib/WeatherMapLink.class.php index d25f1d4..725db80 100644 --- a/lib/WeatherMapLink.class.php +++ b/lib/WeatherMapLink.class.php @@ -244,6 +244,10 @@ function CopyFrom(&$source) { function DrawComments($image, $col, $widths) { $curvepoints = $this->curvepoints; + if (cacti_sizeof($curvepoints) === 0) { + return; + } + $last = cacti_count($curvepoints) - 1; $totaldistance = $curvepoints[$last][2]; @@ -515,6 +519,10 @@ function Draw($image, &$map) { $this->DrawComments($image,[$comment_colour_in, $comment_colour_out],[$link_in_width * 1.1, $link_out_width * 1.1]); } + if (cacti_sizeof($this->curvepoints) === 0) { + return; + } + $curvelength = $this->curvepoints[cacti_count($this->curvepoints) - 1][2]; // figure out where the labels should be, and what the angle of the curve is at that point @@ -754,7 +762,7 @@ function WriteConfig() { $output .= TAB . 'TARGET'; foreach ($this->targets as $target) { - if (strpos($target[4], ' ') == false) { + if (strpos($target[4], ' ') === false) { $output .= ' ' . $target[4]; } else { $output .= ' "' . $target[4] . '"'; @@ -846,7 +854,7 @@ function asJS() { $tgt = ''; foreach ($this->targets as $target) { - if (strpos($target[4], ' ') == false) { + if (strpos($target[4], ' ') === false) { $tgt .= $target[4] . ' '; } else { $tgt .= '"' . $target[4] . '" '; diff --git a/lib/WeatherMapNode.class.php b/lib/WeatherMapNode.class.php index f0c2b60..abc7f5b 100644 --- a/lib/WeatherMapNode.class.php +++ b/lib/WeatherMapNode.class.php @@ -882,7 +882,7 @@ function WriteConfig() { $output .= TAB . 'TARGET'; foreach ($this->targets as $target) { - if (strpos($target[4], ' ') == false) { + if (strpos($target[4], ' ') === false) { $output .= ' ' . $target[4]; } else { $output .= ' "' . $target[4] . '"'; diff --git a/lib/datasources/WeatherMapDataSource_fping.php b/lib/datasources/WeatherMapDataSource_fping.php index 6540cff..8ddb3cb 100644 --- a/lib/datasources/WeatherMapDataSource_fping.php +++ b/lib/datasources/WeatherMapDataSource_fping.php @@ -100,10 +100,10 @@ function ReadData($targetstring, &$map, &$item) { $pattern .= '/'; if (is_executable($this->fping_cmd)) { - $command = $this->fping_cmd . " -t100 -r1 -p20 -u -C $ping_count -i10 -q $target 2>&1"; + $command = cacti_escapeshellarg($this->fping_cmd) . ' -t100 -r1 -p20 -u -C ' . (int) $ping_count . ' -i10 -q ' . cacti_escapeshellarg($target) . ' 2>&1'; // nosemgrep: php.lang.security.exec-use.exec-use -- fping_cmd is admin-configured; target validated against fping: pattern wm_debug("Running $command"); - $pipe = popen($command, 'r'); + $pipe = popen($command, 'r'); // nosemgrep: php.lang.security.exec-use.exec-use -- fping_cmd is admin-configured; target validated above via cacti_escapeshellarg $count = 0; $hitcount = 0; diff --git a/lib/datasources/WeatherMapDataSource_rrd.php b/lib/datasources/WeatherMapDataSource_rrd.php index 0aeffc3..3b9d9a6 100644 --- a/lib/datasources/WeatherMapDataSource_rrd.php +++ b/lib/datasources/WeatherMapDataSource_rrd.php @@ -308,21 +308,27 @@ function wmrrd_read_from_real_rrdtool_aggregate($rrdfile,$cf,$aggregatefn,$start $args[] = "PRINT:agg_out:'OUT %lf'"; } - $command = $map->rrdtool; + $command = cacti_escapeshellarg($map->rrdtool); foreach ($args as $arg) { - if (strchr($arg, ' ') != false) { - $command .= ' "' . $arg . '"'; + $command .= ' ' . cacti_escapeshellarg($arg); + } + + if ($extra_options !== '' && $extra_options !== null) { + if (preg_match('/["\'\\]/', (string) $extra_options)) { + $msg = 'RRD ReadData: rrd_options contains quote or backslash characters and was skipped to prevent argument corruption. Use only space-separated single-token flags. [WMRRD04]'; + wm_warn($msg); + cacti_log('WEATHERMAP: ' . $msg, false, 'POLLER', POLLER_VERBOSITY_LOW); } else { - $command .= ' ' . $arg; + foreach (preg_split('/\s+/', (string) $extra_options, -1, PREG_SPLIT_NO_EMPTY) as $opt) { + $command .= ' ' . cacti_escapeshellarg($opt); + } } } - $command .= ' ' . $extra_options; - wm_debug("RRD ReadData: Running: $command"); - $pipe = popen($command, 'r'); + $pipe = popen($command, 'r'); // nosemgrep: php.lang.security.exec-use.exec-use -- rrdtool path is admin-configured; all args cacti_escapeshellarg'd $lines = []; $count = 0; @@ -412,21 +418,27 @@ function wmrrd_read_from_real_rrdtool($rrdfile, $cf, $start, $end, $dsnames, &$d $args[] = '--end'; $args[] = $end; - $command = $map->rrdtool; + $command = cacti_escapeshellarg($map->rrdtool); foreach ($args as $arg) { - if (strchr($arg, ' ') != false) { - $command .= ' "' . $arg . '"'; + $command .= ' ' . cacti_escapeshellarg($arg); + } + + if ($extra_options !== '' && $extra_options !== null) { + if (preg_match('/["\'\\]/', (string) $extra_options)) { + $msg = 'RRD ReadData: rrd_options contains quote or backslash characters and was skipped to prevent argument corruption. Use only space-separated single-token flags. [WMRRD04]'; + wm_warn($msg); + cacti_log('WEATHERMAP: ' . $msg, false, 'POLLER', POLLER_VERBOSITY_LOW); } else { - $command .= ' ' . $arg; + foreach (preg_split('/\s+/', (string) $extra_options, -1, PREG_SPLIT_NO_EMPTY) as $opt) { + $command .= ' ' . cacti_escapeshellarg($opt); + } } } - $command .= ' ' . $extra_options; - wm_debug("RRD ReadData: Running: $command"); - $pipe = popen($command, 'r'); + $pipe = popen($command, 'r'); // nosemgrep: php.lang.security.exec-use.exec-use -- rrdtool path is admin-configured; all args cacti_escapeshellarg'd $lines = []; $count = 0; diff --git a/setup.php b/setup.php index 9c0562c..30c7637 100644 --- a/setup.php +++ b/setup.php @@ -113,7 +113,7 @@ function plugin_weathermap_upgrade() { $current = plugin_weathermap_version(); $current = $current['version']; - $old = db_fetch_cell("SELECT version FROM plugin_config WHERE directory='weathermap'"); + $old = db_fetch_cell("SELECT version FROM plugin_config WHERE directory = 'weathermap'"); if ($current != $old) { db_execute_prepared('UPDATE plugin_realms diff --git a/weathermap-cacti-plugin.php b/weathermap-cacti-plugin.php index 4dbd592..cfe7f5c 100644 --- a/weathermap-cacti-plugin.php +++ b/weathermap-cacti-plugin.php @@ -379,7 +379,7 @@ function weathermap_singleview($mapid) { print do_hook_function('weathermap_page_top', ''); $htmlfile = $outdir . $map['filehash'] . '.html'; - $maptitle = $map['titlecache']; + $maptitle = html_escape($map['titlecache']); if ($maptitle == '') { $maptitle = __esc('Map for config file: %s', $map['configfile']);