1<?php
2/*
3 +-------------------------------------------------------------------------+
4 | Copyright (C) 2004-2021 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
25include('./include/auth.php');
26
27$color_actions = array(
28	'1' => __('Delete')
29);
30
31/* set default action */
32set_default_action();
33
34switch (get_request_var('action')) {
35	case 'save':
36		form_save();
37
38		break;
39	case 'actions':
40		form_actions();
41
42		break;
43	case 'remove':
44		color_remove();
45
46		header ('Location: color.php');
47		break;
48	case 'edit':
49		top_header();
50
51		color_edit();
52
53		bottom_footer();
54		break;
55	case 'export':
56		color_export();
57
58		break;
59	case 'import':
60		top_header();
61
62		color_import();
63
64		bottom_footer();
65		break;
66	default:
67		top_header();
68
69		color();
70
71		bottom_footer();
72		break;
73}
74
75/* --------------------------
76    The Save Function
77   -------------------------- */
78
79function form_save() {
80	if (isset_request_var('save_component_color')) {
81		/* ================= input validation ================= */
82		get_filter_request_var('id');
83		/* ==================================================== */
84
85		$save['id']        = get_nfilter_request_var('id');
86
87		if (get_nfilter_request_var('read_only') == '') {
88			$save['name']      = get_nfilter_request_var('name');
89			$save['hex']       = form_input_validate(get_nfilter_request_var('hex'),  'hex',  '^[a-fA-F0-9]+$' , false, 3);
90		} else {
91			$save['name']      = get_nfilter_request_var('hidden_name');
92			$save['read_only'] = 'on';
93		}
94
95		if (!is_error_message()) {
96			$color_id = sql_save($save, 'colors');
97
98			if ($color_id) {
99				raise_message(1);
100			} else {
101				raise_message(2);
102			}
103		}
104
105		if (is_error_message()) {
106			header('Location: color.php?header=false&action=edit&id=' . (empty($color_id) ? get_nfilter_request_var('id') : $color_id));
107		} else {
108			header('Location: color.php?header=false');
109		}
110	} elseif (isset_request_var('save_component_import')) {
111		if (isset($_FILES['import_file']['tmp_name'])) {
112			if (($_FILES['import_file']['tmp_name'] != 'none') && ($_FILES['import_file']['tmp_name'] != '')) {
113				$csv_data = file($_FILES['import_file']['tmp_name']);
114				$debug_data = color_import_processor($csv_data);
115
116				if (cacti_sizeof($debug_data)) {
117					$_SESSION['import_debug_info'] = $debug_data;
118				}
119
120				header('Location: color.php?action=import');
121			}
122		} else {
123			raise_message(35);
124
125			header('Location: color.php?action=import');
126		}
127	}
128
129	exit;
130}
131
132/* -----------------------
133    Color Functions
134   ----------------------- */
135
136function form_actions() {
137	global $color_actions;
138
139	/* ================= input validation ================= */
140	get_filter_request_var('drp_action', FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => '/^([a-zA-Z0-9_]+)$/')));
141	/* ==================================================== */
142
143	/* if we are to save this form, instead of display it */
144	if (isset_request_var('selected_items')) {
145		$selected_items = sanitize_unserialize_selected_items(get_nfilter_request_var('selected_items'));
146
147		if ($selected_items != false) {
148			if (get_request_var('drp_action') == '1') { /* delete */
149				db_execute('DELETE FROM colors WHERE ' . array_to_sql_or($selected_items, 'id'));
150			}
151		}
152
153		header('Location: color.php?header=false');
154		exit;
155	}
156
157	/* setup some variables */
158	$color_list = '';
159	$i = 0;
160
161	/* loop through each of the graphs selected on the previous page and get more info about them */
162	foreach ($_POST as $var => $val) {
163		if (preg_match('/^chk_([0-9]+)$/', $var, $matches)) {
164			/* ================= input validation ================= */
165			input_validate_input_number($matches[1]);
166			/* ==================================================== */
167
168			$color = db_fetch_row_prepared('SELECT name, hex FROM colors WHERE id = ?', array($matches[1]));
169
170			$color_list .= '<li>' . ($color['name'] != '' ? html_escape($color['name']): __('Unnamed Color')) . ' (<span style="background-color:#' . $color['hex'] . '">' . $color['hex'] . '</span>)</li>';
171			$color_array[$i] = $matches[1];
172
173			$i++;
174		}
175	}
176
177	top_header();
178
179	form_start('color.php');
180
181	html_start_box($color_actions[get_nfilter_request_var('drp_action')], '60%', '', '3', 'center', '');
182
183	if (isset($color_array) && cacti_sizeof($color_array)) {
184		if (get_nfilter_request_var('drp_action') == '1') { /* delete */
185			print "<tr>
186				<td class='textArea' class='odd'>
187					<p>" . __n('Click \'Continue\' to delete the following Color', 'Click \'Continue\' to delete the following Colors', cacti_sizeof($color_array)) . "</p>
188					<div class='itemlist'><ul>$color_list</ul></div>
189				</td>
190			</tr>\n";
191
192			$save_html = "<input type='button' class='ui-button ui-corner-all ui-widget' value='" . __esc('Cancel') . "' onClick='cactiReturnTo()'>&nbsp;<input type='submit' class='ui-button ui-corner-all ui-widget' value='" . __esc('Continue') . "' title='" . __n('Delete Color', 'Delete Colors', cacti_sizeof($color_array)) . "'>";
193		}
194	} else {
195		raise_message(40);
196		header('Location: color.php?header=false');
197		exit;
198	}
199
200	print "<tr>
201		<td class='saveRow'>
202			<input type='hidden' name='action' value='actions'>
203			<input type='hidden' name='selected_items' value='" . (isset($color_array) ? serialize($color_array) : '') . "'>
204			<input type='hidden' name='drp_action' value='" . get_request_var('drp_action') . "'>
205			$save_html
206		</td>
207	</tr>\n";
208
209	html_end_box();
210
211	form_end();
212
213	bottom_footer();
214}
215
216function color_import_processor(&$colors) {
217	$i      = 0;
218	$hexcol = 0;
219	$return_array = array();
220
221	if (cacti_sizeof($colors)) {
222		foreach($colors as $color_line) {
223			/* parse line */
224			$line_array = explode(',', $color_line);
225
226			/* header row */
227			if ($i == 0) {
228				$save_order = '(';
229				$j = 0;
230				$first_column = true;
231				$required = 0;
232				$update_suffix = '';
233
234				if (cacti_sizeof($line_array)) {
235				foreach($line_array as $line_item) {
236					$line_item = trim(str_replace("'", '', $line_item));
237					$line_item = trim(str_replace('"', '', $line_item));
238
239					switch ($line_item) {
240						case 'hex':
241							$hexcol = $j;
242						case 'name':
243							if (!$first_column) {
244								$save_order .= ', ';
245							}
246
247							$save_order .= $line_item;
248
249							$insert_columns[] = $j;
250							$first_column = false;
251
252							if ($update_suffix != '') {
253								$update_suffix .= ", $line_item=VALUES($line_item)";
254							} else {
255								$update_suffix .= " ON DUPLICATE KEY UPDATE $line_item=VALUES($line_item)";
256							}
257
258							$required++;
259
260							break;
261						default:
262							/* ignore unknown columns */
263					}
264
265					$j++;
266				}
267			}
268
269			$save_order .= ')';
270
271			if ($required >= 2) {
272				array_push($return_array, '<b>HEADER LINE PROCESSED OK</b>:  <br>Columns found where: ' . $save_order . '<br>');
273			} else {
274				array_push($return_array, '<b>HEADER LINE PROCESSING ERROR</b>: Missing required field <br>Columns found where:' . $save_order . '<br>');
275				break;
276			}
277		} else {
278			$save_value = '(';
279			$j = 0;
280			$first_column = true;
281			$sql_where = '';
282
283			if (cacti_sizeof($line_array)) {
284			foreach($line_array as $line_item) {
285				if (in_array($j, $insert_columns)) {
286					$line_item = trim(str_replace("'", '', $line_item));
287					$line_item = trim(str_replace('"', '', $line_item));
288
289					if (!$first_column) {
290						$save_value .= ',';
291					} else {
292						$first_column = false;
293					}
294
295					$save_value .= "'" . $line_item . "'";
296
297					if ($j == $hexcol) {
298						$sql_where = "WHERE hex='$line_item'";
299					}
300				}
301
302				$j++;
303			}
304			}
305
306			$save_value .= ')';
307
308			if ($j > 0) {
309				if (isset_request_var('allow_update')) {
310					$sql_execute = 'INSERT INTO colors ' . $save_order .
311						' VALUES ' . $save_value . $update_suffix;
312
313					if (db_execute($sql_execute)) {
314						array_push($return_array,"INSERT SUCCEEDED: $save_value");
315					} else {
316						array_push($return_array,"INSERT FAILED: $save_value");
317					}
318				} else {
319					/* perform check to see if the row exists */
320					$existing_row = db_fetch_row("SELECT * FROM colors $sql_where");
321
322					if (cacti_sizeof($existing_row)) {
323						array_push($return_array,"<strong>INSERT SKIPPED, EXISTING:</strong> $save_value");
324					} else {
325						$sql_execute = 'INSERT INTO colors ' . $save_order .
326							' VALUES ' . $save_value;
327
328						if (db_execute($sql_execute)) {
329							array_push($return_array,"INSERT SUCCEEDED: $save_value");
330						} else {
331							array_push($return_array,"INSERT FAILED: $save_value");
332						}
333					}
334				}
335			}
336		}
337
338		$i++;
339	}
340	}
341
342	return $return_array;
343}
344
345function color_import() {
346	form_start('color.php?action=import', '', true);
347
348	if ((isset($_SESSION['import_debug_info'])) && (is_array($_SESSION['import_debug_info']))) {
349		html_start_box('Import Results', '100%', '', '3', 'center', '');
350
351		print "<tr class='even'><td>
352			<p class='textArea'>" . __('Cacti has imported the following items:') . "</p>
353		</td></tr>\n";
354
355		if (cacti_sizeof($_SESSION['import_debug_info'])) {
356			foreach($_SESSION['import_debug_info'] as $import_result) {
357				print "<tr class='even'><td>" . $import_result . "</td></tr>\n";
358			}
359		}
360
361		html_end_box();
362
363		kill_session_var('import_debug_info');
364	}
365
366	html_start_box( __('Import Colors'), '100%', '', '3', 'center', '');
367
368	form_alternate_row();?>
369		<td width='50%'><font class='textEditTitle'><?php print __('Import Colors from Local File'); ?></font><br>
370			<?php print __('Please specify the location of the CSV file containing your Color information.');?>
371		</td>
372		<td class='left'>
373			<div>
374				<label class='import_label' for='import_file'><?php print __('Select a File'); ?></label>
375				<input class='import_button' type='file' id='import_file' name='import_file'>
376				<span class='import_text'></span>
377			</div>
378		</td>
379	</tr><?php
380	form_alternate_row();?>
381		<td width='50%'><font class='textEditTitle'><?php print __('Overwrite Existing Data?');?></font><br>
382			<?php print __('Should the import process be allowed to overwrite existing data?  Please note, this does not mean delete old rows, only update duplicate rows.');?>
383		</td>
384		<td class='left'>
385			<input type='checkbox' name='allow_update' id='allow_update'><?php print __('Allow Existing Rows to be Updated?');?>
386		</td><?php
387
388	html_end_box(false);
389
390	html_start_box( __('Required File Format Notes'), '100%', '', '3', 'center', '');
391
392	form_alternate_row();?>
393		<td><strong><?php print __('The file must contain a header row with the following column headings.');?></strong>
394			<br><br>
395				<?php print __('<strong>name</strong> - The Color Name');?><br>
396				<?php print __('<strong>hex</strong> - The Hex Value');?><br>
397			<br>
398		</td>
399	</tr><?php
400
401	form_hidden_box('save_component_import','1','');
402
403	html_end_box();
404
405	form_save_button('color.php', 'import');
406}
407
408function color_edit() {
409	global $fields_color_edit;
410
411	/* ================= input validation ================= */
412	get_filter_request_var('id');
413	/* ==================================================== */
414
415	if (!isempty_request_var('id')) {
416		$color = db_fetch_row_prepared('SELECT * FROM colors WHERE id = ?', array(get_request_var('id')));
417		$header_label = __esc('Colors [edit: %s]', $color['hex']);
418	} else {
419		$header_label = __('Colors [new]');
420	}
421
422	form_start('color.php', 'color');
423
424	html_start_box($header_label, '100%', true, '3', 'center', '');
425
426	draw_edit_form(array(
427		'config' => array('no_form_tag' => true),
428		'fields' => inject_form_variables($fields_color_edit, (isset($color) ? $color : array()))
429		)
430	);
431
432	html_end_box(true, true);
433
434	form_save_button('color.php');
435
436	?>
437	<script type='text/javascript'>
438	$(function() {
439		checkReadonly();
440
441		$('#hex').colorpicker().css({'width':'60px'});
442		$('#read_only').click(function() {
443			checkReadonly();
444		});
445
446		$('#name').keyup(function() {
447			$('#hidden_name').val($(this).val());
448		});
449
450		function checkReadonly() {
451			if ($('#read_only').is(':checked') || $('#read_only').val() == 'on') {
452				$('#name').prop('disabled', true);
453				$('#hex').prop('disabled', true);
454			} else {
455				$('#name').prop('disabled', false);
456				$('#hex').prop('disabled', false);
457			}
458		}
459	});
460	</script>
461	<?php
462}
463
464function process_request_vars() {
465	/* ================= input validation and session storage ================= */
466	$filters = array(
467		'rows' => array(
468			'filter' => FILTER_VALIDATE_INT,
469			'pageset' => true,
470			'default' => '-1'
471			),
472		'page' => array(
473			'filter' => FILTER_VALIDATE_INT,
474			'default' => '1'
475			),
476		'filter' => array(
477			'filter' => FILTER_DEFAULT,
478			'pageset' => true,
479			'default' => ''
480			),
481		'sort_column' => array(
482			'filter' => FILTER_CALLBACK,
483			'default' => 'name',
484			'options' => array('options' => 'sanitize_search_string')
485			),
486		'sort_direction' => array(
487			'filter' => FILTER_CALLBACK,
488			'default' => 'ASC',
489			'options' => array('options' => 'sanitize_search_string')
490			),
491		'has_graphs' => array(
492			'filter' => FILTER_VALIDATE_REGEXP,
493			'options' => array('options' => array('regexp' => '(true|false)')),
494			'pageset' => true,
495			'default' => read_config_option('default_has') == 'on' ? 'true':'false'
496			),
497		'named' => array(
498			'filter' => FILTER_VALIDATE_REGEXP,
499			'options' => array('options' => array('regexp' => '(true|false)')),
500			'pageset' => true,
501			'default' => 'true'
502			)
503	);
504
505	validate_store_request_vars($filters, 'sess_color');
506	/* ================= input validation ================= */
507}
508
509function color() {
510	global $color_actions, $item_rows;
511
512	process_request_vars();
513
514	if (get_request_var('rows') == '-1') {
515		$rows = read_config_option('num_rows_table');
516	} else {
517		$rows = get_request_var('rows');
518	}
519
520	html_start_box(__('Colors'), '100%', '', '3', 'center', 'color.php?action=edit');
521
522	?>
523	<tr class='even'>
524		<td>
525			<form id='form_color' action='color.php'>
526			<table class='filterTable'>
527				<tr>
528					<td>
529						<?php print __('Search');?>
530					</td>
531					<td>
532						<input type='text' class='ui-state-default ui-corner-all' id='filter' name='filter' size='25' value='<?php print html_escape_request_var('filter');?>'>
533					</td>
534					<td>
535						<?php print __('Colors');?>
536					</td>
537					<td>
538						<select id='rows' onChange='applyFilter()'>
539							<option value='-1'<?php print (get_request_var('rows') == '-1' ? ' selected>':'>') . __('Default');?></option>
540							<?php
541							if (cacti_sizeof($item_rows) > 0) {
542								foreach ($item_rows as $key => $value) {
543									print "<option value='" . $key . "'"; if (get_request_var('rows') == $key) { print ' selected'; } print '>' . html_escape($value) . "</option>\n";
544								}
545							}
546							?>
547						</select>
548					</td>
549					<td>
550						<span>
551							<input type='checkbox' id='named' <?php print (get_request_var('named') == 'true' ? 'checked':'');?>>
552							<label for='named'><?php print __('Named Colors');?></label>
553						</span>
554					</td>
555					<td>
556						<span>
557							<input type='checkbox' id='has_graphs' <?php print (get_request_var('has_graphs') == 'true' ? 'checked':'');?>>
558							<label for='has_graphs'><?php print __('Has Graphs');?></label>
559						</span>
560					</td>
561					<td>
562						<span>
563							<input type='button' class='ui-button ui-corner-all ui-widget' id='refresh' value='<?php print __esc('Go');?>' title='<?php print __esc('Set/Refresh Filters');?>'>
564							<input type='button' class='ui-button ui-corner-all ui-widget' id='clear' value='<?php print __esc('Clear');?>' title='<?php print __esc('Clear Filters');?>'>
565						</span>
566					</td>
567					<td>
568						<span>
569							<input type='button' class='ui-button ui-corner-all ui-widget' id='import' value='<?php print __esc('Import');?>' title='<?php print __esc('Import Colors');?>'>
570							<input type='button' class='ui-button ui-corner-all ui-widget' id='export' value='<?php print __esc('Export');?>' title='<?php print __esc('Export Colors');?>'>
571						</span>
572					</td>
573				</tr>
574			</table>
575			</form>
576			<script type='text/javascript'>
577			function applyFilter() {
578				strURL  = 'color.php?header=false';
579				strURL += '&filter='+$('#filter').val();
580				strURL += '&rows='+$('#rows').val();
581				strURL += '&has_graphs='+$('#has_graphs').is(':checked');
582				strURL += '&named='+$('#named').is(':checked');
583				loadPageNoHeader(strURL);
584			}
585
586			function clearFilter() {
587				strURL = 'color.php?clear=1&header=false';
588				loadPageNoHeader(strURL);
589			}
590
591			$(function() {
592				$('#refresh').click(function() {
593					applyFilter();
594				});
595
596				$('#has_graphs').click(function() {
597					applyFilter();
598				});
599
600				$('#named').click(function() {
601					applyFilter();
602				});
603
604				$('#clear').click(function() {
605					clearFilter();
606				});
607
608				$('#form_color').submit(function(event) {
609					event.preventDefault();
610					applyFilter();
611				});
612
613				$('#import').click(function(event) {
614					strURL = 'color.php?action=import&header=false';
615					loadPageNoHeader(strURL);
616				});
617
618				$('#export').click(function(event) {
619					strURL = 'color.php?action=export&header=false';
620					document.location = strURL;
621					Pace.stop();
622				});
623			});
624			</script>
625		</td>
626	</tr>
627	<?php
628
629	html_end_box();
630
631	/* form the 'where' clause for our main sql query */
632	if (get_request_var('filter') != '') {
633		$sql_where = 'WHERE (name LIKE ' . db_qstr('%' . get_request_var('filter') . '%') . '
634			OR hex LIKE ' . db_qstr('%' .  get_request_var('filter') . '%') . ')';
635	} else {
636		$sql_where = '';
637	}
638
639	if (get_request_var('named') == 'true') {
640		$sql_where .= ($sql_where != '' ? ' AND' : 'WHERE') . " read_only='on'";
641	}
642
643	if (get_request_var('has_graphs') == 'true') {
644		$sql_having = 'HAVING graphs>0 OR templates>0';
645	} else {
646		$sql_having = '';
647	}
648
649	$total_rows = db_fetch_cell("SELECT
650		COUNT(color)
651		FROM (
652			SELECT
653			c.id AS color,
654			SUM(CASE WHEN local_graph_id>0 THEN 1 ELSE 0 END) AS graphs,
655			SUM(CASE WHEN local_graph_id=0 THEN 1 ELSE 0 END) AS templates
656			FROM colors AS c
657			LEFT JOIN (
658				SELECT DISTINCT color_id, graph_template_id, local_graph_id
659				FROM graph_templates_item
660				WHERE color_id>0
661			) AS gti
662			ON gti.color_id=c.id
663			$sql_where
664			GROUP BY c.id
665			$sql_having
666		) AS rs");
667
668	$sql_order = get_order_string();
669	$sql_limit = ' LIMIT ' . ($rows*(get_request_var('page')-1)) . ',' . $rows;
670
671	$colors = db_fetch_assoc("SELECT *,
672        SUM(CASE WHEN local_graph_id>0 THEN 1 ELSE 0 END) AS graphs,
673        SUM(CASE WHEN local_graph_id=0 THEN 1 ELSE 0 END) AS templates
674        FROM (
675			SELECT c.*, local_graph_id
676			FROM colors AS c
677			LEFT JOIN (
678				SELECT DISTINCT color_id, graph_template_id, local_graph_id
679				FROM graph_templates_item
680				WHERE color_id>0
681			) AS gti
682			ON c.id=gti.color_id
683		) AS rs
684		$sql_where
685		GROUP BY rs.id
686		$sql_having
687		$sql_order
688		$sql_limit");
689
690    $nav = html_nav_bar('color.php?filter=' . get_request_var('filter'), MAX_DISPLAY_PAGES, get_request_var('page'), $rows, $total_rows, 8, __('Colors'), 'page', 'main');
691
692	form_start('color.php', 'chk');
693
694    print $nav;
695
696	html_start_box('', '100%', '', '3', 'center', '');
697
698	$display_text = array(
699		'hex'       => array('display' => __('Hex'), 'align' => 'left', 'sort' => 'DESC', 'tip' => __('The Hex Value for this Color.')),
700		'name'      => array('display' => __('Color Name'), 'align' => 'left', 'sort' => 'ASC', 'tip' => __('The name of this Color definition.')),
701		'read_only' => array('display' => __('Named Color'), 'align' => 'left', 'sort' => 'ASC', 'tip' => __('Is this color a named color which are read only.')),
702		'nosort1'   => array('display' => __('Color'), 'align' => 'center', 'sort' => 'DESC', 'tip' => __('The Color as shown on the screen.')),
703		'nosort'    => array('display' => __('Deletable'), 'align' => 'right', 'sort' => '', 'tip' => __('Colors in use cannot be Deleted.  In use is defined as being referenced either by a Graph or a Graph Template.')),
704		'graphs'    => array('display' => __('Graphs Using'), 'align' => 'right', 'sort' => 'DESC', 'tip' => __('The number of Graph using this Color.')),
705		'templates' => array('display' => __('Templates Using'), 'align' => 'right', 'sort' => 'DESC', 'tip' => __('The number of Graph Templates using this Color.'))
706	);
707
708	html_header_sort_checkbox($display_text, get_request_var('sort_column'), get_request_var('sort_direction'), false);
709
710	$i = 0;
711	if (cacti_sizeof($colors)) {
712		foreach ($colors as $color) {
713			if ($color['graphs'] == 0 && $color['templates'] == 0) {
714				$disabled = false;
715			} else {
716				$disabled = true;
717			}
718
719			if ($color['name'] == '') {
720				$color['name'] = 'Unnamed #'. $color['hex'];
721			}
722
723			form_alternate_row('line' . $color['id'], false, $disabled);
724			form_selectable_cell("<a class='linkEditMain' href='" . html_escape('color.php?action=edit&id=' . $color['id']) . "'>" . $color['hex'] . '</a>', $color['id']);
725			form_selectable_cell(filter_value($color['name'], get_request_var('filter')), $color['id']);
726			form_selectable_cell($color['read_only'] == 'on' ? __('Yes'):__('No'), $color['id']);
727			form_selectable_cell('', $color['id'], '', 'text-align:right;background-color:#' . $color['hex'] . ';min-width:30%');
728			form_selectable_cell($disabled ? __('No'):__('Yes'), $color['id'], '', 'text-align:right');
729			form_selectable_cell(number_format_i18n($color['graphs'], '-1'), $color['id'], '', 'text-align:right');
730			form_selectable_cell(number_format_i18n($color['templates'], '-1'), $color['id'], '', 'text-align:right');
731			form_checkbox_cell($color['name'], $color['id'], $disabled);
732			form_end_row();
733		}
734	} else {
735		print "<tr class='tableRow'><td colspan='7'><em>" . __('No Colors Found') . "</em></td></tr>\n";
736	}
737
738	html_end_box(false);
739
740	if (cacti_sizeof($colors)) {
741		print $nav;
742	}
743
744	/* draw the dropdown containing a list of available actions for this form */
745	draw_actions_dropdown($color_actions, 1);
746
747	form_end();
748}
749
750function color_export() {
751	process_request_vars();
752
753	/* form the 'where' clause for our main sql query */
754	if (get_request_var('filter') != '') {
755		$sql_where = 'WHERE (name LIKE ' . db_qstr('%' . get_request_var('filter') . '%') . '
756			OR hex LIKE ' . db_qstr('%' .  get_request_var('filter') . '%') . ')';
757	} else {
758		$sql_where = '';
759	}
760
761	if (get_request_var('named') == 'true') {
762		$sql_where .= ($sql_where != '' ? ' AND' : 'WHERE') . " read_only='on'";
763	}
764
765	if (get_request_var('has_graphs') == 'true') {
766		$sql_having = 'HAVING graphs>0 OR templates>0';
767	} else {
768		$sql_having = '';
769	}
770
771	$colors = db_fetch_assoc("SELECT *,
772        SUM(CASE WHEN local_graph_id>0 THEN 1 ELSE 0 END) AS graphs,
773        SUM(CASE WHEN local_graph_id=0 THEN 1 ELSE 0 END) AS templates
774        FROM (
775			SELECT c.*, local_graph_id
776			FROM colors AS c
777			LEFT JOIN (
778				SELECT color_id, graph_template_id, local_graph_id
779				FROM graph_templates_item
780				WHERE color_id>0
781			) AS gti
782			ON c.id=gti.color_id
783		) AS rs
784		$sql_where
785		GROUP BY rs.id
786		$sql_having");
787
788	if (cacti_sizeof($colors)) {
789		header('Content-type: application/csv');
790		header('Content-Disposition: attachment; filename=colors.csv');
791
792		print '"name","hex"' . "\n";
793
794		foreach($colors as $color) {
795			print '"' . $color['name'] . '","' . $color['hex'] . '"' . "\n";
796		}
797	}
798}
799
800