Issues (2963)

includes/html/graphs/device/collectd.inc.php (3 issues)

1
<?php
2
3
/*
4
 * Copyright (C) 2009  Bruno Prémont <bonbons AT linux-vserver.org>
5
 *
6
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; only version 2 of the License is applicable.
9
 *
10
 * This program is distributed in the hope that it will be useful, but WITHOUT
11
 * ANY WARRANTY; without even the implied wadsnty of MERCHANTABILITY or FITNESS
12
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
13
 * details.
14
 *
15
 * You should have received a copy of the GNU General Public License along with
16
 * this program; if not, write to the Free Software Foundation, Inc.,
17
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18
 */
19
20
use LibreNMS\Config;
21
22
require 'includes/html/collectd/config.php';
23
require 'includes/html/collectd/functions.php';
24
require 'includes/html/collectd/definitions.php';
25
26
function makeTextBlock($text, $fontfile, $fontsize, $width)
27
{
28
    // TODO: handle explicit line-break!
29
    $words = explode(' ', $text);
30
    $lines = [$words[0]];
31
    $currentLine = 0;
32
    foreach ($words as $word) {
33
        $lineSize = imagettfbbox($fontsize, 0, $fontfile, $lines[$currentLine] . ' ' . $word);
34
        if (($lineSize[2] - $lineSize[0]) < $width) {
35
            $lines[$currentLine] .= ' ' . $word;
36
        } else {
37
            $currentLine++;
38
            $lines[$currentLine] = $word;
39
        }
40
    }
41
42
    error_log(sprintf('Handles message "%s", %d words => %d/%d lines', $text, count($words), $currentLine, count($lines)));
43
44
    return implode("\n", $lines);
45
}//end makeTextBlock()
46
47
/**
48
 * No RRD files found that could match request
49
 *
50
 * @code HTTP error code
51
 * @code_msg Short text description of HTTP error code
52
 * @title Title for fake RRD graph
53
 * @msg Complete error message to display in place of graph content
54
 */
55
function error($code, $code_msg, $title, $msg)
56
{
57
    header(sprintf('HTTP/1.0 %d %s', $code, $code_msg));
58
    header('Pragma: no-cache');
59
    header('Expires: Mon, 01 Jan 2008 00:00:00 CET');
60
    header('Content-Type: image/png');
61
    $w = (Config::get('rrd_width') + 81);
62
    $h = (Config::get('rrd_height') + 79);
63
64
    $png = imagecreate($w, $h);
65
    $c_bkgnd = imagecolorallocate($png, 240, 240, 240);
66
    $c_fgnd = imagecolorallocate($png, 255, 255, 255);
67
    $c_blt = imagecolorallocate($png, 208, 208, 208);
68
    $c_brb = imagecolorallocate($png, 160, 160, 160);
69
    $c_grln = imagecolorallocate($png, 114, 114, 114);
70
    $c_grarr = imagecolorallocate($png, 128, 32, 32);
71
    $c_txt = imagecolorallocate($png, 0, 0, 0);
72
    $c_etxt = imagecolorallocate($png, 64, 0, 0);
73
74
    if (function_exists('imageantialias')) {
75
        imageantialias($png, true);
76
    }
77
78
    imagefilledrectangle($png, 0, 0, $w, $h, $c_bkgnd);
79
    imagefilledrectangle($png, 51, 33, ($w - 31), ($h - 47), $c_fgnd);
80
    imageline($png, 51, 30, 51, ($h - 43), $c_grln);
81
    imageline($png, 48, ($h - 46), ($w - 28), ($h - 46), $c_grln);
82
    imagefilledpolygon($png, [49, 30, 51, 26, 53, 30], 3, $c_grarr);
83
    imagefilledpolygon($png, [$w - 28, $h - 48, $w - 24, $h - 46, $w - 28, $h - 44], 3, $c_grarr);
84
    imageline($png, 0, 0, $w, 0, $c_blt);
85
    imageline($png, 0, 1, $w, 1, $c_blt);
86
    imageline($png, 0, 0, 0, $h, $c_blt);
87
    imageline($png, 1, 0, 1, $h, $c_blt);
88
    imageline($png, ($w - 1), 0, ($w - 1), $h, $c_brb);
89
    imageline($png, ($w - 2), 1, ($w - 2), $h, $c_brb);
90
    imageline($png, 1, ($h - 2), $w, ($h - 2), $c_brb);
91
    imageline($png, 0, ($h - 1), $w, ($h - 1), $c_brb);
92
93
    imagestring($png, 4, ceil(($w - strlen($title) * imagefontwidth(4)) / 2), 10, $title, $c_txt);
94
    imagestring($png, 5, 60, 35, sprintf('%s [%d]', $code_msg, $code), $c_etxt);
95
    if (function_exists('imagettfbbox') && is_file(Config::get('error_font'))) {
96
        // Detailled error message
97
        $errorfont = Config::get('error_font');
98
        $fmt_msg = makeTextBlock($msg, $errorfont, 10, ($w - 86));
99
        $fmtbox = imagettfbbox(12, 0, $errorfont, $fmt_msg);
100
        imagettftext($png, 10, 0, 55, (35 + 3 + imagefontwidth(5) - $fmtbox[7] + $fmtbox[1]), $c_txt, $errorfont, $fmt_msg);
101
    } else {
102
        imagestring($png, 4, 53, (35 + 6 + imagefontwidth(5)), $msg, $c_txt);
103
    }
104
105
    imagepng($png);
106
    imagedestroy($png);
107
}//end error()
108
109
/**
110
 * No RRD files found that could match request
111
 */
112
function error404($title, $msg)
113
{
114
    return error(404, 'Not found', $title, $msg);
115
}//end error404()
116
117
function error500($title, $msg)
118
{
119
    return error(500, 'Not found', $title, $msg);
120
}//end error500()
121
122
/**
123
 * Incomplete / invalid request
124
 */
125
function error400($title, $msg)
126
{
127
    return error(400, 'Bad request', $title, $msg);
128
}//end error400()
129
130
// Process input arguments
131
// $host   = read_var('host', $_GET, null);
132
$host = $device['hostname'];
133
if (is_null($host)) {
134
    return error400('?/?-?/?', 'Missing host name');
135
} elseif (! is_string($host)) {
136
    return error400('?/?-?/?', 'Expecting exactly 1 host name');
137
} elseif (strlen($host) == 0) {
138
    return error400('?/?-?/?', 'Host name may not be blank');
139
}
140
141
$plugin = read_var('c_plugin', $_GET, null);
142
if (is_null($plugin)) {
143
    return error400($host . '/?-?/?', 'Missing plugin name');
144
} elseif (! is_string($plugin)) {
0 ignored issues
show
The condition is_string($plugin) is always true.
Loading history...
145
    return error400($host . '/?-?/?', 'Plugin name must be a string');
146
} elseif (strlen($plugin) == 0) {
147
    return error400($host . '/?-?/?', 'Plugin name may not be blank');
148
}
149
150
$pinst = read_var('c_plugin_instance', $_GET, '');
151
if (! is_string($pinst)) {
0 ignored issues
show
The condition is_string($pinst) is always true.
Loading history...
152
    return error400($host . '/' . $plugin . '-?/?', 'Plugin instance name must be a string');
153
}
154
155
$type = read_var('c_type', $_GET, '');
156
if (is_null($type)) {
157
    return error400($host . '/' . $plugin . (strlen($pinst) ? '-' . $pinst : '') . '/?', 'Missing type name');
158
} elseif (! is_string($type)) {
0 ignored issues
show
The condition is_string($type) is always true.
Loading history...
159
    return error400($host . '/' . $plugin . (strlen($pinst) ? '-' . $pinst : '') . '/?', 'Type name must be a string');
160
} elseif (strlen($type) == 0) {
161
    return error400($host . '/' . $plugin . (strlen($pinst) ? '-' . $pinst : '') . '/?', 'Type name may not be blank');
162
}
163
164
$tinst = read_var('c_type_instance', $_GET, '');
165
166
$graph_identifier = $host . '/' . $plugin . (strlen($pinst) ? '-' . $pinst : '') . '/' . $type . (strlen($tinst) ? '-' . $tinst : '-*');
167
168
$timespan = read_var('timespan', $_GET, Config::get('timespan.0.name'));
169
$timespan_ok = false;
170
foreach (Config::get('timespan') as &$ts) {
171
    if ($ts['name'] == $timespan) {
172
        $timespan_ok = true;
173
    }
174
}
175
176
if (! $timespan_ok) {
177
    return error400($graph_identifier, 'Unknown timespan requested');
178
}
179
180
$logscale = (bool) read_var('logarithmic', $_GET, false);
181
$tinylegend = (bool) read_var('tinylegend', $_GET, false);
182
183
// Check that at least 1 RRD exists for the specified request
184
$all_tinst = collectd_list_tinsts($host, $plugin, $pinst, $type);
185
if (count($all_tinst) == 0) {
186
    return error404($graph_identifier, 'No rrd file found for graphing');
187
}
188
189
// Now that we are read, do the bulk work
190
load_graph_definitions($logscale, $tinylegend);
191
192
$pinst = strlen($pinst) == 0 ? null : $pinst;
193
$tinst = strlen($tinst) == 0 ? null : $tinst;
194
195
$opts = [];
196
$opts['timespan'] = $timespan;
197
if ($logscale) {
198
    $opts['logarithmic'] = 1;
199
}
200
201
if ($tinylegend) {
202
    $opts['tinylegend'] = 1;
203
}
204
205
$rrd_cmd = false;
206
if (isset($MetaGraphDefs[$type])) {
207
    $identifiers = [];
208
    foreach ($all_tinst as &$atinst) {
209
        $identifiers[] = collectd_identifier($host, $plugin, $type, is_null($pinst) ? '' : $pinst, $atinst);
210
    }
211
212
    collectd_flush($identifiers);
213
    $rrd_cmd = $MetaGraphDefs[$type]($host, $plugin, $pinst, $type, $all_tinst, $opts);
214
} else {
215
    if (! in_array(is_null($tinst) ? '' : $tinst, $all_tinst)) {
216
        return error404($host . '/' . $plugin . (! is_null($pinst) ? '-' . $pinst : '') . '/' . $type . (! is_null($tinst) ? '-' . $tinst : ''), 'No rrd file found for graphing');
217
    }
218
219
    collectd_flush(collectd_identifier($host, $plugin, $type, is_null($pinst) ? '' : $pinst, is_null($tinst) ? '' : $tinst));
220
    if (isset($GraphDefs[$type])) {
221
        $rrd_cmd = collectd_draw_generic($timespan, $host, $plugin, $type, $pinst, $tinst);
222
    } else {
223
        $rrd_cmd = collectd_draw_rrd($host, $plugin, $type, $pinst, $tinst);
224
    }
225
}
226
227
if (isset($rrd_cmd)) {
228
    $from = (int) ($_GET['from'] ?? time() - 86400);
229
    $to = (int) ($_GET['to'] ?? time());
230
231
    $rrd_cmd .= ' -s ' . $from . ' -e ' . $to;
232
}
233
234
if ($_GET['legend'] == 'no') {
235
    $rrd_cmd .= ' -g ';
236
}
237
238
if ($height < '99') {
239
    $rrd_cmd .= ' --only-graph ';
240
}
241
242
if ($width <= '300') {
243
    $rrd_cmd .= ' --font LEGEND:7:' . Config::get('mono_font') . ' --font AXIS:6:' . Config::get('mono_font') . ' ';
244
} else {
245
    $rrd_cmd .= ' --font LEGEND:8:' . Config::get('mono_font') . ' --font AXIS:7:' . Config::get('mono_font') . ' ';
246
}
247
248
if (isset($_GET['debug'])) {
249
    header('Content-Type: text/plain; charset=utf-8');
250
    printf("Would have executed:\n%s\n", $rrd_cmd);
251
252
    return 0;
253
} elseif ($rrd_cmd) {
254
    header('Content-Type: image/png');
255
    header('Cache-Control: max-age=60');
256
    $rt = 0;
257
    passthru($rrd_cmd, $rt);
258
    if ($rt !== 0) {
259
        return error500($graph_identifier, 'RRD failed to generate the graph: ' . $rt);
260
    }
261
262
    return $rt;
263
} else {
264
    return error500($graph_identifier, 'Failed to tell RRD how to generate the graph');
265
}
266