~ubuntu-branches/debian/stretch/cacti/stretch

« back to all changes in this revision

Viewing changes to .pc/CVE-2014-5261_shell_metachar.patch/lib/rrd.php

  • Committer: Package Import Robot
  • Author(s): Paul Gevers
  • Date: 2015-06-22 19:59:13 UTC
  • mfrom: (1.1.16) (36.1.2 experimental)
  • Revision ID: package-import@ubuntu.com-20150622195913-40twdt0k4ondnuvz
Tags: 0.8.8d+ds1-1
* Upload to unstable
* New upstream release
  - CVE-2015-2665 Cross-site scripting (XSS) vulnerability in Cacti
    before 0.8.8d allows remote attackers to inject arbitrary web script
    or HTML via unspecified vectors.
  - CVE-2015-4342 SQL Injection and Location header injection from cdef id
  - CVE-2015-4454 SQL injection vulnerability in the
    get_hash_graph_template function in lib/functions.php in Cacti before
    0.8.8d allows remote attackers to execute arbitrary SQL commands via
    the graph_template_id parameter to graph_templates.php.
  - Unassigned CVE VN:JVN#78187936 / TN:JPCERT#98968540 Fixed SQL injection
* Remove Sean from the list of uploaders. Thanks for all the fish
  (Closes: #773436)
* Fix d/p/07_cli-include-path.patch (LP: #1433665)
* Update debian/patches/fix_php_strict_warning_in_ping.patch for partial
  upstream fix
* Include the virtual alternative for the recommends on mysql-server
  (Closes: #781982)
* Upstream dropped unused javascripts, remove them from d/copyright
* Add patch to have upgrade script mention version 0.8.8d i.s.o. 0.8.8c

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
/*
3
 
 +-------------------------------------------------------------------------+
4
 
 | Copyright (C) 2004-2013 The Cacti Group                                 |
5
 
 |                                                                         |
6
 
 | This program is free software; you can redistribute it and/or           |
7
 
 | modify it under the terms of the GNU General Public License             |
8
 
 | as published by the Free Software Foundation; either version 2          |
9
 
 | of the License, or (at your option) any later version.                  |
10
 
 |                                                                         |
11
 
 | This program is distributed in the hope that it will be useful,         |
12
 
 | but WITHOUT ANY WARRANTY; without even the implied warranty of          |
13
 
 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           |
14
 
 | GNU General Public License for more details.                            |
15
 
 +-------------------------------------------------------------------------+
16
 
 | Cacti: The Complete RRDTool-based Graphing Solution                     |
17
 
 +-------------------------------------------------------------------------+
18
 
 | This code is designed, written, and maintained by the Cacti Group. See  |
19
 
 | about.php and/or the AUTHORS file for specific developer information.   |
20
 
 +-------------------------------------------------------------------------+
21
 
 | http://www.cacti.net/                                                   |
22
 
 +-------------------------------------------------------------------------+
23
 
*/
24
 
 
25
 
define("RRD_NL", " \\\n");
26
 
define("MAX_FETCH_CACHE_SIZE", 5);
27
 
 
28
 
function escape_command($command) {
29
 
        return $command;                # we escape every single argument now, no need for "special" escaping
30
 
        #return preg_replace("/(\\\$|`)/", "", $command); # current cacti code
31
 
        #TODO return preg_replace((\\\$(?=\w+|\*|\@|\#|\?|\-|\\\$|\!|\_|[0-9]|\(.*\))|`(?=.*(?=`)))","$2", $command);  #suggested by ldevantier to allow for a single $
32
 
}
33
 
 
34
 
function rrd_init($output_to_term = TRUE) {
35
 
        global $config;
36
 
 
37
 
        /* set the rrdtool default font */
38
 
        if (read_config_option("path_rrdtool_default_font")) {
39
 
                putenv("RRD_DEFAULT_FONT=" . read_config_option("path_rrdtool_default_font"));
40
 
        }
41
 
 
42
 
        if ($output_to_term) {
43
 
                $command = read_config_option("path_rrdtool") . " - ";
44
 
        }else{
45
 
                if ($config["cacti_server_os"] == "win32") {
46
 
                        $command = read_config_option("path_rrdtool") . " - > nul";
47
 
                }else{
48
 
                        $command = read_config_option("path_rrdtool") . " - > /dev/null 2>&1";
49
 
                }
50
 
        }
51
 
 
52
 
        return popen($command, "w");
53
 
}
54
 
 
55
 
function rrd_close($rrdtool_pipe) {
56
 
        /* close the rrdtool file descriptor */
57
 
        if (is_resource($rrdtool_pipe)) {
58
 
                pclose($rrdtool_pipe);
59
 
        }
60
 
}
61
 
 
62
 
function rrdtool_execute($command_line, $log_to_stdout, $output_flag, $rrdtool_pipe = "", $logopt = "WEBLOG") {
63
 
        global $config;
64
 
 
65
 
        static $last_command;
66
 
 
67
 
        if (!is_numeric($output_flag)) {
68
 
                $output_flag = RRDTOOL_OUTPUT_STDOUT;
69
 
        }
70
 
 
71
 
        /* WIN32: before sending this command off to rrdtool, get rid
72
 
        of all of the '\' characters. Unix does not care; win32 does.
73
 
        Also make sure to replace all of the fancy \'s at the end of the line,
74
 
        but make sure not to get rid of the "\n"'s that are supposed to be
75
 
        in there (text format) */
76
 
        $command_line = str_replace("\\\n", " ", $command_line);
77
 
 
78
 
        /* output information to the log file if appropriate */
79
 
        if (read_config_option("log_verbosity") >= POLLER_VERBOSITY_DEBUG) {
80
 
                cacti_log("CACTI2RRD: " . read_config_option("path_rrdtool") . " $command_line", $log_to_stdout, $logopt);
81
 
        }
82
 
 
83
 
        /* if we want to see the error output from rrdtool; make sure to specify this */
84
 
        if (($output_flag == RRDTOOL_OUTPUT_STDERR) && (!is_resource($rrdtool_pipe))) {
85
 
                $command_line .= " 2>&1";
86
 
        }
87
 
 
88
 
        /* use popen to eliminate the zombie issue */
89
 
        if ($config["cacti_server_os"] == "unix") {
90
 
                $pipe_mode = "r";
91
 
        }else{
92
 
                $pipe_mode = "rb";
93
 
        }
94
 
 
95
 
        /* an empty $rrdtool_pipe array means no fp is available */
96
 
        if (!is_resource($rrdtool_pipe)) {
97
 
                session_write_close();
98
 
                $fp = popen(read_config_option("path_rrdtool") . escape_command(" $command_line"), $pipe_mode);
99
 
                if (!is_resource($fp)) {
100
 
                        unset($fp);
101
 
                }
102
 
        }else{
103
 
                $i = 0;
104
 
                while (1) {
105
 
                        if (fwrite($rrdtool_pipe, escape_command(" $command_line") . "\r\n") === false) {
106
 
                                cacti_log("ERROR: Detected RRDtool Crash on '$command_line'.  Last command was '$last_command'");
107
 
 
108
 
                                /* close the invalid pipe */
109
 
                                rrd_close($rrdtool_pipe);
110
 
 
111
 
                                /* open a new rrdtool process */
112
 
                                $rrdtool_pipe = rrd_init();
113
 
 
114
 
                                if ($i > 4) {
115
 
                                        cacti_log("FATAL: RRDtool Restart Attempts Exceeded. Giving up on '$command_line'.");
116
 
 
117
 
                                        break;
118
 
                                }else{
119
 
                                        $i++;
120
 
                                }
121
 
 
122
 
                                continue;
123
 
                        }else{
124
 
                                fflush($rrdtool_pipe);
125
 
 
126
 
                                break;
127
 
                        }
128
 
                }
129
 
        }
130
 
 
131
 
        /* store the last command to provide rrdtool segfault diagnostics */
132
 
        $last_command = $command_line;
133
 
 
134
 
        switch ($output_flag) {
135
 
                case RRDTOOL_OUTPUT_NULL:
136
 
                        return;
137
 
                case RRDTOOL_OUTPUT_STDOUT:
138
 
                        if (isset($fp) && is_resource($fp)) {
139
 
                                $line = "";
140
 
                                while (!feof($fp)) {
141
 
                                        $line .= fgets($fp, 4096);
142
 
                                }
143
 
 
144
 
                                pclose($fp);
145
 
 
146
 
                                return $line;
147
 
                        }
148
 
 
149
 
                        break;
150
 
                case RRDTOOL_OUTPUT_STDERR:
151
 
                        if (isset($fp) && is_resource($fp)) {
152
 
                                $output = fgets($fp, 1000000);
153
 
 
154
 
                                pclose($fp);
155
 
 
156
 
                                if (substr($output, 1, 3) == "PNG") {
157
 
                                        return "OK";
158
 
                                }
159
 
 
160
 
                                if (substr($output, 0, 5) == "GIF87") {
161
 
                                        return "OK";
162
 
                                }
163
 
 
164
 
                                print $output;
165
 
                        }
166
 
 
167
 
                        break;
168
 
                case RRDTOOL_OUTPUT_GRAPH_DATA:
169
 
                        if (isset($fp) && is_resource($fp)) {
170
 
                                $line = "";
171
 
                                while (!feof($fp)) {
172
 
                                        $line .= fgets($fp, 4096);
173
 
                                }
174
 
 
175
 
                                pclose($fp);
176
 
 
177
 
                                return $line;
178
 
                        }
179
 
 
180
 
                        break;
181
 
        }
182
 
}
183
 
 
184
 
function rrdtool_function_create($local_data_id, $show_source, $rrdtool_pipe = "") {
185
 
        global $config;
186
 
 
187
 
        include ($config["include_path"] . "/global_arrays.php");
188
 
 
189
 
        $data_source_path = get_data_source_path($local_data_id, true);
190
 
 
191
 
        /* ok, if that passes lets check to make sure an rra does not already
192
 
        exist, the last thing we want to do is overright data! */
193
 
        if ($show_source != true) {
194
 
                if (file_exists($data_source_path) == true) {
195
 
                        return -1;
196
 
                }
197
 
        }
198
 
 
199
 
        /* the first thing we must do is make sure there is at least one
200
 
        rra associated with this data source... *
201
 
        UPDATE: As of version 0.6.6, we are splitting this up into two
202
 
        SQL strings because of the multiple DS per RRD support. This is
203
 
        not a big deal however since this function gets called once per
204
 
        data source */
205
 
 
206
 
        $rras = db_fetch_assoc("select
207
 
                data_template_data.rrd_step,
208
 
                rra.x_files_factor,
209
 
                rra.steps,
210
 
                rra.rows,
211
 
                rra_cf.consolidation_function_id,
212
 
                (rra.rows*rra.steps) as rra_order
213
 
                from data_template_data
214
 
                left join data_template_data_rra on (data_template_data.id=data_template_data_rra.data_template_data_id)
215
 
                left join rra on (data_template_data_rra.rra_id=rra.id)
216
 
                left join rra_cf on (rra.id=rra_cf.rra_id)
217
 
                where data_template_data.local_data_id=$local_data_id
218
 
                and (rra.steps is not null or rra.rows is not null)
219
 
                order by rra_cf.consolidation_function_id,rra_order");
220
 
 
221
 
        /* if we find that this DS has no RRA associated; get out */
222
 
        if (sizeof($rras) <= 0) {
223
 
                cacti_log("ERROR: There are no RRA's assigned to local_data_id: $local_data_id.");
224
 
                return false;
225
 
        }
226
 
 
227
 
        /* create the "--step" line */
228
 
        $create_ds = RRD_NL . "--step ". $rras[0]["rrd_step"] . " " . RRD_NL;
229
 
 
230
 
        /* query the data sources to be used in this .rrd file */
231
 
        $data_sources = db_fetch_assoc("SELECT
232
 
                data_template_rrd.id,
233
 
                data_template_rrd.rrd_heartbeat,
234
 
                data_template_rrd.rrd_minimum,
235
 
                data_template_rrd.rrd_maximum,
236
 
                data_template_rrd.data_source_type_id
237
 
                FROM data_template_rrd
238
 
                WHERE data_template_rrd.local_data_id=$local_data_id
239
 
                ORDER BY local_data_template_rrd_id");
240
 
 
241
 
        /* ONLY make a new DS entry if:
242
 
        - There is multiple data sources and this item is not the main one.
243
 
        - There is only one data source (then use it) */
244
 
 
245
 
        if (sizeof($data_sources) > 0) {
246
 
        foreach ($data_sources as $data_source) {
247
 
                /* use the cacti ds name by default or the user defined one, if entered */
248
 
                $data_source_name = get_data_source_item_name($data_source["id"]);
249
 
 
250
 
                if (empty($data_source["rrd_maximum"])) {
251
 
                        /* in case no maximum is given, use "Undef" value */
252
 
                        $data_source["rrd_maximum"] = "U";
253
 
                } elseif (strpos($data_source["rrd_maximum"], "|query_") !== false) {
254
 
                        /* in case a query variable is given, evaluate it */
255
 
                        $data_local = db_fetch_row("SELECT * FROM data_local WHERE id=" . $local_data_id);
256
 
                        if ($data_source["rrd_maximum"] == "|query_ifSpeed|" || $data_source["rrd_maximum"] == "|query_ifHighSpeed|") {
257
 
                                $highSpeed = db_fetch_cell("SELECT field_value
258
 
                                        FROM host_snmp_cache
259
 
                                        WHERE host_id=" . $data_local["host_id"] . "
260
 
                                        AND snmp_query_id=" . $data_local["snmp_query_id"] . "
261
 
                                        AND snmp_index='" . $data_local["snmp_index"] . "'
262
 
                                        AND field_name='ifHighSpeed'");
263
 
 
264
 
                                if (!empty($highSpeed)) {
265
 
                                        $data_source["rrd_maximum"] = $highSpeed * 1000000;
266
 
                                }else{
267
 
                                        $data_source["rrd_maximum"] = substitute_snmp_query_data("|query_ifSpeed|",$data_local["host_id"], $data_local["snmp_query_id"], $data_local["snmp_index"]);
268
 
                                }
269
 
                        }else{
270
 
                                $data_source["rrd_maximum"] = substitute_snmp_query_data($data_source["rrd_maximum"],$data_local["host_id"], $data_local["snmp_query_id"], $data_local["snmp_index"]);
271
 
                        }
272
 
                } elseif (($data_source["rrd_maximum"] != "U") && (int)$data_source["rrd_maximum"]<=(int)$data_source["rrd_minimum"]) {
273
 
                        /* max > min required, but take care of an "Undef" value */
274
 
                        $data_source["rrd_maximum"] = (int)$data_source["rrd_minimum"]+1;
275
 
                }
276
 
 
277
 
                /* min==max==0 won't work with rrdtool */
278
 
                if ($data_source["rrd_minimum"] == 0 && $data_source["rrd_maximum"] == 0) {
279
 
                        $data_source["rrd_maximum"] = "U";
280
 
                }
281
 
 
282
 
                $create_ds .= "DS:$data_source_name:" . $data_source_types{$data_source["data_source_type_id"]} . ":" . $data_source["rrd_heartbeat"] . ":" . $data_source["rrd_minimum"] . ":" . $data_source["rrd_maximum"] . RRD_NL;
283
 
        }
284
 
        }
285
 
 
286
 
        $create_rra = "";
287
 
        /* loop through each available RRA for this DS */
288
 
        foreach ($rras as $rra) {
289
 
                $create_rra .= "RRA:" . $consolidation_functions{$rra["consolidation_function_id"]} . ":" . $rra["x_files_factor"] . ":" . $rra["steps"] . ":" . $rra["rows"] . RRD_NL;
290
 
        }
291
 
 
292
 
        /* check for structured path configuration, if in place verify directory
293
 
           exists and if not create it.
294
 
         */
295
 
        if (read_config_option("extended_paths") == "on") {
296
 
                if (!is_dir(dirname($data_source_path))) {
297
 
                        if (mkdir(dirname($data_source_path), 0775)) {
298
 
                                if ($config["cacti_server_os"] != "win32") {
299
 
                                        $owner_id      = fileowner($config["rra_path"]);
300
 
                                        $group_id      = filegroup($config["rra_path"]);
301
 
 
302
 
                                        if ((chown(dirname($data_source_path), $owner_id)) &&
303
 
                                                (chgrp(dirname($data_source_path), $group_id))) {
304
 
                                                /* permissions set ok */
305
 
                                        }else{
306
 
                                                cacti_log("ERROR: Unable to set directory permissions for '" . dirname($data_source_path) . "'", FALSE);
307
 
                                        }
308
 
                                }
309
 
                        }else{
310
 
                                cacti_log("ERROR: Unable to create directory '" . dirname($data_source_path) . "'", FALSE);
311
 
                        }
312
 
                }
313
 
        }
314
 
 
315
 
        if ($show_source == true) {
316
 
                return read_config_option("path_rrdtool") . " create" . RRD_NL . "$data_source_path$create_ds$create_rra";
317
 
        }else{
318
 
                rrdtool_execute("create $data_source_path $create_ds$create_rra", true, RRDTOOL_OUTPUT_STDOUT, $rrdtool_pipe, "POLLER");
319
 
        }
320
 
}
321
 
 
322
 
function rrdtool_function_update($update_cache_array, $rrdtool_pipe = "") {
323
 
        /* lets count the number of rrd files processed */
324
 
        $rrds_processed = 0;
325
 
 
326
 
        while (list($rrd_path, $rrd_fields) = each($update_cache_array)) {
327
 
                $create_rrd_file = false;
328
 
 
329
 
                /* create the rrd if one does not already exist */
330
 
                if (!file_exists($rrd_path)) {
331
 
                        rrdtool_function_create($rrd_fields["local_data_id"], false, $rrdtool_pipe);
332
 
 
333
 
                        $create_rrd_file = true;
334
 
                }
335
 
 
336
 
                if ((is_array($rrd_fields["times"])) && (sizeof($rrd_fields["times"]) > 0)) {
337
 
                        ksort($rrd_fields["times"]);
338
 
 
339
 
                        while (list($update_time, $field_array) = each($rrd_fields["times"])) {
340
 
                                if (empty($update_time)) {
341
 
                                        /* default the rrdupdate time to now */
342
 
                                        $current_rrd_update_time = "N";
343
 
                                }else if ($create_rrd_file == true) {
344
 
                                        /* for some reason rrdtool will not let you update using times less than the
345
 
                                        rrd create time */
346
 
                                        $current_rrd_update_time = "N";
347
 
                                }else{
348
 
                                        $current_rrd_update_time = $update_time;
349
 
                                }
350
 
 
351
 
                                $i = 0; $rrd_update_template = ""; $rrd_update_values = $current_rrd_update_time . ":";
352
 
                                while (list($field_name, $value) = each($field_array)) {
353
 
                                        $rrd_update_template .= $field_name;
354
 
 
355
 
                                        /* if we have "invalid data", give rrdtool an Unknown (U) */
356
 
                                        if ((!isset($value)) || (!is_numeric($value))) {
357
 
                                                $value = "U";
358
 
                                        }
359
 
 
360
 
                                        $rrd_update_values .= $value;
361
 
 
362
 
                                        if (($i+1) < count($field_array)) {
363
 
                                                $rrd_update_template .= ":";
364
 
                                                $rrd_update_values .= ":";
365
 
                                        }
366
 
 
367
 
                                        $i++;
368
 
                                }
369
 
 
370
 
                                rrdtool_execute("update $rrd_path --template $rrd_update_template $rrd_update_values", true, RRDTOOL_OUTPUT_STDOUT, $rrdtool_pipe, "POLLER");
371
 
                                $rrds_processed++;
372
 
                        }
373
 
                }
374
 
        }
375
 
 
376
 
        return $rrds_processed;
377
 
}
378
 
 
379
 
function rrdtool_function_tune($rrd_tune_array) {
380
 
        global $config;
381
 
 
382
 
        include($config["include_path"] . "/global_arrays.php");
383
 
 
384
 
        $data_source_name = get_data_source_item_name($rrd_tune_array["data_source_id"]);
385
 
        $data_source_type = $data_source_types{$rrd_tune_array["data-source-type"]};
386
 
        $data_source_path = get_data_source_path($rrd_tune_array["data_source_id"], true);
387
 
 
388
 
        if ($rrd_tune_array["heartbeat"] != "") {
389
 
                $rrd_tune .= " --heartbeat $data_source_name:" . $rrd_tune_array["heartbeat"];
390
 
        }
391
 
 
392
 
        if ($rrd_tune_array["minimum"] != "") {
393
 
                $rrd_tune .= " --minimum $data_source_name:" . $rrd_tune_array["minimum"];
394
 
        }
395
 
 
396
 
        if ($rrd_tune_array["maximum"] != "") {
397
 
                $rrd_tune .= " --maximum $data_source_name:" . $rrd_tune_array["maximum"];
398
 
        }
399
 
 
400
 
        if ($rrd_tune_array["data-source-type"] != "") {
401
 
                $rrd_tune .= " --data-source-type $data_source_name:" . $data_source_type;
402
 
        }
403
 
 
404
 
        if ($rrd_tune_array["data-source-rename"] != "") {
405
 
                $rrd_tune .= " --data-source-rename $data_source_name:" . $rrd_tune_array["data-source-rename"];
406
 
        }
407
 
 
408
 
        if ($rrd_tune != "") {
409
 
                if (file_exists($data_source_path) == true) {
410
 
                        $fp = popen(read_config_option("path_rrdtool") . " tune $data_source_path $rrd_tune", "r");
411
 
                        pclose($fp);
412
 
 
413
 
                        if (read_config_option("log_verbosity") >= POLLER_VERBOSITY_DEBUG) {
414
 
                                cacti_log("CACTI2RRD: " . read_config_option("path_rrdtool") . " tune $data_source_path $rrd_tune");
415
 
                        }
416
 
                }
417
 
        }
418
 
}
419
 
 
420
 
$rrd_fetch_cache = array();
421
 
 
422
 
/* rrdtool_function_fetch - given a data source, return all of its data in an array
423
 
   @arg $local_data_id - the data source to fetch data for
424
 
   @arg $start_time - the start time to use for the data calculation. this value can
425
 
     either be absolute (unix timestamp) or relative (to now)
426
 
   @arg $end_time - the end time to use for the data calculation. this value can
427
 
     either be absolute (unix timestamp) or relative (to now)
428
 
   @arg $resolution - the accuracy of the data measured in seconds
429
 
   @arg $show_unknown - Show unknown 'NAN' values in the output as 'U'
430
 
   @returns - (array) an array containing all data in this data source broken down
431
 
     by each data source item. the maximum of all data source items is included in
432
 
     an item called 'ninety_fifth_percentile_maximum' */
433
 
function rrdtool_function_fetch($local_data_id, $start_time, $end_time, $resolution = 0, $show_unknown = false, $rrdtool_file = null) {
434
 
        global $rrd_fetch_cache;
435
 
 
436
 
        /* validate local data id */
437
 
        if (empty($local_data_id) && is_null($rrdtool_file)) {
438
 
                return array();
439
 
        }
440
 
 
441
 
        /* the cache hash is used to identify unique items in the cache */
442
 
        $current_hash_cache = md5($local_data_id . $start_time . $end_time . $resolution . $show_unknown . $rrdtool_file);
443
 
 
444
 
        /* return the cached entry if available */
445
 
        if (isset($rrd_fetch_cache[$current_hash_cache])) {
446
 
                return $rrd_fetch_cache[$current_hash_cache];
447
 
        }
448
 
 
449
 
        /* initialize fetch array */
450
 
        $fetch_array = array();
451
 
 
452
 
        /* check if we have been passed a file instead of lodal data source to look up */
453
 
        if (is_null($rrdtool_file)) {
454
 
                $data_source_path = get_data_source_path($local_data_id, true);
455
 
        }else{
456
 
                $data_source_path = $rrdtool_file;
457
 
        }
458
 
 
459
 
        /* update the rrdfile if performing a fetch */
460
 
        api_plugin_hook_function('rrdtool_function_fetch_cache_check', $local_data_id);
461
 
 
462
 
        /* build and run the rrdtool fetch command with all of our data */
463
 
        $cmd_line = "fetch $data_source_path AVERAGE -s $start_time -e $end_time";
464
 
        if ($resolution > 0) {
465
 
                $cmd_line .= " -r $resolution";
466
 
        }
467
 
        $output = rrdtool_execute($cmd_line, false, RRDTOOL_OUTPUT_STDOUT);
468
 
 
469
 
        /* grab the first line of the output which contains a list of data sources in this rrd output */
470
 
        $line_one_eol = strpos($output, "\n");
471
 
        $line_one = substr($output, 0, $line_one_eol);
472
 
        $output = substr($output, $line_one_eol);
473
 
 
474
 
        /* split the output into an array */
475
 
        $output = preg_split('/[\r\n]{1,2}/', $output, null, PREG_SPLIT_NO_EMPTY);
476
 
 
477
 
        /* find the data sources in the rrdtool output */
478
 
        if (preg_match_all('/\S+/', $line_one, $data_source_names)) {
479
 
                /* version 1.0.49 changed the output slightly, remove the timestamp label if present */
480
 
                if (preg_match('/^timestamp/', $line_one)) {
481
 
                        array_shift($data_source_names[0]);
482
 
                }
483
 
                $fetch_array["data_source_names"] = $data_source_names[0];
484
 
 
485
 
                /* build a regular expression to match each data source value in the rrdtool output line */
486
 
                $regex = '/[0-9]+:\s+';
487
 
                for ($i=0; $i < count($fetch_array["data_source_names"]); $i++) {
488
 
                        $regex .= '([\-]?[0-9]{1}[.,][0-9]+e[\+-][0-9]{2,3}|-?[Nn][Aa][Nn])';
489
 
 
490
 
                        if ($i < count($fetch_array["data_source_names"]) - 1) {
491
 
                                $regex .= '\s+';
492
 
                        }
493
 
                }
494
 
                $regex .= '/';
495
 
        }
496
 
 
497
 
        /* loop through each line of the output */
498
 
        $fetch_array["values"] = array();
499
 
        for ($j = 0; $j < count($output); $j++) {
500
 
                $matches = array();
501
 
                $max_array = array();
502
 
                /* match the output line */
503
 
                if (preg_match($regex, $output[$j], $matches)) {
504
 
                        /* only process the output line if we have the correct number of matches */
505
 
                        if (count($matches) - 1 == count($fetch_array["data_source_names"])) {
506
 
                                /* get all values from the line and set them to the appropriate data source */
507
 
                                for ($i=1; $i <= count($fetch_array["data_source_names"]); $i++) {
508
 
                                        if (! isset($fetch_array["values"][$i - 1])) {
509
 
                                                $fetch_array["values"][$i - 1] = array();
510
 
                                        }
511
 
                                        if ((strtolower($matches[$i]) == "nan") || (strtolower($matches[$i]) == "-nan")) {
512
 
                                                if ($show_unknown) {
513
 
                                                        $fetch_array["values"][$i - 1][$j] = "U";
514
 
                                                }
515
 
                                        } else {
516
 
                                                list($mantisa, $exponent) = explode('e', $matches[$i]);
517
 
                                                $mantisa = str_replace(",",".",$mantisa);
518
 
                                                $value = ($mantisa * (pow(10, (float)$exponent)));
519
 
                                                $mantisa = str_replace(",",".",$mantisa);
520
 
                                                $fetch_array["values"][$i - 1][$j] = ($value * 1);
521
 
                                                $max_array[$i - 1] = $value;
522
 
                                        }
523
 
                                }
524
 
                                /* get max value for values on the line */
525
 
                                if (count($max_array) > 0) {
526
 
                                        $fetch_array["values"][count($fetch_array["data_source_names"])][$j] = max($max_array);
527
 
                                }
528
 
                        }
529
 
                }
530
 
        }
531
 
        /* add nth percentile maximum data source */
532
 
        if (isset($fetch_array["values"][count($fetch_array["data_source_names"])])) {
533
 
                $fetch_array["data_source_names"][count($fetch_array["data_source_names"])] = "nth_percentile_maximum";
534
 
        }
535
 
 
536
 
        /* clear the cache if it gets too big */
537
 
        if (sizeof($rrd_fetch_cache) >= MAX_FETCH_CACHE_SIZE) {
538
 
                $rrd_fetch_cache = array();
539
 
        }
540
 
 
541
 
        /* update the cache */
542
 
        if (MAX_FETCH_CACHE_SIZE > 0) {
543
 
                $rrd_fetch_cache[$current_hash_cache] = $fetch_array;
544
 
        }
545
 
 
546
 
        return $fetch_array;
547
 
}
548
 
 
549
 
function rrdtool_function_graph($local_graph_id, $rra_id, $graph_data_array, $rrdtool_pipe = "") {
550
 
        global $config, $consolidation_functions;
551
 
 
552
 
        include_once($config["library_path"] . "/cdef.php");
553
 
        include_once($config["library_path"] . "/graph_variables.php");
554
 
        include($config["include_path"] . "/global_arrays.php");
555
 
        
556
 
        
557
 
        /* prevent command injection
558
 
         * This function prepares an rrdtool graph statement to be executed by the web server.
559
 
         * We have to take care, that the attacker does not insert shell code.
560
 
         * As some rrdtool parameters accept "Cacti variables", we have to perform the
561
 
         * variable substitution prior to vulnerability checks.
562
 
         * We will enclose all parameters in quotes and substitute quotation marks within
563
 
         * those parameters. 
564
 
         */
565
 
 
566
 
        /* rrdtool fetches the default font from it's execution environment
567
 
         * you won't find that default font on the rrdtool statement itself!
568
 
         * set the rrdtool default font via environment variable */
569
 
        if (read_config_option("path_rrdtool_default_font")) {
570
 
                putenv("RRD_DEFAULT_FONT=" . read_config_option("path_rrdtool_default_font"));
571
 
        }
572
 
 
573
 
        /* before we do anything; make sure the user has permission to view this graph,
574
 
        if not then get out */
575
 
        if ((read_config_option("auth_method") != 0) && (isset($_SESSION["sess_user_id"]))) {
576
 
                $access_denied = !(is_graph_allowed($local_graph_id));
577
 
 
578
 
                if ($access_denied == true) {
579
 
                        return "GRAPH ACCESS DENIED";
580
 
                }
581
 
        }
582
 
 
583
 
        $data = api_plugin_hook_function('rrdtool_function_graph_cache_check', array('local_graph_id' => $local_graph_id,'rra_id' => $rra_id,'rrd_struc' => $rrdtool_pipe,'graph_data_array' => $graph_data_array, 'return' => false));
584
 
        if (isset($data['return']) && $data['return'] != false)
585
 
                return $data['return'];
586
 
 
587
 
        /* find the step and how often this graph is updated with new data */
588
 
        $ds_step = db_fetch_cell("select
589
 
                data_template_data.rrd_step
590
 
                from (data_template_data,data_template_rrd,graph_templates_item)
591
 
                where graph_templates_item.task_item_id=data_template_rrd.id
592
 
                and data_template_rrd.local_data_id=data_template_data.local_data_id
593
 
                and graph_templates_item.local_graph_id=$local_graph_id
594
 
                limit 0,1");
595
 
        $ds_step = empty($ds_step) ? 300 : $ds_step;
596
 
 
597
 
        /* if no rra was specified, we need to figure out which one RRDTool will choose using
598
 
         * "best-fit" resolution fit algorithm */
599
 
        if (empty($rra_id)) {
600
 
                if ((empty($graph_data_array["graph_start"])) || (empty($graph_data_array["graph_end"]))) {
601
 
                        $rra["rows"] = 600;
602
 
                        $rra["steps"] = 1;
603
 
                        $rra["timespan"] = 86400;
604
 
                }else{
605
 
                        /* get a list of RRAs related to this graph */
606
 
                        $rras = get_associated_rras($local_graph_id);
607
 
 
608
 
                        if (sizeof($rras) > 0) {
609
 
                                foreach ($rras as $unchosen_rra) {
610
 
                                        /* the timespan specified in the RRA "timespan" field may not be accurate */
611
 
                                        $real_timespan = ($ds_step * $unchosen_rra["steps"] * $unchosen_rra["rows"]);
612
 
 
613
 
                                        /* make sure the current start/end times fit within each RRA's timespan */
614
 
                                        if ( (($graph_data_array["graph_end"] - $graph_data_array["graph_start"]) <= $real_timespan) && ((time() - $graph_data_array["graph_start"]) <= $real_timespan) ) {
615
 
                                                /* is this RRA better than the already chosen one? */
616
 
                                                if ((isset($rra)) && ($unchosen_rra["steps"] < $rra["steps"])) {
617
 
                                                        $rra = $unchosen_rra;
618
 
                                                }else if (!isset($rra)) {
619
 
                                                        $rra = $unchosen_rra;
620
 
                                                }
621
 
                                        }
622
 
                                }
623
 
                        }
624
 
 
625
 
                        if (!isset($rra)) {
626
 
                                $rra["rows"] = 600;
627
 
                                $rra["steps"] = 1;
628
 
                        }
629
 
                }
630
 
        }else{
631
 
                $rra = db_fetch_row("select timespan,rows,steps from rra where id=$rra_id");
632
 
        }
633
 
 
634
 
        $seconds_between_graph_updates = ($ds_step * $rra["steps"]);
635
 
 
636
 
        $graph = db_fetch_row("select
637
 
                graph_local.id AS local_graph_id,
638
 
                graph_local.host_id,
639
 
                graph_local.snmp_query_id,
640
 
                graph_local.snmp_index,
641
 
                graph_templates_graph.title_cache,
642
 
                graph_templates_graph.vertical_label,
643
 
                graph_templates_graph.slope_mode,
644
 
                graph_templates_graph.auto_scale,
645
 
                graph_templates_graph.auto_scale_opts,
646
 
                graph_templates_graph.auto_scale_log,
647
 
                graph_templates_graph.scale_log_units,
648
 
                graph_templates_graph.auto_scale_rigid,
649
 
                graph_templates_graph.auto_padding,
650
 
                graph_templates_graph.base_value,
651
 
                graph_templates_graph.upper_limit,
652
 
                graph_templates_graph.lower_limit,
653
 
                graph_templates_graph.height,
654
 
                graph_templates_graph.width,
655
 
                graph_templates_graph.image_format_id,
656
 
                graph_templates_graph.unit_value,
657
 
                graph_templates_graph.unit_exponent_value,
658
 
                graph_templates_graph.export
659
 
                from (graph_templates_graph,graph_local)
660
 
                where graph_local.id=graph_templates_graph.local_graph_id
661
 
                and graph_templates_graph.local_graph_id=$local_graph_id");
662
 
 
663
 
        /* lets make that sql query... */
664
 
        $graph_items = db_fetch_assoc("select
665
 
                graph_templates_item.id as graph_templates_item_id,
666
 
                graph_templates_item.cdef_id,
667
 
                graph_templates_item.text_format,
668
 
                graph_templates_item.value,
669
 
                graph_templates_item.hard_return,
670
 
                graph_templates_item.consolidation_function_id,
671
 
                graph_templates_item.graph_type_id,
672
 
                graph_templates_gprint.gprint_text,
673
 
                colors.hex,
674
 
                graph_templates_item.alpha,
675
 
                data_template_rrd.id as data_template_rrd_id,
676
 
                data_template_rrd.local_data_id,
677
 
                data_template_rrd.rrd_minimum,
678
 
                data_template_rrd.rrd_maximum,
679
 
                data_template_rrd.data_source_name,
680
 
                data_template_rrd.local_data_template_rrd_id
681
 
                from graph_templates_item
682
 
                left join data_template_rrd on (graph_templates_item.task_item_id=data_template_rrd.id)
683
 
                left join colors on (graph_templates_item.color_id=colors.id)
684
 
                left join graph_templates_gprint on (graph_templates_item.gprint_id=graph_templates_gprint.id)
685
 
                where graph_templates_item.local_graph_id=$local_graph_id
686
 
                order by graph_templates_item.sequence");
687
 
 
688
 
        /* +++++++++++++++++++++++ GRAPH OPTIONS +++++++++++++++++++++++ */
689
 
 
690
 
        /* define some variables */
691
 
        $scale = "";
692
 
        $rigid = "";
693
 
        $unit_value = "";
694
 
        $unit_exponent_value = "";
695
 
        $graph_legend = "";
696
 
        $graph_defs = "";
697
 
        $txt_graph_items = "";
698
 
        $text_padding = "";
699
 
        $greatest_text_format = 0;
700
 
        $last_graph_type = "";
701
 
 
702
 
        if ($graph["auto_scale"] == "on") {
703
 
                switch ($graph["auto_scale_opts"]) {
704
 
                        case "1": /* autoscale ignores lower, upper limit */
705
 
                                $scale = "--alt-autoscale" . RRD_NL;
706
 
                                break;
707
 
                        case "2": /* autoscale-max, accepts a given lower limit */
708
 
                                $scale = "--alt-autoscale-max" . RRD_NL;
709
 
                                if ( is_numeric($graph["lower_limit"])) {
710
 
                                        $scale .= "--lower-limit=" . cacti_escapeshellarg($graph["lower_limit"]) . RRD_NL;
711
 
                                }
712
 
                                break;
713
 
                        case "3": /* autoscale-min, accepts a given upper limit */
714
 
                                if (read_config_option("rrdtool_version") != "rrd-1.0.x") {
715
 
                                        $scale = "--alt-autoscale-min" . RRD_NL;
716
 
                                        if ( is_numeric($graph["upper_limit"])) {
717
 
                                                $scale .= "--upper-limit=" . cacti_escapeshellarg($graph["upper_limit"]) . RRD_NL;
718
 
                                        }
719
 
                                }
720
 
                                break;
721
 
                        case "4": /* auto_scale with limits */
722
 
                                $scale = "--alt-autoscale" . RRD_NL;
723
 
                                if ( is_numeric($graph["upper_limit"])) {
724
 
                                        $scale .= "--upper-limit=" . cacti_escapeshellarg($graph["upper_limit"]) . RRD_NL;
725
 
                                }
726
 
                                if ( is_numeric($graph["lower_limit"])) {
727
 
                                        $scale .= "--lower-limit=" . cacti_escapeshellarg($graph["lower_limit"]) . RRD_NL;
728
 
                                }
729
 
                                break;
730
 
                }
731
 
        }else{
732
 
                if (strlen($graph["upper_limit"])) {
733
 
                        $scale =  "--upper-limit=" . cacti_escapeshellarg($graph["upper_limit"]) . RRD_NL;
734
 
                }
735
 
                if (strlen($graph["lower_limit"])) {
736
 
                        $scale .= "--lower-limit=" . cacti_escapeshellarg($graph["lower_limit"]) . RRD_NL;
737
 
                }
738
 
        }
739
 
 
740
 
        if ($graph["auto_scale_log"] == "on") {
741
 
                $scale .= "--logarithmic" . RRD_NL;
742
 
        }
743
 
 
744
 
        /* --units=si only defined for logarithmic y-axis scaling, even if it doesn't hurt on linear graphs */
745
 
        if (($graph["scale_log_units"] == "on") &&
746
 
                ($graph["auto_scale_log"] == "on")) {
747
 
                $scale .= "--units=si" . RRD_NL;
748
 
        }
749
 
 
750
 
        if ($graph["auto_scale_rigid"] == "on") {
751
 
                $rigid = "--rigid" . RRD_NL;
752
 
        }
753
 
 
754
 
        if (!empty($graph["unit_value"])) {
755
 
                if (read_config_option("rrdtool_version") != "rrd-1.0.x") {
756
 
                        $unit_value = "--y-grid=" . cacti_escapeshellarg($graph["unit_value"]) . RRD_NL;
757
 
                }else{
758
 
                        $unit_value = "--unit=" . cacti_escapeshellarg($graph["unit_value"]) . RRD_NL;
759
 
                }
760
 
        }
761
 
 
762
 
        if (preg_match("/^[0-9]+$/", $graph["unit_exponent_value"])) {
763
 
                $unit_exponent_value = "--units-exponent=" . cacti_escapeshellarg($graph["unit_exponent_value"]) . RRD_NL;
764
 
        }
765
 
 
766
 
        /*
767
 
         * optionally you can specify and array that overrides some of the db's values, lets set
768
 
         * that all up here
769
 
         */
770
 
 
771
 
        /* override: graph start time */
772
 
        if ((!isset($graph_data_array["graph_start"])) || ($graph_data_array["graph_start"] == "0")) {
773
 
                $graph_start = -($rra["timespan"]);
774
 
        }else{
775
 
                $graph_start = $graph_data_array["graph_start"];
776
 
        }
777
 
 
778
 
        /* override: graph end time */
779
 
        if ((!isset($graph_data_array["graph_end"])) || ($graph_data_array["graph_end"] == "0")) {
780
 
                $graph_end = -($seconds_between_graph_updates);
781
 
        }else{
782
 
                $graph_end = $graph_data_array["graph_end"];
783
 
        }
784
 
 
785
 
        /* override: graph height (in pixels) */
786
 
        if (isset($graph_data_array["graph_height"])) {
787
 
                $graph_height = $graph_data_array["graph_height"];
788
 
        }else{
789
 
                $graph_height = $graph["height"];
790
 
        }
791
 
 
792
 
        /* override: graph width (in pixels) */
793
 
        if (isset($graph_data_array["graph_width"])) {
794
 
                $graph_width = $graph_data_array["graph_width"];
795
 
        }else{
796
 
                $graph_width = $graph["width"];
797
 
        }
798
 
 
799
 
        /* override: skip drawing the legend? */
800
 
        if (isset($graph_data_array["graph_nolegend"])) {
801
 
                $graph_legend = "--no-legend" . RRD_NL;
802
 
        }else{
803
 
                $graph_legend = "";
804
 
        }
805
 
 
806
 
        /* export options */
807
 
        if (isset($graph_data_array["export"])) {
808
 
                $graph_opts = read_config_option("path_html_export") . "/" . $graph_data_array["export_filename"] . RRD_NL;
809
 
        }else{
810
 
                if (empty($graph_data_array["output_filename"])) {
811
 
                                $graph_opts = "-" . RRD_NL;
812
 
                }else{
813
 
                        $graph_opts = $graph_data_array["output_filename"] . RRD_NL;
814
 
                }
815
 
        }
816
 
 
817
 
        /* setup date format */
818
 
        $date_fmt = read_graph_config_option("default_date_format");
819
 
        $datechar = read_graph_config_option("default_datechar");
820
 
 
821
 
        if ($datechar == GDC_HYPHEN) {
822
 
                $datechar = "-";
823
 
        }else {
824
 
                $datechar = "/";
825
 
        }
826
 
 
827
 
        switch ($date_fmt) {
828
 
                case GD_MO_D_Y:
829
 
                        $graph_date = "m" . $datechar . "d" . $datechar . "Y H:i:s";
830
 
                        break;
831
 
                case GD_MN_D_Y:
832
 
                        $graph_date = "M" . $datechar . "d" . $datechar . "Y H:i:s";
833
 
                        break;
834
 
                case GD_D_MO_Y:
835
 
                        $graph_date = "d" . $datechar . "m" . $datechar . "Y H:i:s";
836
 
                        break;
837
 
                case GD_D_MN_Y:
838
 
                        $graph_date = "d" . $datechar . "M" . $datechar . "Y H:i:s";
839
 
                        break;
840
 
                case GD_Y_MO_D:
841
 
                        $graph_date = "Y" . $datechar . "m" . $datechar . "d H:i:s";
842
 
                        break;
843
 
                case GD_Y_MN_D:
844
 
                        $graph_date = "Y" . $datechar . "M" . $datechar . "d H:i:s";
845
 
                        break;
846
 
        }
847
 
 
848
 
        /* display the timespan for zoomed graphs */
849
 
        if ((isset($graph_data_array["graph_start"])) && (isset($graph_data_array["graph_end"]))) {
850
 
                if (($graph_data_array["graph_start"] < 0) && ($graph_data_array["graph_end"] < 0)) {
851
 
                        if (read_config_option("rrdtool_version") != "rrd-1.0.x") {
852
 
                                $graph_legend .= "COMMENT:\"From " . str_replace(":", "\:", date($graph_date, time()+$graph_data_array["graph_start"])) . " To " . str_replace(":", "\:", date($graph_date, time()+$graph_data_array["graph_end"])) . "\\c\"" . RRD_NL . "COMMENT:\"  \\n\"" . RRD_NL;
853
 
                        }else {
854
 
                                $graph_legend .= "COMMENT:\"From " . date($graph_date, time()+$graph_data_array["graph_start"]) . " To " . date($graph_date, time()+$graph_data_array["graph_end"]) . "\\c\"" . RRD_NL . "COMMENT:\"  \\n\"" . RRD_NL;
855
 
                        }
856
 
                }else if (($graph_data_array["graph_start"] >= 0) && ($graph_data_array["graph_end"] >= 0)) {
857
 
                        if (read_config_option("rrdtool_version") != "rrd-1.0.x") {
858
 
                                $graph_legend .= "COMMENT:\"From " . str_replace(":", "\:", date($graph_date, $graph_data_array["graph_start"])) . " To " . str_replace(":", "\:", date($graph_date, $graph_data_array["graph_end"])) . "\\c\"" . RRD_NL . "COMMENT:\"  \\n\"" . RRD_NL;
859
 
                        }else {
860
 
                                $graph_legend .= "COMMENT:\"From " . date($graph_date, $graph_data_array["graph_start"]) . " To " . date($graph_date, $graph_data_array["graph_end"]) . "\\c\"" . RRD_NL . "COMMENT:\"  \\n\"" . RRD_NL;
861
 
                        }
862
 
                }
863
 
        }
864
 
 
865
 
        /* basic graph options */
866
 
        $graph_opts .=
867
 
                "--imgformat=" . $image_types{$graph["image_format_id"]} . RRD_NL .
868
 
                "--start=" . cacti_escapeshellarg($graph_start) . RRD_NL .
869
 
                "--end=" . cacti_escapeshellarg($graph_end) . RRD_NL .
870
 
                "--title=" . cacti_escapeshellarg($graph["title_cache"]) . RRD_NL .
871
 
                "$rigid" .
872
 
                "--base=" . cacti_escapeshellarg($graph["base_value"]) . RRD_NL .
873
 
                "--height=" . cacti_escapeshellarg($graph_height) . RRD_NL .
874
 
                "--width=" . cacti_escapeshellarg($graph_width) . RRD_NL .
875
 
                "$scale" .
876
 
                "$unit_value" .
877
 
                "$unit_exponent_value" .
878
 
                "$graph_legend" .
879
 
                "--vertical-label=" . cacti_escapeshellarg($graph["vertical_label"]) . RRD_NL;
880
 
 
881
 
        /* rrdtool 1.2.x does not provide smooth lines, let's force it */
882
 
        if (read_config_option("rrdtool_version") != "rrd-1.0.x") {
883
 
                if ($graph["slope_mode"] == "on") {
884
 
                        $graph_opts .= "--slope-mode" . RRD_NL;
885
 
                }
886
 
        }
887
 
 
888
 
        /* rrdtool 1.2 font options */
889
 
        if (read_config_option("rrdtool_version") != "rrd-1.0.x") {
890
 
                /* title fonts */
891
 
                $graph_opts .= rrdtool_set_font("title", ((!empty($graph_data_array["graph_nolegend"])) ? $graph_data_array["graph_nolegend"] : ""));
892
 
 
893
 
                /* axis fonts */
894
 
                $graph_opts .= rrdtool_set_font("axis");
895
 
 
896
 
                /* legend fonts */
897
 
                $graph_opts .= rrdtool_set_font("legend");
898
 
 
899
 
                /* unit fonts */
900
 
                $graph_opts .= rrdtool_set_font("unit");
901
 
        }
902
 
 
903
 
        $i = 0; $j = 0;
904
 
        $last_graph_cf = array();
905
 
        if (sizeof($graph_items) > 0) {
906
 
 
907
 
                /* we need to add a new column "cf_reference", so unless PHP 5 is used, this foreach syntax is required */
908
 
                foreach ($graph_items as $key => $graph_item) {
909
 
                        /* mimic the old behavior: LINE[123], AREA and STACK items use the CF specified in the graph item */
910
 
                        if (($graph_item["graph_type_id"] == GRAPH_ITEM_TYPE_LINE1) ||
911
 
                                ($graph_item["graph_type_id"] == GRAPH_ITEM_TYPE_LINE2) ||
912
 
                                ($graph_item["graph_type_id"] == GRAPH_ITEM_TYPE_LINE3) ||
913
 
                                ($graph_item["graph_type_id"] == GRAPH_ITEM_TYPE_AREA)  ||
914
 
                                ($graph_item["graph_type_id"] == GRAPH_ITEM_TYPE_STACK)) {
915
 
                                $graph_cf = $graph_item["consolidation_function_id"];
916
 
                                /* remember the last CF for this data source for use with GPRINT
917
 
                                 * if e.g. an AREA/AVERAGE and a LINE/MAX is used
918
 
                                 * we will have AVERAGE first and then MAX, depending on GPRINT sequence */
919
 
                                $last_graph_cf["data_source_name"]["local_data_template_rrd_id"] = $graph_cf;
920
 
                                /* remember this for second foreach loop */
921
 
                                $graph_items[$key]["cf_reference"] = $graph_cf;
922
 
                        }elseif ($graph_item["graph_type_id"] == GRAPH_ITEM_TYPE_GPRINT) {
923
 
                                /* ATTENTION!
924
 
                                 * the "CF" given on graph_item edit screen for GPRINT is indeed NOT a real "CF",
925
 
                                 * but an aggregation function
926
 
                                 * see "man rrdgraph_data" for the correct VDEF based notation
927
 
                                 * so our task now is to "guess" the very graph_item, this GPRINT is related to
928
 
                                 * and to use that graph_item's CF */
929
 
                                if (isset($last_graph_cf["data_source_name"]["local_data_template_rrd_id"])) {
930
 
                                        $graph_cf = $last_graph_cf["data_source_name"]["local_data_template_rrd_id"];
931
 
                                        /* remember this for second foreach loop */
932
 
                                        $graph_items[$key]["cf_reference"] = $graph_cf;
933
 
                                } else {
934
 
                                        $graph_cf = generate_graph_best_cf($graph_item["local_data_id"], $graph_item["consolidation_function_id"]);
935
 
                                        /* remember this for second foreach loop */
936
 
                                        $graph_items[$key]["cf_reference"] = $graph_cf;
937
 
                                }
938
 
                        }else{
939
 
                                /* all other types are based on the best matching CF */
940
 
                                $graph_cf = generate_graph_best_cf($graph_item["local_data_id"], $graph_item["consolidation_function_id"]);
941
 
                                /* remember this for second foreach loop */
942
 
                                $graph_items[$key]["cf_reference"] = $graph_cf;
943
 
                        }
944
 
 
945
 
                        if ((!empty($graph_item["local_data_id"])) && (!isset($cf_ds_cache{$graph_item["data_template_rrd_id"]}[$graph_cf]))) {
946
 
                                /* use a user-specified ds path if one is entered */
947
 
                                $data_source_path = get_data_source_path($graph_item["local_data_id"], true);
948
 
 
949
 
                                /* FOR WIN32: Escape all colon for drive letters (ex. D\:/path/to/rra) */
950
 
                                $data_source_path = str_replace(":", "\:", $data_source_path);
951
 
 
952
 
                                if (!empty($data_source_path)) {
953
 
                                        /* NOTE: (Update) Data source DEF names are created using the graph_item_id; then passed
954
 
                                        to a function that matches the digits with letters. rrdtool likes letters instead
955
 
                                        of numbers in DEF names; especially with CDEF's. cdef's are created
956
 
                                        the same way, except a 'cdef' is put on the beginning of the hash */
957
 
                                        $graph_defs .= "DEF:" . generate_graph_def_name(strval($i)) . "=" . cacti_escapeshellarg($data_source_path) . ":" . cacti_escapeshellarg($graph_item["data_source_name"], true) . ":" . $consolidation_functions[$graph_cf] . RRD_NL;
958
 
 
959
 
                                        $cf_ds_cache{$graph_item["data_template_rrd_id"]}[$graph_cf] = "$i";
960
 
 
961
 
                                        $i++;
962
 
                                }
963
 
                        }
964
 
 
965
 
                        /* cache cdef value here to support data query variables in the cdef string */
966
 
                        if (empty($graph_item["cdef_id"])) {
967
 
                                $graph_item["cdef_cache"] = "";
968
 
                                $graph_items[$j]["cdef_cache"] = "";
969
 
                        }else{
970
 
                                $graph_item["cdef_cache"] = get_cdef($graph_item["cdef_id"]);
971
 
                                $graph_items[$j]["cdef_cache"] = get_cdef($graph_item["cdef_id"]);
972
 
                        }
973
 
 
974
 
                        /* +++++++++++++++++++++++ LEGEND: TEXT SUBSTITUTION (<>'s) +++++++++++++++++++++++ */
975
 
 
976
 
                        /* note the current item_id for easy access */
977
 
                        $graph_item_id = $graph_item["graph_templates_item_id"];
978
 
 
979
 
                        /* the following fields will be searched for graph variables */
980
 
                        $variable_fields = array(
981
 
                                "text_format" => array(
982
 
                                        "process_no_legend" => false
983
 
                                        ),
984
 
                                "value" => array(
985
 
                                        "process_no_legend" => true
986
 
                                        ),
987
 
                                "cdef_cache" => array(
988
 
                                        "process_no_legend" => true
989
 
                                        )
990
 
                                );
991
 
 
992
 
                        /* loop through each field that we want to substitute values for:
993
 
                        currently: text format and value */
994
 
                        while (list($field_name, $field_array) = each($variable_fields)) {
995
 
                                /* certain fields do not require values when the legend is not to be shown */
996
 
                                if (($field_array["process_no_legend"] == false) && (isset($graph_data_array["graph_nolegend"]))) {
997
 
                                        continue;
998
 
                                }
999
 
 
1000
 
                                $graph_variables[$field_name][$graph_item_id] = $graph_item[$field_name];
1001
 
 
1002
 
                                /* date/time substitution */
1003
 
                                if (strstr($graph_variables[$field_name][$graph_item_id], "|date_time|")) {
1004
 
                                        $graph_variables[$field_name][$graph_item_id] = str_replace("|date_time|", date('D d M H:i:s T Y', strtotime(db_fetch_cell("select value from settings where name='date'"))), $graph_variables[$field_name][$graph_item_id]);
1005
 
                                }
1006
 
 
1007
 
                                /* data source title substitution */
1008
 
                                if (strstr($graph_variables[$field_name][$graph_item_id], "|data_source_title|")) {
1009
 
                                        $graph_variables[$field_name][$graph_item_id] = str_replace("|data_source_title|", get_data_source_title($graph_item["local_data_id"]), $graph_variables[$field_name][$graph_item_id]);
1010
 
                                }
1011
 
 
1012
 
                                /* data query variables */
1013
 
                                $graph_variables[$field_name][$graph_item_id] = rrd_substitute_host_query_data($graph_variables[$field_name][$graph_item_id], $graph, $graph_item);
1014
 
 
1015
 
                                /* Nth percentile */
1016
 
                                if (preg_match_all("/\|([0-9]{1,2}):(bits|bytes):(\d):(current|total|max|total_peak|all_max_current|all_max_peak|aggregate_max|aggregate_sum|aggregate_current|aggregate):(\d)?\|/", $graph_variables[$field_name][$graph_item_id], $matches, PREG_SET_ORDER)) {
1017
 
                                        foreach ($matches as $match) {
1018
 
                                                $graph_variables[$field_name][$graph_item_id] = str_replace($match[0], variable_nth_percentile($match, $graph_item, $graph_items, $graph_start, $graph_end), $graph_variables[$field_name][$graph_item_id]);
1019
 
                                        }
1020
 
                                }
1021
 
 
1022
 
                                /* bandwidth summation */
1023
 
                                if (preg_match_all("/\|sum:(\d|auto):(current|total|atomic):(\d):(\d+|auto)\|/", $graph_variables[$field_name][$graph_item_id], $matches, PREG_SET_ORDER)) {
1024
 
                                        foreach ($matches as $match) {
1025
 
                                                $graph_variables[$field_name][$graph_item_id] = str_replace($match[0], variable_bandwidth_summation($match, $graph_item, $graph_items, $graph_start, $graph_end, $rra["steps"], $ds_step), $graph_variables[$field_name][$graph_item_id]);
1026
 
                                        }
1027
 
                                }
1028
 
                        }
1029
 
 
1030
 
                        /* if we are not displaying a legend there is no point in us even processing the auto padding,
1031
 
                        text format stuff. */
1032
 
                        if (!isset($graph_data_array["graph_nolegend"])) {
1033
 
                                /* set hard return variable if selected (\n) */
1034
 
                                if ($graph_item["hard_return"] == "on") {
1035
 
                                        $hardreturn[$graph_item_id] = "\\n";
1036
 
                                }else{
1037
 
                                        $hardreturn[$graph_item_id] = "";
1038
 
                                }
1039
 
 
1040
 
                                /* +++++++++++++++++++++++ LEGEND: AUTO PADDING (<>'s) +++++++++++++++++++++++ */
1041
 
 
1042
 
                                /* PADDING: remember this is not perfect! its main use is for the basic graph setup of:
1043
 
                                AREA - GPRINT-CURRENT - GPRINT-AVERAGE - GPRINT-MAXIMUM \n
1044
 
                                of course it can be used in other situations, however may not work as intended.
1045
 
                                If you have any additions to this small peice of code, feel free to send them to me. */
1046
 
                                if ($graph["auto_padding"] == "on") {
1047
 
                                        /* only applies to AREA, STACK and LINEs */
1048
 
                                        if (preg_match("/(AREA|STACK|LINE[123])/", $graph_item_types{$graph_item["graph_type_id"]})) {
1049
 
                                                $text_format_length = mb_strlen($graph_variables["text_format"][$graph_item_id], 'UTF-8');
1050
 
 
1051
 
                                                if ($text_format_length > $greatest_text_format) {
1052
 
                                                        $greatest_text_format = $text_format_length;
1053
 
                                                }
1054
 
                                        }
1055
 
                                }
1056
 
                        }
1057
 
 
1058
 
                        $j++;
1059
 
                }
1060
 
        }
1061
 
 
1062
 
        /* +++++++++++++++++++++++ GRAPH ITEMS: CDEF's +++++++++++++++++++++++ */
1063
 
 
1064
 
        $i = 0;
1065
 
        reset($graph_items);
1066
 
 
1067
 
        /* hack for rrdtool 1.2.x support */
1068
 
        $graph_item_stack_type = "";
1069
 
 
1070
 
        if (sizeof($graph_items) > 0) {
1071
 
        foreach ($graph_items as $graph_item) {
1072
 
                /* first we need to check if there is a DEF for the current data source/cf combination. if so,
1073
 
                we will use that */
1074
 
                if (isset($cf_ds_cache{$graph_item["data_template_rrd_id"]}{$graph_item["consolidation_function_id"]})) {
1075
 
                        $cf_id = $graph_item["consolidation_function_id"];
1076
 
                }else{
1077
 
                /* if there is not a DEF defined for the current data source/cf combination, then we will have to
1078
 
                improvise. choose the first available cf in the following order: AVERAGE, MAX, MIN, LAST */
1079
 
                        if (isset($cf_ds_cache{$graph_item["data_template_rrd_id"]}[1])) {
1080
 
                                $cf_id = 1; /* CF: AVERAGE */
1081
 
                        }elseif (isset($cf_ds_cache{$graph_item["data_template_rrd_id"]}[3])) {
1082
 
                                $cf_id = 3; /* CF: MAX */
1083
 
                        }elseif (isset($cf_ds_cache{$graph_item["data_template_rrd_id"]}[2])) {
1084
 
                                $cf_id = 2; /* CF: MIN */
1085
 
                        }elseif (isset($cf_ds_cache{$graph_item["data_template_rrd_id"]}[4])) {
1086
 
                                $cf_id = 4; /* CF: LAST */
1087
 
                        }else{
1088
 
                                $cf_id = 1; /* CF: AVERAGE */
1089
 
                        }
1090
 
                }
1091
 
                /* now remember the correct CF reference */
1092
 
                $cf_id = $graph_item["cf_reference"];
1093
 
 
1094
 
                /* make cdef string here; a note about CDEF's in cacti. A CDEF is neither unique to a
1095
 
                data source of global cdef, but is unique when those two variables combine. */
1096
 
                $cdef_graph_defs = "";
1097
 
 
1098
 
                if ((!empty($graph_item["cdef_id"])) && (!isset($cdef_cache{$graph_item["cdef_id"]}{$graph_item["data_template_rrd_id"]}[$cf_id]))) {
1099
 
 
1100
 
                        $cdef_string    = $graph_variables["cdef_cache"]{$graph_item["graph_templates_item_id"]};
1101
 
                        $magic_item     = array();
1102
 
                        $already_seen   = array();
1103
 
                        $sources_seen   = array();
1104
 
                        $count_all_ds_dups = 0;
1105
 
                        $count_all_ds_nodups = 0;
1106
 
                        $count_similar_ds_dups = 0;
1107
 
                        $count_similar_ds_nodups = 0;
1108
 
 
1109
 
                        /* if any of those magic variables are requested ... */
1110
 
                        if (preg_match("/(ALL_DATA_SOURCES_(NO)?DUPS|SIMILAR_DATA_SOURCES_(NO)?DUPS)/", $cdef_string) ||
1111
 
                                preg_match("/(COUNT_ALL_DS_(NO)?DUPS|COUNT_SIMILAR_DS_(NO)?DUPS)/", $cdef_string)) {
1112
 
 
1113
 
                                /* now walk through each case to initialize array*/
1114
 
                                if (preg_match("/ALL_DATA_SOURCES_DUPS/", $cdef_string)) {
1115
 
                                        $magic_item["ALL_DATA_SOURCES_DUPS"] = "";
1116
 
                                }
1117
 
                                if (preg_match("/ALL_DATA_SOURCES_NODUPS/", $cdef_string)) {
1118
 
                                        $magic_item["ALL_DATA_SOURCES_NODUPS"] = "";
1119
 
                                }
1120
 
                                if (preg_match("/SIMILAR_DATA_SOURCES_DUPS/", $cdef_string)) {
1121
 
                                        $magic_item["SIMILAR_DATA_SOURCES_DUPS"] = "";
1122
 
                                }
1123
 
                                if (preg_match("/SIMILAR_DATA_SOURCES_NODUPS/", $cdef_string)) {
1124
 
                                        $magic_item["SIMILAR_DATA_SOURCES_NODUPS"] = "";
1125
 
                                }
1126
 
                                if (preg_match("/COUNT_ALL_DS_DUPS/", $cdef_string)) {
1127
 
                                        $magic_item["COUNT_ALL_DS_DUPS"] = "";
1128
 
                                }
1129
 
                                if (preg_match("/COUNT_ALL_DS_NODUPS/", $cdef_string)) {
1130
 
                                        $magic_item["COUNT_ALL_DS_NODUPS"] = "";
1131
 
                                }
1132
 
                                if (preg_match("/COUNT_SIMILAR_DS_DUPS/", $cdef_string)) {
1133
 
                                        $magic_item["COUNT_SIMILAR_DS_DUPS"] = "";
1134
 
                                }
1135
 
                                if (preg_match("/COUNT_SIMILAR_DS_NODUPS/", $cdef_string)) {
1136
 
                                        $magic_item["COUNT_SIMILAR_DS_NODUPS"] = "";
1137
 
                                }
1138
 
 
1139
 
                                /* loop over all graph items */
1140
 
                                for ($t=0;($t<count($graph_items));$t++) {
1141
 
 
1142
 
                                        /* only work on graph items, omit GRPINTs, COMMENTs and stuff */
1143
 
                                        if ((preg_match("/(AREA|STACK|LINE[123])/", $graph_item_types{$graph_items[$t]["graph_type_id"]})) && (!empty($graph_items[$t]["data_template_rrd_id"]))) {
1144
 
                                                /* if the user screws up CF settings, PHP will generate warnings if left unchecked */
1145
 
 
1146
 
                                                /* matching consolidation function? */
1147
 
                                                if (isset($cf_ds_cache{$graph_items[$t]["data_template_rrd_id"]}[$cf_id])) {
1148
 
                                                        $def_name = generate_graph_def_name(strval($cf_ds_cache{$graph_items[$t]["data_template_rrd_id"]}[$cf_id]));
1149
 
 
1150
 
                                                        /* do we need ALL_DATA_SOURCES_DUPS? */
1151
 
                                                        if (isset($magic_item["ALL_DATA_SOURCES_DUPS"])) {
1152
 
                                                                $magic_item["ALL_DATA_SOURCES_DUPS"] .= ($count_all_ds_dups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,$def_name,$def_name,UN,0,$def_name,IF,IF"; /* convert unknowns to '0' first */
1153
 
                                                        }
1154
 
 
1155
 
                                                        /* do we need COUNT_ALL_DS_DUPS? */
1156
 
                                                        if (isset($magic_item["COUNT_ALL_DS_DUPS"])) {
1157
 
                                                                $magic_item["COUNT_ALL_DS_DUPS"] .= ($count_all_ds_dups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,1,$def_name,UN,0,1,IF,IF"; /* convert unknowns to '0' first */
1158
 
                                                        }
1159
 
 
1160
 
                                                        $count_all_ds_dups++;
1161
 
 
1162
 
                                                        /* check if this item also qualifies for NODUPS  */
1163
 
                                                        if(!isset($already_seen[$def_name])) {
1164
 
                                                                if (isset($magic_item["ALL_DATA_SOURCES_NODUPS"])) {
1165
 
                                                                        $magic_item["ALL_DATA_SOURCES_NODUPS"] .= ($count_all_ds_nodups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,$def_name,$def_name,UN,0,$def_name,IF,IF"; /* convert unknowns to '0' first */
1166
 
                                                                }
1167
 
                                                                if (isset($magic_item["COUNT_ALL_DS_NODUPS"])) {
1168
 
                                                                        $magic_item["COUNT_ALL_DS_NODUPS"] .= ($count_all_ds_nodups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,1,$def_name,UN,0,1,IF,IF"; /* convert unknowns to '0' first */
1169
 
                                                                }
1170
 
                                                                $count_all_ds_nodups++;
1171
 
                                                                $already_seen[$def_name]=TRUE;
1172
 
                                                        }
1173
 
 
1174
 
                                                        /* check for SIMILAR data sources */
1175
 
                                                        if ($graph_item["data_source_name"] == $graph_items[$t]["data_source_name"]) {
1176
 
 
1177
 
                                                                /* do we need SIMILAR_DATA_SOURCES_DUPS? */
1178
 
                                                                if (isset($magic_item["SIMILAR_DATA_SOURCES_DUPS"]) && ($graph_item["data_source_name"] == $graph_items[$t]["data_source_name"])) {
1179
 
                                                                        $magic_item["SIMILAR_DATA_SOURCES_DUPS"] .= ($count_similar_ds_dups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,$def_name,$def_name,UN,0,$def_name,IF,IF"; /* convert unknowns to '0' first */
1180
 
                                                                }
1181
 
 
1182
 
                                                                /* do we need COUNT_SIMILAR_DS_DUPS? */
1183
 
                                                                if (isset($magic_item["COUNT_SIMILAR_DS_DUPS"]) && ($graph_item["data_source_name"] == $graph_items[$t]["data_source_name"])) {
1184
 
                                                                        $magic_item["COUNT_SIMILAR_DS_DUPS"] .= ($count_similar_ds_dups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,1,$def_name,UN,0,1,IF,IF"; /* convert unknowns to '0' first */
1185
 
                                                                }
1186
 
 
1187
 
                                                                $count_similar_ds_dups++;
1188
 
 
1189
 
                                                                /* check if this item also qualifies for NODUPS  */
1190
 
                                                                if(!isset($sources_seen{$graph_items[$t]["data_template_rrd_id"]})) {
1191
 
                                                                        if (isset($magic_item["SIMILAR_DATA_SOURCES_NODUPS"])) {
1192
 
                                                                                $magic_item["SIMILAR_DATA_SOURCES_NODUPS"] .= ($count_similar_ds_nodups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,$def_name,$def_name,UN,0,$def_name,IF,IF"; /* convert unknowns to '0' first */
1193
 
                                                                        }
1194
 
                                                                        if (isset($magic_item["COUNT_SIMILAR_DS_NODUPS"]) && ($graph_item["data_source_name"] == $graph_items[$t]["data_source_name"])) {
1195
 
                                                                                $magic_item["COUNT_SIMILAR_DS_NODUPS"] .= ($count_similar_ds_nodups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,1,$def_name,UN,0,1,IF,IF"; /* convert unknowns to '0' first */
1196
 
                                                                        }
1197
 
                                                                        $count_similar_ds_nodups++;
1198
 
                                                                        $sources_seen{$graph_items[$t]["data_template_rrd_id"]} = TRUE;
1199
 
                                                                }
1200
 
                                                        } # SIMILAR data sources
1201
 
                                                } # matching consolidation function?
1202
 
                                        } # only work on graph items, omit GRPINTs, COMMENTs and stuff
1203
 
                                } #  loop over all graph items
1204
 
 
1205
 
                                /* if there is only one item to total, don't even bother with the summation.
1206
 
                                 * Otherwise cdef=a,b,c,+,+ is fine. */
1207
 
                                if ($count_all_ds_dups > 1 && isset($magic_item["ALL_DATA_SOURCES_DUPS"])) {
1208
 
                                        $magic_item["ALL_DATA_SOURCES_DUPS"] .= str_repeat(",+", ($count_all_ds_dups - 2)) . ",+";
1209
 
                                }
1210
 
                                if ($count_all_ds_nodups > 1 && isset($magic_item["ALL_DATA_SOURCES_NODUPS"])) {
1211
 
                                        $magic_item["ALL_DATA_SOURCES_NODUPS"] .= str_repeat(",+", ($count_all_ds_nodups - 2)) . ",+";
1212
 
                                }
1213
 
                                if ($count_similar_ds_dups > 1 && isset($magic_item["SIMILAR_DATA_SOURCES_DUPS"])) {
1214
 
                                        $magic_item["SIMILAR_DATA_SOURCES_DUPS"] .= str_repeat(",+", ($count_similar_ds_dups - 2)) . ",+";
1215
 
                                }
1216
 
                                if ($count_similar_ds_nodups > 1 && isset($magic_item["SIMILAR_DATA_SOURCES_NODUPS"])) {
1217
 
                                        $magic_item["SIMILAR_DATA_SOURCES_NODUPS"] .= str_repeat(",+", ($count_similar_ds_nodups - 2)) . ",+";
1218
 
                                }
1219
 
                                if ($count_all_ds_dups > 1 && isset($magic_item["COUNT_ALL_DS_DUPS"])) {
1220
 
                                        $magic_item["COUNT_ALL_DS_DUPS"] .= str_repeat(",+", ($count_all_ds_dups - 2)) . ",+";
1221
 
                                }
1222
 
                                if ($count_all_ds_nodups > 1 && isset($magic_item["COUNT_ALL_DS_NODUPS"])) {
1223
 
                                        $magic_item["COUNT_ALL_DS_NODUPS"] .= str_repeat(",+", ($count_all_ds_nodups - 2)) . ",+";
1224
 
                                }
1225
 
                                if ($count_similar_ds_dups > 1 && isset($magic_item["COUNT_SIMILAR_DS_DUPS"])) {
1226
 
                                        $magic_item["COUNT_SIMILAR_DS_DUPS"] .= str_repeat(",+", ($count_similar_ds_dups - 2)) . ",+";
1227
 
                                }
1228
 
                                if ($count_similar_ds_nodups > 1 && isset($magic_item["COUNT_SIMILAR_DS_NODUPS"])) {
1229
 
                                        $magic_item["COUNT_SIMILAR_DS_NODUPS"] .= str_repeat(",+", ($count_similar_ds_nodups - 2)) . ",+";
1230
 
                                }
1231
 
                        }
1232
 
 
1233
 
                        $cdef_string = str_replace("CURRENT_DATA_SOURCE", generate_graph_def_name(strval((isset($cf_ds_cache{$graph_item["data_template_rrd_id"]}[$cf_id]) ? $cf_ds_cache{$graph_item["data_template_rrd_id"]}[$cf_id] : "0"))), $cdef_string);
1234
 
 
1235
 
                        /* ALL|SIMILAR_DATA_SOURCES(NO)?DUPS are to be replaced here */
1236
 
                        if (isset($magic_item["ALL_DATA_SOURCES_DUPS"])) {
1237
 
                                $cdef_string = str_replace("ALL_DATA_SOURCES_DUPS", $magic_item["ALL_DATA_SOURCES_DUPS"], $cdef_string);
1238
 
                        }
1239
 
                        if (isset($magic_item["ALL_DATA_SOURCES_NODUPS"])) {
1240
 
                                $cdef_string = str_replace("ALL_DATA_SOURCES_NODUPS", $magic_item["ALL_DATA_SOURCES_NODUPS"], $cdef_string);
1241
 
                        }
1242
 
                        if (isset($magic_item["SIMILAR_DATA_SOURCES_DUPS"])) {
1243
 
                                $cdef_string = str_replace("SIMILAR_DATA_SOURCES_DUPS", $magic_item["SIMILAR_DATA_SOURCES_DUPS"], $cdef_string);
1244
 
                        }
1245
 
                        if (isset($magic_item["SIMILAR_DATA_SOURCES_NODUPS"])) {
1246
 
                                $cdef_string = str_replace("SIMILAR_DATA_SOURCES_NODUPS", $magic_item["SIMILAR_DATA_SOURCES_NODUPS"], $cdef_string);
1247
 
                        }
1248
 
 
1249
 
                        /* COUNT_ALL|SIMILAR_DATA_SOURCES(NO)?DUPS are to be replaced here */
1250
 
                        if (isset($magic_item["COUNT_ALL_DS_DUPS"])) {
1251
 
                                $cdef_string = str_replace("COUNT_ALL_DS_DUPS", $magic_item["COUNT_ALL_DS_DUPS"], $cdef_string);
1252
 
                        }
1253
 
                        if (isset($magic_item["COUNT_ALL_DS_NODUPS"])) {
1254
 
                                $cdef_string = str_replace("COUNT_ALL_DS_NODUPS", $magic_item["COUNT_ALL_DS_NODUPS"], $cdef_string);
1255
 
                        }
1256
 
                        if (isset($magic_item["COUNT_SIMILAR_DS_DUPS"])) {
1257
 
                                $cdef_string = str_replace("COUNT_SIMILAR_DS_DUPS", $magic_item["COUNT_SIMILAR_DS_DUPS"], $cdef_string);
1258
 
                        }
1259
 
                        if (isset($magic_item["COUNT_SIMILAR_DS_NODUPS"])) {
1260
 
                                $cdef_string = str_replace("COUNT_SIMILAR_DS_NODUPS", $magic_item["COUNT_SIMILAR_DS_NODUPS"], $cdef_string);
1261
 
                        }
1262
 
 
1263
 
                        /* data source item variables */
1264
 
                        $cdef_string = str_replace("CURRENT_DS_MINIMUM_VALUE", (empty($graph_item["rrd_minimum"]) ? "0" : $graph_item["rrd_minimum"]), $cdef_string);
1265
 
                        $cdef_string = str_replace("CURRENT_DS_MAXIMUM_VALUE", (empty($graph_item["rrd_maximum"]) ? "0" : $graph_item["rrd_maximum"]), $cdef_string);
1266
 
                        $cdef_string = str_replace("CURRENT_GRAPH_MINIMUM_VALUE", (empty($graph["lower_limit"]) ? "0" : $graph["lower_limit"]), $cdef_string);
1267
 
                        $cdef_string = str_replace("CURRENT_GRAPH_MAXIMUM_VALUE", (empty($graph["upper_limit"]) ? "0" : $graph["upper_limit"]), $cdef_string);
1268
 
 
1269
 
                        /* replace query variables in cdefs */
1270
 
                        $cdef_string = rrd_substitute_host_query_data($cdef_string, $graph, $graph_item);
1271
 
 
1272
 
                        /* make the initial "virtual" cdef name: 'cdef' + [a,b,c,d...] */
1273
 
                        $cdef_graph_defs .= "CDEF:cdef" . generate_graph_def_name(strval($i)) . "=";
1274
 
                        /* prohibit command injection and provide platform specific quoting */
1275
 
                        $cdef_graph_defs .= cacti_escapeshellarg(sanitize_cdef($cdef_string), true);
1276
 
                        $cdef_graph_defs .= " \\\n";
1277
 
 
1278
 
                        /* the CDEF cache is so we do not create duplicate CDEF's on a graph */
1279
 
                        $cdef_cache{$graph_item["cdef_id"]}{$graph_item["data_template_rrd_id"]}[$cf_id] = "$i";
1280
 
                }
1281
 
 
1282
 
                /* add the cdef string to the end of the def string */
1283
 
                $graph_defs .= $cdef_graph_defs;
1284
 
 
1285
 
                /* note the current item_id for easy access */
1286
 
                $graph_item_id = $graph_item["graph_templates_item_id"];
1287
 
 
1288
 
                /* if we are not displaying a legend there is no point in us even processing the auto padding,
1289
 
                text format stuff. */
1290
 
                if ((!isset($graph_data_array["graph_nolegend"])) && ($graph["auto_padding"] == "on")) {
1291
 
                        /* only applies to AREA, STACK and LINEs */
1292
 
                        if (preg_match("/(AREA|STACK|LINE[123])/", $graph_item_types{$graph_item["graph_type_id"]})) {
1293
 
                                $text_format_length = mb_strlen($graph_variables["text_format"][$graph_item_id], 'UTF-8');
1294
 
 
1295
 
                                /* we are basing how much to pad on area and stack text format,
1296
 
                                not gprint. but of course the padding has to be displayed in gprint,
1297
 
                                how fun! */
1298
 
 
1299
 
                                $pad_number = ($greatest_text_format - $text_format_length);
1300
 
                                //cacti_log("MAX: $greatest_text_format, CURR: $text_format_lengths[$item_dsid], DSID: $item_dsid");
1301
 
                                $text_padding = str_pad("", $pad_number);
1302
 
 
1303
 
                        /* two GPRINT's in a row screws up the padding, lets not do that */
1304
 
                        } else if (($graph_item_types{$graph_item["graph_type_id"]} == "GPRINT") && ($last_graph_type == "GPRINT")) {
1305
 
                                $text_padding = "";
1306
 
                        }
1307
 
 
1308
 
                        $last_graph_type = $graph_item_types{$graph_item["graph_type_id"]};
1309
 
                }
1310
 
 
1311
 
                /* we put this in a variable so it can be manipulated before mainly used
1312
 
                if we want to skip it, like below */
1313
 
                $current_graph_item_type = $graph_item_types{$graph_item["graph_type_id"]};
1314
 
 
1315
 
                /* IF this graph item has a data source... get a DEF name for it, or the cdef if that applies
1316
 
                to this graph item */
1317
 
                if ($graph_item["cdef_id"] == "0") {
1318
 
                        if (isset($cf_ds_cache{$graph_item["data_template_rrd_id"]}[$cf_id])) {
1319
 
                                $data_source_name = generate_graph_def_name(strval($cf_ds_cache{$graph_item["data_template_rrd_id"]}[$cf_id]));
1320
 
                        }else{
1321
 
                                $data_source_name = "";
1322
 
                        }
1323
 
                }else{
1324
 
                        $data_source_name = "cdef" . generate_graph_def_name(strval($cdef_cache{$graph_item["cdef_id"]}{$graph_item["data_template_rrd_id"]}[$cf_id]));
1325
 
                }
1326
 
 
1327
 
                /* to make things easier... if there is no text format set; set blank text */
1328
 
                if (!isset($graph_variables["text_format"][$graph_item_id])) {
1329
 
                        $graph_variables["text_format"][$graph_item_id] = "";
1330
 
                } else {
1331
 
                        $graph_variables["text_format"][$graph_item_id] = str_replace('"', '\"', $graph_variables["text_format"][$graph_item_id]); /* escape doublequotes */
1332
 
                }
1333
 
 
1334
 
                if (!isset($hardreturn[$graph_item_id])) {
1335
 
                        $hardreturn[$graph_item_id] = "";
1336
 
                }
1337
 
 
1338
 
                /* +++++++++++++++++++++++ GRAPH ITEMS +++++++++++++++++++++++ */
1339
 
 
1340
 
                /* most of the calculations have been done above. now we have for print everything out
1341
 
                in an RRDTool-friendly fashion */
1342
 
 
1343
 
                $need_rrd_nl = TRUE;
1344
 
 
1345
 
                if ($graph_item_types{$graph_item["graph_type_id"]} == "COMMENT") {
1346
 
                        # perform variable substitution first (in case this will yield an empty results or brings command injection problems)
1347
 
                        $comment_arg = rrd_substitute_host_query_data($graph_variables["text_format"][$graph_item_id], $graph, $graph_item);
1348
 
                        # next, compute the argument of the COMMENT statement and perform injection counter measures
1349
 
                        if (trim($comment_arg) == '') { # an empty COMMENT must be treated with care
1350
 
                                $comment_arg = cacti_escapeshellarg(' ' . $hardreturn[$graph_item_id]);
1351
 
                        } else {
1352
 
                                $comment_arg = cacti_escapeshellarg($comment_arg . $hardreturn[$graph_item_id]);
1353
 
                        }
1354
 
 
1355
 
                        # create rrdtool specific command line
1356
 
                        if (read_config_option("rrdtool_version") != "rrd-1.0.x") {
1357
 
                                $txt_graph_items .= $graph_item_types{$graph_item["graph_type_id"]} . ":" . str_replace(":", "\:", $comment_arg) . " ";
1358
 
                        }else {
1359
 
                                $txt_graph_items .= $graph_item_types{$graph_item["graph_type_id"]} . ":" . $comment_arg . " ";
1360
 
                        }
1361
 
                }elseif (($graph_item_types{$graph_item["graph_type_id"]} == "GPRINT") && (!isset($graph_data_array["graph_nolegend"]))) {
1362
 
                        $graph_variables["text_format"][$graph_item_id] = str_replace(":", "\:", $graph_variables["text_format"][$graph_item_id]); /* escape colons */
1363
 
                        $txt_graph_items .= $graph_item_types{$graph_item["graph_type_id"]} . ":" . $data_source_name . ":" . $consolidation_functions{$graph_item["consolidation_function_id"]} . ":" . cacti_escapeshellarg($text_padding . $graph_variables["text_format"][$graph_item_id] . $graph_item["gprint_text"] . $hardreturn[$graph_item_id]) . " ";
1364
 
                }elseif (preg_match("/^(AREA|LINE[123]|STACK|HRULE|VRULE)$/", $graph_item_types{$graph_item["graph_type_id"]})) {
1365
 
 
1366
 
                        /* initialize any color syntax for graph item */
1367
 
                        if (empty($graph_item["hex"])) {
1368
 
                                $graph_item_color_code = "";
1369
 
                        }else{
1370
 
                                $graph_item_color_code = "#" . $graph_item["hex"];
1371
 
                                if (read_config_option("rrdtool_version") != "rrd-1.0.x") {
1372
 
                                        $graph_item_color_code .= $graph_item["alpha"];
1373
 
                                }
1374
 
                        }
1375
 
 
1376
 
                        if (preg_match("/^(AREA|LINE[123])$/", $graph_item_types{$graph_item["graph_type_id"]})) {
1377
 
                                $graph_item_stack_type = $graph_item_types{$graph_item["graph_type_id"]};
1378
 
                                $graph_variables["text_format"][$graph_item_id] = str_replace(":", "\:", $graph_variables["text_format"][$graph_item_id]); /* escape colons */
1379
 
                                $txt_graph_items .= $graph_item_types{$graph_item["graph_type_id"]} . ":" . $data_source_name . $graph_item_color_code . ":" . cacti_escapeshellarg($graph_variables["text_format"][$graph_item_id] . $hardreturn[$graph_item_id]) . " ";
1380
 
                        }elseif ($graph_item_types{$graph_item["graph_type_id"]} == "STACK") {
1381
 
                                if (read_config_option("rrdtool_version") != "rrd-1.0.x") {
1382
 
                                        $graph_variables["text_format"][$graph_item_id] = str_replace(":", "\:", $graph_variables["text_format"][$graph_item_id]); /* escape colons */
1383
 
                                        $txt_graph_items .= $graph_item_stack_type . ":" . $data_source_name . $graph_item_color_code . ":" . cacti_escapeshellarg($graph_variables["text_format"][$graph_item_id] . $hardreturn[$graph_item_id]) . ":STACK";
1384
 
                                }else {
1385
 
                                        $graph_variables["text_format"][$graph_item_id] = str_replace(":", "\:", $graph_variables["text_format"][$graph_item_id]); /* escape colons */
1386
 
                                        $txt_graph_items .= $graph_item_types{$graph_item["graph_type_id"]} . ":" . $data_source_name . $graph_item_color_code . ":" . cacti_escapeshellarg($graph_variables["text_format"][$graph_item_id] . $hardreturn[$graph_item_id]) . " ";
1387
 
                                }
1388
 
                        }elseif ($graph_item_types{$graph_item["graph_type_id"]} == "HRULE") {
1389
 
                                $graph_variables["text_format"][$graph_item_id] = str_replace(":", "\:", $graph_variables["text_format"][$graph_item_id]); /* escape colons */
1390
 
                                $graph_variables["value"][$graph_item_id] = str_replace(":", "\:", $graph_variables["value"][$graph_item_id]); /* escape colons */
1391
 
                                /* perform variable substitution; if this does not return a number, rrdtool will FAIL! */
1392
 
                                $substitute = rrd_substitute_host_query_data($graph_variables["value"][$graph_item_id], $graph, $graph_item);
1393
 
                                if (is_numeric($substitute)) {
1394
 
                                        $graph_variables["value"][$graph_item_id] = $substitute;
1395
 
                                }
1396
 
                                $txt_graph_items .= $graph_item_types{$graph_item["graph_type_id"]} . ":" . $graph_variables["value"][$graph_item_id] . $graph_item_color_code . ":" . cacti_escapeshellarg($graph_variables["text_format"][$graph_item_id] . $hardreturn[$graph_item_id]) . " ";
1397
 
                        }elseif ($graph_item_types{$graph_item["graph_type_id"]} == "VRULE") {
1398
 
                                $graph_variables["text_format"][$graph_item_id] = str_replace(":", "\:", $graph_variables["text_format"][$graph_item_id]); /* escape colons */
1399
 
 
1400
 
                                if (substr_count($graph_item["value"], ":")) {
1401
 
                                        $value_array = explode(":", $graph_item["value"]);
1402
 
 
1403
 
                                        if ($value_array[0] < 0) {
1404
 
                                                $value = date("U") - (-3600 * $value_array[0]) - 60 * $value_array[1];
1405
 
                                        }else{
1406
 
                                                $value = date("U", mktime($value_array[0],$value_array[1],0));
1407
 
                                        }
1408
 
                                }else if (is_numeric($graph_item["value"])) {
1409
 
                                        $value = $graph_item["value"];
1410
 
                                }
1411
 
 
1412
 
                                $txt_graph_items .= $graph_item_types{$graph_item["graph_type_id"]} . ":" . $value . $graph_item_color_code . ":" . cacti_escapeshellarg($graph_variables["text_format"][$graph_item_id] . $hardreturn[$graph_item_id]) . " ";
1413
 
                        }
1414
 
                }else{
1415
 
                        $need_rrd_nl = FALSE;
1416
 
                }
1417
 
 
1418
 
                $i++;
1419
 
 
1420
 
                if (($i < sizeof($graph_items)) && ($need_rrd_nl)) {
1421
 
                        $txt_graph_items .= RRD_NL;
1422
 
                }
1423
 
        }
1424
 
        }
1425
 
 
1426
 
        $graph_array = api_plugin_hook_function('rrd_graph_graph_options', array('graph_opts' => $graph_opts, 'graph_defs' => $graph_defs, 'txt_graph_items' => $txt_graph_items, 'graph_id' => $local_graph_id, 'start' => $graph_start, 'end' => $graph_end));
1427
 
        if (!empty($graph_array)) {
1428
 
                $graph_defs = $graph_array['graph_defs'];
1429
 
                $txt_graph_items = $graph_array['txt_graph_items'];
1430
 
                $graph_opts = $graph_array['graph_opts'];
1431
 
        }
1432
 
 
1433
 
        /* either print out the source or pass the source onto rrdtool to get us a nice PNG */
1434
 
        if (isset($graph_data_array["print_source"])) {
1435
 
                print "<PRE>" . htmlspecialchars(read_config_option("path_rrdtool") . " graph " . $graph_opts . $graph_defs . $txt_graph_items) . "</PRE>";
1436
 
        }else{
1437
 
                if (isset($graph_data_array["export"])) {
1438
 
                        rrdtool_execute("graph $graph_opts$graph_defs$txt_graph_items", false, RRDTOOL_OUTPUT_NULL, $rrdtool_pipe);
1439
 
                        return 0;
1440
 
                }else{
1441
 
                        $graph_data_array = api_plugin_hook_function('prep_graph_array', $graph_data_array);
1442
 
 
1443
 
                        if (isset($graph_data_array["output_flag"])) {
1444
 
                                $output_flag = $graph_data_array["output_flag"];
1445
 
                        }else{
1446
 
                                $output_flag = RRDTOOL_OUTPUT_GRAPH_DATA;
1447
 
                        }
1448
 
 
1449
 
                        $output = rrdtool_execute("graph $graph_opts$graph_defs$txt_graph_items", false, $output_flag, $rrdtool_pipe);
1450
 
 
1451
 
                        api_plugin_hook_function('rrdtool_function_graph_set_file', array('output' => $output, 'local_graph_id' => $local_graph_id, 'rra_id' => $rra_id));
1452
 
 
1453
 
                        return $output;
1454
 
                }
1455
 
        }
1456
 
}
1457
 
 
1458
 
function rrdtool_function_xport($local_graph_id, $rra_id, $xport_data_array, &$xport_meta) {
1459
 
        global $config, $consolidation_functions;
1460
 
 
1461
 
        include_once($config["library_path"] . "/cdef.php");
1462
 
        include_once($config["library_path"] . "/graph_variables.php");
1463
 
        include_once($config["library_path"] . "/xml.php");
1464
 
        include($config["include_path"] . "/global_arrays.php");
1465
 
 
1466
 
        /* before we do anything; make sure the user has permission to view this graph,
1467
 
        if not then get out */
1468
 
        if ((read_config_option("auth_method") != 0) && (isset($_SESSION["sess_user_id"]))) {
1469
 
                $access_denied = !(is_graph_allowed($local_graph_id));
1470
 
 
1471
 
                if ($access_denied == true) {
1472
 
                        return "GRAPH ACCESS DENIED";
1473
 
                }
1474
 
        }
1475
 
 
1476
 
        /* find the step and how often this graph is updated with new data */
1477
 
        $ds_step = db_fetch_cell("select
1478
 
                data_template_data.rrd_step
1479
 
                from (data_template_data,data_template_rrd,graph_templates_item)
1480
 
                where graph_templates_item.task_item_id=data_template_rrd.id
1481
 
                and data_template_rrd.local_data_id=data_template_data.local_data_id
1482
 
                and graph_templates_item.local_graph_id=$local_graph_id
1483
 
                limit 0,1");
1484
 
        $ds_step = empty($ds_step) ? 300 : $ds_step;
1485
 
 
1486
 
        /* if no rra was specified, we need to figure out which one RRDTool will choose using
1487
 
         * "best-fit" resolution fit algorithm */
1488
 
        if (empty($rra_id)) {
1489
 
                if ((empty($xport_data_array["graph_start"])) || (empty($xport_data_array["graph_end"]))) {
1490
 
                        $rra["rows"] = 600;
1491
 
                        $rra["steps"] = 1;
1492
 
                        $rra["timespan"] = 86400;
1493
 
                }else{
1494
 
                        /* get a list of RRAs related to this graph */
1495
 
                        $rras = get_associated_rras($local_graph_id);
1496
 
 
1497
 
                        if (sizeof($rras) > 0) {
1498
 
                                foreach ($rras as $unchosen_rra) {
1499
 
                                        /* the timespan specified in the RRA "timespan" field may not be accurate */
1500
 
                                        $real_timespan = ($ds_step * $unchosen_rra["steps"] * $unchosen_rra["rows"]);
1501
 
 
1502
 
                                        /* make sure the current start/end times fit within each RRA's timespan */
1503
 
                                        if ( (($xport_data_array["graph_end"] - $xport_data_array["graph_start"]) <= $real_timespan) && ((time() - $xport_data_array["graph_start"]) <= $real_timespan) ) {
1504
 
                                                /* is this RRA better than the already chosen one? */
1505
 
                                                if ((isset($rra)) && ($unchosen_rra["steps"] < $rra["steps"])) {
1506
 
                                                        $rra = $unchosen_rra;
1507
 
                                                }else if (!isset($rra)) {
1508
 
                                                        $rra = $unchosen_rra;
1509
 
                                                }
1510
 
                                        }
1511
 
                                }
1512
 
                        }
1513
 
 
1514
 
                        if (!isset($rra)) {
1515
 
                                $rra["rows"] = 600;
1516
 
                                $rra["steps"] = 1;
1517
 
                        }
1518
 
                }
1519
 
        }else{
1520
 
                $rra = db_fetch_row("select timespan,rows,steps from rra where id=$rra_id");
1521
 
        }
1522
 
 
1523
 
        $seconds_between_graph_updates = ($ds_step * $rra["steps"]);
1524
 
 
1525
 
        /* override: graph start time */
1526
 
        if ((!isset($xport_data_array["graph_start"])) || ($xport_data_array["graph_start"] == "0")) {
1527
 
                $graph_start = -($rra["timespan"]);
1528
 
        }else{
1529
 
                $graph_start = $xport_data_array["graph_start"];
1530
 
        }
1531
 
 
1532
 
        /* override: graph end time */
1533
 
        if ((!isset($xport_data_array["graph_end"])) || ($xport_data_array["graph_end"] == "0")) {
1534
 
                $graph_end = -($seconds_between_graph_updates);
1535
 
        }else{
1536
 
                $graph_end = $xport_data_array["graph_end"];
1537
 
        }
1538
 
 
1539
 
        $graph = db_fetch_row("select
1540
 
                graph_local.id AS local_graph_id,
1541
 
                graph_local.host_id,
1542
 
                graph_local.snmp_query_id,
1543
 
                graph_local.snmp_index,
1544
 
                graph_templates_graph.title_cache,
1545
 
                graph_templates_graph.vertical_label,
1546
 
                graph_templates_graph.slope_mode,
1547
 
                graph_templates_graph.auto_scale,
1548
 
                graph_templates_graph.auto_scale_opts,
1549
 
                graph_templates_graph.auto_scale_log,
1550
 
                graph_templates_graph.scale_log_units,
1551
 
                graph_templates_graph.auto_scale_rigid,
1552
 
                graph_templates_graph.auto_padding,
1553
 
                graph_templates_graph.base_value,
1554
 
                graph_templates_graph.upper_limit,
1555
 
                graph_templates_graph.lower_limit,
1556
 
                graph_templates_graph.height,
1557
 
                graph_templates_graph.width,
1558
 
                graph_templates_graph.image_format_id,
1559
 
                graph_templates_graph.unit_value,
1560
 
                graph_templates_graph.unit_exponent_value,
1561
 
                graph_templates_graph.export
1562
 
                from (graph_templates_graph,graph_local)
1563
 
                where graph_local.id=graph_templates_graph.local_graph_id
1564
 
                and graph_templates_graph.local_graph_id=$local_graph_id");
1565
 
 
1566
 
        /* lets make that sql query... */
1567
 
        $xport_items = db_fetch_assoc("select
1568
 
                graph_templates_item.id as graph_templates_item_id,
1569
 
                graph_templates_item.cdef_id,
1570
 
                graph_templates_item.text_format,
1571
 
                graph_templates_item.value,
1572
 
                graph_templates_item.hard_return,
1573
 
                graph_templates_item.consolidation_function_id,
1574
 
                graph_templates_item.graph_type_id,
1575
 
                graph_templates_gprint.gprint_text,
1576
 
                colors.hex,
1577
 
                graph_templates_item.alpha,
1578
 
                data_template_rrd.id as data_template_rrd_id,
1579
 
                data_template_rrd.local_data_id,
1580
 
                data_template_rrd.rrd_minimum,
1581
 
                data_template_rrd.rrd_maximum,
1582
 
                data_template_rrd.data_source_name,
1583
 
                data_template_rrd.local_data_template_rrd_id
1584
 
                from graph_templates_item
1585
 
                left join data_template_rrd on (graph_templates_item.task_item_id=data_template_rrd.id)
1586
 
                left join colors on (graph_templates_item.color_id=colors.id)
1587
 
                left join graph_templates_gprint on (graph_templates_item.gprint_id=graph_templates_gprint.id)
1588
 
                where graph_templates_item.local_graph_id=$local_graph_id
1589
 
                order by graph_templates_item.sequence");
1590
 
 
1591
 
        /* +++++++++++++++++++++++ XPORT OPTIONS +++++++++++++++++++++++ */
1592
 
 
1593
 
        /* override: graph start time */
1594
 
        if ((!isset($xport_data_array["graph_start"])) || ($xport_data_array["graph_start"] == "0")) {
1595
 
                $xport_start = -($rra["timespan"]);
1596
 
        }else{
1597
 
                $xport_start = $xport_data_array["graph_start"];
1598
 
        }
1599
 
 
1600
 
        /* override: graph end time */
1601
 
        if ((!isset($xport_data_array["graph_end"])) || ($xport_data_array["graph_end"] == "0")) {
1602
 
                $xport_end = -($seconds_between_graph_updates);
1603
 
        }else{
1604
 
                $xport_end = $xport_data_array["graph_end"];
1605
 
        }
1606
 
 
1607
 
        /* basic export options */
1608
 
        $xport_opts =
1609
 
                "--start=" . cacti_escapeshellarg($xport_start) . RRD_NL .
1610
 
                "--end=" . cacti_escapeshellarg($xport_end) . RRD_NL .
1611
 
                "--maxrows=10000" . RRD_NL;
1612
 
 
1613
 
        $xport_defs = "";
1614
 
 
1615
 
        $i = 0; $j = 0;
1616
 
        $nth = 0; $sum = 0;
1617
 
        if (sizeof($xport_items) > 0) {
1618
 
                /* we need to add a new column "cf_reference", so unless PHP 5 is used, this foreach syntax is required */
1619
 
                foreach ($xport_items as $key => $xport_item) {
1620
 
                        /* mimic the old behavior: LINE[123], AREA, STACK and GPRINT items use the CF specified in the graph item */
1621
 
                        if (($xport_item["graph_type_id"] == GRAPH_ITEM_TYPE_LINE1) ||
1622
 
                                ($xport_item["graph_type_id"] == GRAPH_ITEM_TYPE_LINE2) ||
1623
 
                                ($xport_item["graph_type_id"] == GRAPH_ITEM_TYPE_LINE3) ||
1624
 
                                ($xport_item["graph_type_id"] == GRAPH_ITEM_TYPE_AREA)  ||
1625
 
                                ($xport_item["graph_type_id"] == GRAPH_ITEM_TYPE_STACK)) {
1626
 
                                $xport_cf = $xport_item["consolidation_function_id"];
1627
 
                                $last_xport_cf["data_source_name"]["local_data_template_rrd_id"] = $xport_cf;
1628
 
                                /* remember this for second foreach loop */
1629
 
                                $xport_items[$key]["cf_reference"] = $xport_cf;
1630
 
                        }elseif ($xport_item["graph_type_id"] == GRAPH_ITEM_TYPE_GPRINT) {
1631
 
                                /* ATTENTION!
1632
 
                                 * the "CF" given on graph_item edit screen for GPRINT is indeed NOT a real "CF",
1633
 
                                 * but an aggregation function
1634
 
                                 * see "man rrdgraph_data" for the correct VDEF based notation
1635
 
                                 * so our task now is to "guess" the very graph_item, this GPRINT is related to
1636
 
                                 * and to use that graph_item's CF */
1637
 
                                if (isset($last_xport_cf["data_source_name"]["local_data_template_rrd_id"])) {
1638
 
                                        $xport_cf = $last_xport_cf["data_source_name"]["local_data_template_rrd_id"];
1639
 
                                        /* remember this for second foreach loop */
1640
 
                                        $xport_items[$key]["cf_reference"] = $xport_cf;
1641
 
                                } else {
1642
 
                                        $xport_cf = generate_graph_best_cf($xport_item["local_data_id"], $xport_item["consolidation_function_id"]);
1643
 
                                        /* remember this for second foreach loop */
1644
 
                                        $xport_items[$key]["cf_reference"] = $xport_cf;
1645
 
                                }
1646
 
                        }else{
1647
 
                                /* all other types are based on the best matching CF */
1648
 
                                $xport_cf = generate_graph_best_cf($xport_item["local_data_id"], $xport_item["consolidation_function_id"]);
1649
 
                                /* remember this for second foreach loop */
1650
 
                                $xport_items[$key]["cf_reference"] = $xport_cf;
1651
 
                        }
1652
 
 
1653
 
                        if ((!empty($xport_item["local_data_id"])) &&
1654
 
                                (!isset($cf_ds_cache{$xport_item["data_template_rrd_id"]}[$xport_cf]))) {
1655
 
                                /* use a user-specified ds path if one is entered */
1656
 
                                $data_source_path = get_data_source_path($xport_item["local_data_id"], true);
1657
 
 
1658
 
                                /* FOR WIN32: Escape all colon for drive letters (ex. D\:/path/to/rra) */
1659
 
                                $data_source_path = str_replace(":", "\:", $data_source_path);
1660
 
 
1661
 
                                if (!empty($data_source_path)) {
1662
 
                                        /* NOTE: (Update) Data source DEF names are created using the graph_item_id; then passed
1663
 
                                        to a function that matches the digits with letters. rrdtool likes letters instead
1664
 
                                        of numbers in DEF names; especially with CDEF's. cdef's are created
1665
 
                                        the same way, except a 'cdef' is put on the beginning of the hash */
1666
 
                                        $xport_defs .= "DEF:" . generate_graph_def_name(strval($i)) . "=" . cacti_escapeshellarg($data_source_path) . ":" . cacti_escapeshellarg($xport_item["data_source_name"], true) . ":" . $consolidation_functions[$xport_cf] . RRD_NL;
1667
 
 
1668
 
                                        $cf_ds_cache{$xport_item["data_template_rrd_id"]}[$xport_cf] = "$i";
1669
 
 
1670
 
                                        $i++;
1671
 
                                }
1672
 
                        }
1673
 
 
1674
 
                        /* cache cdef value here to support data query variables in the cdef string */
1675
 
                        if (empty($xport_item["cdef_id"])) {
1676
 
                                $xport_item["cdef_cache"] = "";
1677
 
                                $xport_items[$j]["cdef_cache"] = "";
1678
 
                        }else{
1679
 
                                $xport_item["cdef_cache"] = get_cdef($xport_item["cdef_id"]);
1680
 
                                $xport_items[$j]["cdef_cache"] = get_cdef($xport_item["cdef_id"]);
1681
 
                        }
1682
 
 
1683
 
                        /* +++++++++++++++++++++++ LEGEND: TEXT SUBSTITUTION (<>'s) +++++++++++++++++++++++ */
1684
 
 
1685
 
                        /* note the current item_id for easy access */
1686
 
                        $xport_item_id = $xport_item["graph_templates_item_id"];
1687
 
 
1688
 
                        /* the following fields will be searched for graph variables */
1689
 
                        $variable_fields = array(
1690
 
                                "text_format" => array(
1691
 
                                        "process_no_legend" => false
1692
 
                                        ),
1693
 
                                "value" => array(
1694
 
                                        "process_no_legend" => true
1695
 
                                        ),
1696
 
                                "cdef_cache" => array(
1697
 
                                        "process_no_legend" => true
1698
 
                                        )
1699
 
                                );
1700
 
 
1701
 
                        /* loop through each field that we want to substitute values for:
1702
 
                        currently: text format and value */
1703
 
                        while (list($field_name, $field_array) = each($variable_fields)) {
1704
 
                                /* certain fields do not require values when the legend is not to be shown */
1705
 
                                if (($field_array["process_no_legend"] == false) && (isset($xport_data_array["graph_nolegend"]))) {
1706
 
                                        continue;
1707
 
                                }
1708
 
 
1709
 
                                $xport_variables[$field_name][$xport_item_id] = $xport_item[$field_name];
1710
 
 
1711
 
                                /* date/time substitution */
1712
 
                                if (strstr($xport_variables[$field_name][$xport_item_id], "|date_time|")) {
1713
 
                                        $xport_variables[$field_name][$xport_item_id] = str_replace("|date_time|", date('D d M H:i:s T Y', strtotime(db_fetch_cell("select value from settings where name='date'"))), $xport_variables[$field_name][$xport_item_id]);
1714
 
                                }
1715
 
 
1716
 
                                /* data query variables */
1717
 
                                $xport_variables[$field_name][$xport_item_id] = rrd_substitute_host_query_data($xport_variables[$field_name][$xport_item_id], $graph, $xport_item);
1718
 
 
1719
 
                                /* Nth percentile */
1720
 
                                if (preg_match_all("/\|([0-9]{1,2}):(bits|bytes):(\d):(current|total|max|total_peak|all_max_current|all_max_peak|aggregate_max|aggregate_sum|aggregate_current|aggregate):(\d)?\|/", $xport_variables[$field_name][$xport_item_id], $matches, PREG_SET_ORDER)) {
1721
 
                                        foreach ($matches as $match) {
1722
 
                                                if ($field_name == "value") {
1723
 
                                                        $xport_meta["NthPercentile"][$nth]["format"] = $match[0];
1724
 
                                                        $xport_meta["NthPercentile"][$nth]["value"]  = str_replace($match[0], variable_nth_percentile($match, $xport_item, $xport_items, $graph_start, $graph_end), $xport_variables[$field_name][$xport_item_id]);
1725
 
                                                        $nth++;
1726
 
                                                }
1727
 
                                        }
1728
 
                                }
1729
 
 
1730
 
                                /* bandwidth summation */
1731
 
                                if (preg_match_all("/\|sum:(\d|auto):(current|total|atomic):(\d):(\d+|auto)\|/", $xport_variables[$field_name][$xport_item_id], $matches, PREG_SET_ORDER)) {
1732
 
                                        foreach ($matches as $match) {
1733
 
                                                if ($field_name == "text_format") {
1734
 
                                                        $xport_meta["Summation"][$sum]["format"] = $match[0];
1735
 
                                                        $xport_meta["Summation"][$sum]["value"]  = str_replace($match[0], variable_bandwidth_summation($match, $xport_item, $xport_items, $graph_start, $graph_end, $rra["steps"], $ds_step), $xport_variables[$field_name][$xport_item_id]);
1736
 
                                                        $sum++;
1737
 
                                                }
1738
 
                                        }
1739
 
                                }
1740
 
                        }
1741
 
 
1742
 
                        $j++;
1743
 
                }
1744
 
        }
1745
 
 
1746
 
        /* +++++++++++++++++++++++ CDEF's +++++++++++++++++++++++ */
1747
 
 
1748
 
        $i = 0;
1749
 
        $j = 1;
1750
 
        reset($xport_items);
1751
 
 
1752
 
        $xport_item_stack_type = "";
1753
 
        $txt_xport_items       = "";
1754
 
        $stacked_columns       = array();
1755
 
 
1756
 
        if (sizeof($xport_items) > 0) {
1757
 
        foreach ($xport_items as $xport_item) {
1758
 
                /* first we need to check if there is a DEF for the current data source/cf combination. if so,
1759
 
                we will use that */
1760
 
                if (isset($cf_ds_cache{$xport_item["data_template_rrd_id"]}{$xport_item["consolidation_function_id"]})) {
1761
 
                        $cf_id = $xport_item["consolidation_function_id"];
1762
 
                }else{
1763
 
                /* if there is not a DEF defined for the current data source/cf combination, then we will have to
1764
 
                improvise. choose the first available cf in the following order: AVERAGE, MAX, MIN, LAST */
1765
 
                        if (isset($cf_ds_cache{$xport_item["data_template_rrd_id"]}[1])) {
1766
 
                                $cf_id = 1; /* CF: AVERAGE */
1767
 
                        }elseif (isset($cf_ds_cache{$xport_item["data_template_rrd_id"]}[3])) {
1768
 
                                $cf_id = 3; /* CF: MAX */
1769
 
                        }elseif (isset($cf_ds_cache{$xport_item["data_template_rrd_id"]}[2])) {
1770
 
                                $cf_id = 2; /* CF: MIN */
1771
 
                        }elseif (isset($cf_ds_cache{$xport_item["data_template_rrd_id"]}[4])) {
1772
 
                                $cf_id = 4; /* CF: LAST */
1773
 
                        }else{
1774
 
                                $cf_id = 1; /* CF: AVERAGE */
1775
 
                        }
1776
 
                }
1777
 
                /* now remember the correct CF reference */
1778
 
                $cf_id = $xport_item["cf_reference"];
1779
 
 
1780
 
                /* make cdef string here; a note about CDEF's in cacti. A CDEF is neither unique to a
1781
 
                data source of global cdef, but is unique when those two variables combine. */
1782
 
                $cdef_xport_defs = ""; $cdef_all_ds_dups = ""; $cdef_similar_ds_dups = "";
1783
 
                $cdef_similar_ds_nodups = ""; $cdef_all_ds_nodups = "";
1784
 
 
1785
 
                if ((!empty($xport_item["cdef_id"])) && (!isset($cdef_cache{$xport_item["cdef_id"]}{$xport_item["data_template_rrd_id"]}[$cf_id]))) {
1786
 
 
1787
 
                        $cdef_string = $xport_variables["cdef_cache"]{$xport_item["graph_templates_item_id"]};
1788
 
                        $magic_item     = array();
1789
 
                        $already_seen   = array();
1790
 
                        $sources_seen   = array();
1791
 
                        $count_all_ds_dups = 0;
1792
 
                        $count_all_ds_nodups = 0;
1793
 
                        $count_similar_ds_dups = 0;
1794
 
                        $count_similar_ds_nodups = 0;
1795
 
 
1796
 
                        /* if any of those magic variables are requested ... */
1797
 
                        if (preg_match("/(ALL_DATA_SOURCES_(NO)?DUPS|SIMILAR_DATA_SOURCES_(NO)?DUPS)/", $cdef_string) ||
1798
 
                                preg_match("/(COUNT_ALL_DS_(NO)?DUPS|COUNT_SIMILAR_DS_(NO)?DUPS)/", $cdef_string)) {
1799
 
 
1800
 
                                /* now walk through each case to initialize array*/
1801
 
                                if (preg_match("/ALL_DATA_SOURCES_DUPS/", $cdef_string)) {
1802
 
                                        $magic_item["ALL_DATA_SOURCES_DUPS"] = "";
1803
 
                                }
1804
 
                                if (preg_match("/ALL_DATA_SOURCES_NODUPS/", $cdef_string)) {
1805
 
                                        $magic_item["ALL_DATA_SOURCES_NODUPS"] = "";
1806
 
                                }
1807
 
                                if (preg_match("/SIMILAR_DATA_SOURCES_DUPS/", $cdef_string)) {
1808
 
                                        $magic_item["SIMILAR_DATA_SOURCES_DUPS"] = "";
1809
 
                                }
1810
 
                                if (preg_match("/SIMILAR_DATA_SOURCES_NODUPS/", $cdef_string)) {
1811
 
                                        $magic_item["SIMILAR_DATA_SOURCES_NODUPS"] = "";
1812
 
                                }
1813
 
                                if (preg_match("/COUNT_ALL_DS_DUPS/", $cdef_string)) {
1814
 
                                        $magic_item["COUNT_ALL_DS_DUPS"] = "";
1815
 
                                }
1816
 
                                if (preg_match("/COUNT_ALL_DS_NODUPS/", $cdef_string)) {
1817
 
                                        $magic_item["COUNT_ALL_DS_NODUPS"] = "";
1818
 
                                }
1819
 
                                if (preg_match("/COUNT_SIMILAR_DS_DUPS/", $cdef_string)) {
1820
 
                                        $magic_item["COUNT_SIMILAR_DS_DUPS"] = "";
1821
 
                                }
1822
 
                                if (preg_match("/COUNT_SIMILAR_DS_NODUPS/", $cdef_string)) {
1823
 
                                        $magic_item["COUNT_SIMILAR_DS_NODUPS"] = "";
1824
 
                                }
1825
 
 
1826
 
                                /* loop over all graph items */
1827
 
                                for ($t=0;($t<count($xport_items));$t++) {
1828
 
 
1829
 
                                        /* only work on graph items, omit GRPINTs, COMMENTs and stuff */
1830
 
                                        if ((preg_match("/(AREA|STACK|LINE[123])/", $graph_item_types{$xport_items[$t]["graph_type_id"]})) && (!empty($xport_items[$t]["data_template_rrd_id"]))) {
1831
 
                                                /* if the user screws up CF settings, PHP will generate warnings if left unchecked */
1832
 
 
1833
 
                                                /* matching consolidation function? */
1834
 
                                                if (isset($cf_ds_cache{$xport_items[$t]["data_template_rrd_id"]}[$cf_id])) {
1835
 
                                                        $def_name = generate_graph_def_name(strval($cf_ds_cache{$xport_items[$t]["data_template_rrd_id"]}[$cf_id]));
1836
 
 
1837
 
                                                        /* do we need ALL_DATA_SOURCES_DUPS? */
1838
 
                                                        if (isset($magic_item["ALL_DATA_SOURCES_DUPS"])) {
1839
 
                                                                $magic_item["ALL_DATA_SOURCES_DUPS"] .= ($count_all_ds_dups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,$def_name,$def_name,UN,0,$def_name,IF,IF"; /* convert unknowns to '0' first */
1840
 
                                                        }
1841
 
 
1842
 
                                                        /* do we need COUNT_ALL_DS_DUPS? */
1843
 
                                                        if (isset($magic_item["COUNT_ALL_DS_DUPS"])) {
1844
 
                                                                $magic_item["COUNT_ALL_DS_DUPS"] .= ($count_all_ds_dups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,1,$def_name,UN,0,1,IF,IF"; /* convert unknowns to '0' first */
1845
 
                                                        }
1846
 
 
1847
 
                                                        $count_all_ds_dups++;
1848
 
 
1849
 
                                                        /* check if this item also qualifies for NODUPS  */
1850
 
                                                        if(!isset($already_seen[$def_name])) {
1851
 
                                                                if (isset($magic_item["ALL_DATA_SOURCES_NODUPS"])) {
1852
 
                                                                        $magic_item["ALL_DATA_SOURCES_NODUPS"] .= ($count_all_ds_nodups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,$def_name,$def_name,UN,0,$def_name,IF,IF"; /* convert unknowns to '0' first */
1853
 
                                                                }
1854
 
                                                                if (isset($magic_item["COUNT_ALL_DS_NODUPS"])) {
1855
 
                                                                        $magic_item["COUNT_ALL_DS_NODUPS"] .= ($count_all_ds_nodups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,1,$def_name,UN,0,1,IF,IF"; /* convert unknowns to '0' first */
1856
 
                                                                }
1857
 
                                                                $count_all_ds_nodups++;
1858
 
                                                                $already_seen[$def_name]=TRUE;
1859
 
                                                        }
1860
 
 
1861
 
                                                        /* check for SIMILAR data sources */
1862
 
                                                        if ($xport_item["data_source_name"] == $xport_items[$t]["data_source_name"]) {
1863
 
 
1864
 
                                                                /* do we need SIMILAR_DATA_SOURCES_DUPS? */
1865
 
                                                                if (isset($magic_item["SIMILAR_DATA_SOURCES_DUPS"]) && ($xport_item["data_source_name"] == $xport_items[$t]["data_source_name"])) {
1866
 
                                                                        $magic_item["SIMILAR_DATA_SOURCES_DUPS"] .= ($count_similar_ds_dups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,$def_name,$def_name,UN,0,$def_name,IF,IF"; /* convert unknowns to '0' first */
1867
 
                                                                }
1868
 
 
1869
 
                                                                /* do we need COUNT_SIMILAR_DS_DUPS? */
1870
 
                                                                if (isset($magic_item["COUNT_SIMILAR_DS_DUPS"]) && ($xport_item["data_source_name"] == $xport_items[$t]["data_source_name"])) {
1871
 
                                                                        $magic_item["COUNT_SIMILAR_DS_DUPS"] .= ($count_similar_ds_dups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,1,$def_name,UN,0,1,IF,IF"; /* convert unknowns to '0' first */
1872
 
                                                                }
1873
 
 
1874
 
                                                                $count_similar_ds_dups++;
1875
 
 
1876
 
                                                                /* check if this item also qualifies for NODUPS  */
1877
 
                                                                if(!isset($sources_seen{$xport_items[$t]["data_template_rrd_id"]})) {
1878
 
                                                                        if (isset($magic_item["SIMILAR_DATA_SOURCES_NODUPS"])) {
1879
 
                                                                                $magic_item["SIMILAR_DATA_SOURCES_NODUPS"] .= ($count_similar_ds_nodups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,$def_name,$def_name,UN,0,$def_name,IF,IF"; /* convert unknowns to '0' first */
1880
 
                                                                        }
1881
 
                                                                        if (isset($magic_item["COUNT_SIMILAR_DS_NODUPS"]) && ($xport_item["data_source_name"] == $xport_items[$t]["data_source_name"])) {
1882
 
                                                                                $magic_item["COUNT_SIMILAR_DS_NODUPS"] .= ($count_similar_ds_nodups == 0 ? "" : ",") . "TIME," . (time() - $seconds_between_graph_updates) . ",GT,1,$def_name,UN,0,1,IF,IF"; /* convert unknowns to '0' first */
1883
 
                                                                        }
1884
 
                                                                        $count_similar_ds_nodups++;
1885
 
                                                                        $sources_seen{$xport_items[$t]["data_template_rrd_id"]} = TRUE;
1886
 
                                                                }
1887
 
                                                        } # SIMILAR data sources
1888
 
                                                } # matching consolidation function?
1889
 
                                        } # only work on graph items, omit GRPINTs, COMMENTs and stuff
1890
 
                                } #  loop over all graph items
1891
 
 
1892
 
                                /* if there is only one item to total, don't even bother with the summation.
1893
 
                                 * Otherwise cdef=a,b,c,+,+ is fine. */
1894
 
                                if ($count_all_ds_dups > 1 && isset($magic_item["ALL_DATA_SOURCES_DUPS"])) {
1895
 
                                        $magic_item["ALL_DATA_SOURCES_DUPS"] .= str_repeat(",+", ($count_all_ds_dups - 2)) . ",+";
1896
 
                                }
1897
 
                                if ($count_all_ds_nodups > 1 && isset($magic_item["ALL_DATA_SOURCES_NODUPS"])) {
1898
 
                                        $magic_item["ALL_DATA_SOURCES_NODUPS"] .= str_repeat(",+", ($count_all_ds_nodups - 2)) . ",+";
1899
 
                                }
1900
 
                                if ($count_similar_ds_dups > 1 && isset($magic_item["SIMILAR_DATA_SOURCES_DUPS"])) {
1901
 
                                        $magic_item["SIMILAR_DATA_SOURCES_DUPS"] .= str_repeat(",+", ($count_similar_ds_dups - 2)) . ",+";
1902
 
                                }
1903
 
                                if ($count_similar_ds_nodups > 1 && isset($magic_item["SIMILAR_DATA_SOURCES_NODUPS"])) {
1904
 
                                        $magic_item["SIMILAR_DATA_SOURCES_NODUPS"] .= str_repeat(",+", ($count_similar_ds_nodups - 2)) . ",+";
1905
 
                                }
1906
 
                                if ($count_all_ds_dups > 1 && isset($magic_item["COUNT_ALL_DS_DUPS"])) {
1907
 
                                        $magic_item["COUNT_ALL_DS_DUPS"] .= str_repeat(",+", ($count_all_ds_dups - 2)) . ",+";
1908
 
                                }
1909
 
                                if ($count_all_ds_nodups > 1 && isset($magic_item["COUNT_ALL_DS_NODUPS"])) {
1910
 
                                        $magic_item["COUNT_ALL_DS_NODUPS"] .= str_repeat(",+", ($count_all_ds_nodups - 2)) . ",+";
1911
 
                                }
1912
 
                                if ($count_similar_ds_dups > 1 && isset($magic_item["COUNT_SIMILAR_DS_DUPS"])) {
1913
 
                                        $magic_item["COUNT_SIMILAR_DS_DUPS"] .= str_repeat(",+", ($count_similar_ds_dups - 2)) . ",+";
1914
 
                                }
1915
 
                                if ($count_similar_ds_nodups > 1 && isset($magic_item["COUNT_SIMILAR_DS_NODUPS"])) {
1916
 
                                        $magic_item["COUNT_SIMILAR_DS_NODUPS"] .= str_repeat(",+", ($count_similar_ds_nodups - 2)) . ",+";
1917
 
                                }
1918
 
                        }
1919
 
 
1920
 
                        $cdef_string = str_replace("CURRENT_DATA_SOURCE", generate_graph_def_name(strval((isset($cf_ds_cache{$xport_item["data_template_rrd_id"]}[$cf_id]) ? $cf_ds_cache{$xport_item["data_template_rrd_id"]}[$cf_id] : "0"))), $cdef_string);
1921
 
 
1922
 
                        /* ALL|SIMILAR_DATA_SOURCES(NO)?DUPS are to be replaced here */
1923
 
                        if (isset($magic_item["ALL_DATA_SOURCES_DUPS"])) {
1924
 
                                $cdef_string = str_replace("ALL_DATA_SOURCES_DUPS", $magic_item["ALL_DATA_SOURCES_DUPS"], $cdef_string);
1925
 
                        }
1926
 
                        if (isset($magic_item["ALL_DATA_SOURCES_NODUPS"])) {
1927
 
                                $cdef_string = str_replace("ALL_DATA_SOURCES_NODUPS", $magic_item["ALL_DATA_SOURCES_NODUPS"], $cdef_string);
1928
 
                        }
1929
 
                        if (isset($magic_item["SIMILAR_DATA_SOURCES_DUPS"])) {
1930
 
                                $cdef_string = str_replace("SIMILAR_DATA_SOURCES_DUPS", $magic_item["SIMILAR_DATA_SOURCES_DUPS"], $cdef_string);
1931
 
                        }
1932
 
                        if (isset($magic_item["SIMILAR_DATA_SOURCES_NODUPS"])) {
1933
 
                                $cdef_string = str_replace("SIMILAR_DATA_SOURCES_NODUPS", $magic_item["SIMILAR_DATA_SOURCES_NODUPS"], $cdef_string);
1934
 
                        }
1935
 
 
1936
 
                        /* COUNT_ALL|SIMILAR_DATA_SOURCES(NO)?DUPS are to be replaced here */
1937
 
                        if (isset($magic_item["COUNT_ALL_DS_DUPS"])) {
1938
 
                                $cdef_string = str_replace("COUNT_ALL_DS_DUPS", $magic_item["COUNT_ALL_DS_DUPS"], $cdef_string);
1939
 
                        }
1940
 
                        if (isset($magic_item["COUNT_ALL_DS_NODUPS"])) {
1941
 
                                $cdef_string = str_replace("COUNT_ALL_DS_NODUPS", $magic_item["COUNT_ALL_DS_NODUPS"], $cdef_string);
1942
 
                        }
1943
 
                        if (isset($magic_item["COUNT_SIMILAR_DS_DUPS"])) {
1944
 
                                $cdef_string = str_replace("COUNT_SIMILAR_DS_DUPS", $magic_item["COUNT_SIMILAR_DS_DUPS"], $cdef_string);
1945
 
                        }
1946
 
                        if (isset($magic_item["COUNT_SIMILAR_DS_NODUPS"])) {
1947
 
                                $cdef_string = str_replace("COUNT_SIMILAR_DS_NODUPS", $magic_item["COUNT_SIMILAR_DS_NODUPS"], $cdef_string);
1948
 
                        }
1949
 
 
1950
 
                        /* data source item variables */
1951
 
                        $cdef_string = str_replace("CURRENT_DS_MINIMUM_VALUE", (empty($xport_item["rrd_minimum"]) ? "0" : $xport_item["rrd_minimum"]), $cdef_string);
1952
 
                        $cdef_string = str_replace("CURRENT_DS_MAXIMUM_VALUE", (empty($xport_item["rrd_maximum"]) ? "0" : $xport_item["rrd_maximum"]), $cdef_string);
1953
 
                        $cdef_string = str_replace("CURRENT_GRAPH_MINIMUM_VALUE", (empty($graph["lower_limit"]) ? "0" : $graph["lower_limit"]), $cdef_string);
1954
 
                        $cdef_string = str_replace("CURRENT_GRAPH_MAXIMUM_VALUE", (empty($graph["upper_limit"]) ? "0" : $graph["upper_limit"]), $cdef_string);
1955
 
 
1956
 
                        /* replace query variables in cdefs */
1957
 
                        $cdef_string = rrd_substitute_host_query_data($cdef_string, $graph, $xport_item);
1958
 
 
1959
 
                        /* make the initial "virtual" cdef name: 'cdef' + [a,b,c,d...] */
1960
 
                        $cdef_xport_defs .= "CDEF:cdef" . generate_graph_def_name(strval($i)) . "=";
1961
 
                        /* prohibit command injection and provide platform specific quoting */
1962
 
                        $cdef_xport_defs .= cacti_escapeshellarg(sanitize_cdef($cdef_string), true);
1963
 
                        $cdef_xport_defs .= " \\\n";
1964
 
 
1965
 
                        /* the CDEF cache is so we do not create duplicate CDEF's on a graph */
1966
 
                        $cdef_cache{$xport_item["cdef_id"]}{$xport_item["data_template_rrd_id"]}[$cf_id] = "$i";
1967
 
                }
1968
 
 
1969
 
                /* add the cdef string to the end of the def string */
1970
 
                $xport_defs .= $cdef_xport_defs;
1971
 
 
1972
 
                /* note the current item_id for easy access */
1973
 
                $xport_item_id = $xport_item["graph_templates_item_id"];
1974
 
 
1975
 
                /* IF this graph item has a data source... get a DEF name for it, or the cdef if that applies
1976
 
                to this graph item */
1977
 
                if ($xport_item["cdef_id"] == "0") {
1978
 
                        if (isset($cf_ds_cache{$xport_item["data_template_rrd_id"]}[$cf_id])) {
1979
 
                                $data_source_name = generate_graph_def_name(strval($cf_ds_cache{$xport_item["data_template_rrd_id"]}[$cf_id]));
1980
 
                        }else{
1981
 
                                $data_source_name = "";
1982
 
                        }
1983
 
                }else{
1984
 
                        $data_source_name = "cdef" . generate_graph_def_name(strval($cdef_cache{$xport_item["cdef_id"]}{$xport_item["data_template_rrd_id"]}[$cf_id]));
1985
 
                }
1986
 
 
1987
 
                /* +++++++++++++++++++++++ XPORT ITEMS +++++++++++++++++++++++ */
1988
 
 
1989
 
                $need_rrd_nl = TRUE;
1990
 
                if (preg_match("/^(AREA|LINE[123]|STACK)$/", $graph_item_types{$xport_item["graph_type_id"]})) {
1991
 
                        /* give all export items a name */
1992
 
                        if (trim($xport_variables["text_format"][$xport_item_id]) == "") {
1993
 
                                $legend_name = "col" . $j . "-" . $data_source_name;
1994
 
                        }else{
1995
 
                                $legend_name = $xport_variables["text_format"][$xport_item_id];
1996
 
                        }
1997
 
                        $stacked_columns["col" . $j] = ($graph_item_types{$xport_item["graph_type_id"]} == "STACK") ? 1 : 0;
1998
 
                        $j++;
1999
 
 
2000
 
                        $txt_xport_items .= "XPORT:" . cacti_escapeshellarg($data_source_name) . ":" . str_replace(":", "", cacti_escapeshellarg($legend_name)) ;
2001
 
                }else{
2002
 
                        $need_rrd_nl = FALSE;
2003
 
                }
2004
 
 
2005
 
                $i++;
2006
 
 
2007
 
                if (($i < sizeof($xport_items)) && ($need_rrd_nl)) {
2008
 
                        $txt_xport_items .= RRD_NL;
2009
 
                }
2010
 
        }
2011
 
        }
2012
 
 
2013
 
        $output_flag = RRDTOOL_OUTPUT_STDOUT;
2014
 
 
2015
 
        $xport_array = rrdxport2array(rrdtool_execute("xport $xport_opts$xport_defs$txt_xport_items", false, $output_flag));
2016
 
 
2017
 
        /* add host and graph information */
2018
 
        $xport_array["meta"]["stacked_columns"]= $stacked_columns;
2019
 
        $xport_array["meta"]["title_cache"]    = cacti_escapeshellarg($graph["title_cache"]);
2020
 
        $xport_array["meta"]["vertical_label"] = cacti_escapeshellarg($graph["vertical_label"]);
2021
 
        $xport_array["meta"]["local_graph_id"] = $local_graph_id;
2022
 
        $xport_array["meta"]["host_id"]        = $graph["host_id"];
2023
 
 
2024
 
        return $xport_array;
2025
 
}
2026
 
 
2027
 
function rrdtool_set_font($type, $no_legend = "") {
2028
 
        global $config;
2029
 
 
2030
 
        if (read_graph_config_option("custom_fonts") == "on") {
2031
 
                $font = read_graph_config_option($type . "_font");
2032
 
                $size = read_graph_config_option($type . "_size");
2033
 
        }else{
2034
 
                $font = read_config_option($type . "_font");
2035
 
                $size = read_config_option($type . "_size");
2036
 
        }
2037
 
 
2038
 
        if(strlen($font)) {
2039
 
                /* do some simple checks */
2040
 
                if (read_config_option("rrdtool_version") == "rrd-1.0.x" ||
2041
 
                        read_config_option("rrdtool_version") == "rrd-1.2.x") { # rrdtool 1.0 and 1.2 use font files
2042
 
                        if (!is_file($font)) {
2043
 
                                $font = "";
2044
 
                        }
2045
 
                } else {        # rrdtool 1.3+ use fontconfig
2046
 
                        /* verifying all possible pango font params is too complex to be tested here
2047
 
                         * so we only escape the font
2048
 
                         */
2049
 
                        $font = cacti_escapeshellarg($font);
2050
 
                }
2051
 
        }
2052
 
 
2053
 
        if ($type == "title") {
2054
 
                if (!empty($no_legend)) {
2055
 
                        $size = $size * .70;
2056
 
                }elseif (($size <= 4) || ($size == "")) {
2057
 
                        $size = 12;
2058
 
                }
2059
 
        }else if (($size <= 4) || ($size == "")) {
2060
 
                $size = 8;
2061
 
        }
2062
 
 
2063
 
        return "--font " . strtoupper($type) . ":" . $size . ":" . $font . RRD_NL;
2064
 
}
2065
 
 
2066
 
function rrd_substitute_host_query_data($txt_graph_item, $graph, $graph_item) {
2067
 
        /* replace host variables in graph elements */
2068
 
        $host_id = 0;
2069
 
        if (empty($graph["host_id"])) {
2070
 
                /* if graph has no associated host determine host_id from graph item data source */
2071
 
                if (!empty($graph_item["local_data_id"])) {
2072
 
                        $host_id = db_fetch_cell("select host_id from data_local where id='" . $graph_item["local_data_id"] . "'");
2073
 
                }
2074
 
        } else {
2075
 
                $host_id = $graph["host_id"];
2076
 
        }
2077
 
        $txt_graph_item = substitute_host_data($txt_graph_item, '|','|', $host_id);
2078
 
 
2079
 
        /* replace query variables in graph elements */
2080
 
        if (preg_match("/\|query_[a-zA-Z0-9_]+\|/", $txt_graph_item)) {
2081
 
                /* default to the graph data query information from the graph */
2082
 
                if (empty($graph_item["local_data_id"])) {
2083
 
                        $txt_graph_item = substitute_snmp_query_data($txt_graph_item, $graph["host_id"], $graph["snmp_query_id"], $graph["snmp_index"]);
2084
 
                /* use the data query information from the data source if possible */
2085
 
                }else{
2086
 
                        $data_local = db_fetch_row("select snmp_index,snmp_query_id,host_id from data_local where id='" . $graph_item["local_data_id"] . "'");
2087
 
                        $txt_graph_item = substitute_snmp_query_data($txt_graph_item, $data_local["host_id"], $data_local["snmp_query_id"], $data_local["snmp_index"]);
2088
 
                }
2089
 
        }
2090
 
 
2091
 
        /* replace query variables in graph elements */
2092
 
        if (preg_match("/\|input_[a-zA-Z0-9_]+\|/", $txt_graph_item)) {
2093
 
                return substitute_data_input_data($txt_graph_item, $graph, $graph_item["local_data_id"]);
2094
 
        }
2095
 
 
2096
 
        return $txt_graph_item;
2097
 
}
2098
 
 
2099
 
?>