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
25function prime_default_settings() {
26	global $settings;
27
28	if (is_array($settings) && !isset($_SESSION['settings_primed'])) {
29		foreach ($settings as $tab_array) {
30			if (cacti_sizeof($tab_array)) {
31				foreach($tab_array as $setting => $attributes) {
32					if (isset($attributes['default'])) {
33						$current = db_fetch_cell_prepared('SELECT value
34							FROM settings
35							WHERE name = ?',
36							array($setting));
37
38						if ($current == '' || $current == null) {
39							db_execute_prepared('INSERT IGNORE INTO settings
40								(name, value) VALUES (?, ?)',
41								array($setting, $attributes['default']));
42						}
43					} elseif (isset($attributes['items'])) {
44						foreach($attributes['items'] as $isetting => $iattributes) {
45							if (isset($iattributes['default'])) {
46								$current = db_fetch_cell_prepared('SELECT value
47									FROM settings
48									WHERE name = ?',
49									array($isetting));
50
51								if ($current == '' || $current == null) {
52									db_execute_prepared('INSERT IGNORE INTO settings
53										(name, value)
54										VALUES (?, ?)',
55										array($isetting, $iattributes['default']));
56								}
57							}
58						}
59					}
60				}
61			}
62		}
63	}
64
65	$_SESSION['settings_primed'] = true;
66}
67
68function install_create_csrf_secret($file) {
69	if (!file_exists($file)) {
70		if (is_resource_writable($file)) {
71			// Write the file
72			$fh = fopen($file, 'w');
73			fwrite($fh, csrf_get_secret());
74			fclose($fh);
75
76			return true;
77		} else {
78			return false;
79		}
80	}
81
82	return true;
83}
84
85function install_test_local_database_connection() {
86	global $database_type, $database_hostname, $database_username, $database_password, $database_default, $database_type, $database_port, $database_retries, $database_ssl, $database_ssl_key, $database_ssl_cert, $database_ssl_ca;
87
88	if (!isset($database_ssl))      $database_ssl      = false;
89	if (!isset($database_ssl_key))  $database_ssl_key  = false;
90	if (!isset($database_ssl_cert)) $database_ssl_cert = false;
91	if (!isset($database_ssl_ca))   $database_ssl_ca   = false;
92
93	$connection = db_connect_real(
94		$database_hostname,
95		$database_username,
96		$database_password,
97		$database_default,
98		$database_type,
99		$database_port,
100		$database_retries,
101		$database_ssl,
102		$database_ssl_key,
103		$database_ssl_cert,
104		$database_ssl_ca
105	);
106
107	if (is_object($connection)) {
108		db_close($connection);
109		return json_encode(array('status' => 'true'));
110	} else {
111		return json_encode(array('status' => 'false'));
112	}
113}
114
115function install_test_remote_database_connection() {
116	global $rdatabase_type, $rdatabase_hostname, $rdatabase_username, $rdatabase_password, $rdatabase_default, $rdatabase_type, $rdatabase_port, $rdatabase_retries, $rdatabase_ssl, $rdatabase_ssl_key, $rdatabase_ssl_cert, $rdatabase_ssl_ca;
117
118	if (!isset($rdatabase_ssl))      $rdatabase_ssl      = false;
119	if (!isset($rdatabase_ssl_key))  $rdatabase_ssl_key  = false;
120	if (!isset($rdatabase_ssl_cert)) $rdatabase_ssl_cert = false;
121	if (!isset($rdatabase_ssl_ca))   $rdatabase_ssl_ca   = false;
122
123	$connection = db_connect_real(
124		$rdatabase_hostname,
125		$rdatabase_username,
126		$rdatabase_password,
127		$rdatabase_default,
128		$rdatabase_type,
129		$rdatabase_port,
130		$rdatabase_retries,
131		$rdatabase_ssl,
132		$rdatabase_ssl_key,
133		$rdatabase_ssl_cert,
134		$rdatabase_ssl_ca
135	);
136
137	if (is_object($connection)) {
138		db_close($connection);
139		return json_encode(array('status' => 'true'));
140	} else {
141		return json_encode(array('status' => 'false'));
142	}
143}
144
145function install_test_temporary_table() {
146	$table = 'test_temp_' . rand();
147
148	if (!db_execute('CREATE TEMPORARY TABLE ' . $table . ' (`cacti` char(20) NOT NULL DEFAULT "", PRIMARY KEY (`cacti`)) ENGINE=InnoDB')) {
149		return false;
150	} else {
151		if (!db_execute('DROP TABLE ' . $table)) {
152			return false;
153		}
154	}
155
156	return true;
157}
158
159function db_install_execute($sql, $params = array(), $log = true) {
160	$status = (db_execute_prepared($sql, $params, $log) ? DB_STATUS_SUCCESS : DB_STATUS_ERROR);
161
162	if ($log) {
163		db_install_add_cache($status, $sql, $params);
164	}
165
166	return $status;
167}
168
169function db_install_fetch_function($func, $sql, $params = array(), $log = true) {
170	global $database_last_error;
171
172	$database_last_error = false;
173	$data = false;
174	if (!is_callable($func) || !function_exists($func)) {
175		$status = DB_STATUS_ERROR;
176	}
177
178	if ($func == 'db_fetch_cell_prepared') {
179		$data = $func($sql, $params, '', $log);
180	} else {
181		$data = $func($sql, $params, $log);
182	}
183	$status = ($database_last_error ? DB_STATUS_ERROR : DB_STATUS_SUCCESS);
184
185	if ($log || $status == DB_STATUS_ERROR) {
186		db_install_add_cache($status, $sql, $params);
187	}
188
189	return array('status' => $status, 'data' => $data);
190}
191
192function db_install_fetch_assoc($sql, $params = array(), $log = true) {
193	return db_install_fetch_function('db_fetch_assoc_prepared', $sql, $params, $log);
194}
195
196function db_install_fetch_cell($sql, $params = array(), $log = true) {
197	return db_install_fetch_function('db_fetch_cell_prepared', $sql, $params, $log);
198}
199
200function db_install_fetch_row($sql, $params = array(), $log = true) {
201	return db_install_fetch_function('db_fetch_row_prepared', $sql, $params, $log);
202}
203
204function db_install_add_column($table, $column, $ignore = true) {
205	// Example: db_install_add_column ('plugin_config', array('name' => 'test' . rand(1, 200), 'type' => 'varchar (255)', 'NULL' => false));
206	global $database_last_error;
207	$status = DB_STATUS_SKIPPED;
208
209	$sql = 'ALTER TABLE `' . $table . '` ADD `' . $column['name'] . '`';
210
211	if (!db_table_exists($table)) {
212		$database_last_error = 'Table \'' . $table . '\' missing, cannot add column \'' . $column['name'] . '\'';
213		$status = DB_STATUS_WARNING;
214	} elseif (!db_column_exists($table, $column['name'], false)) {
215		$status = db_add_column($table, $column, false) ? DB_STATUS_SUCCESS : DB_STATUS_ERROR;
216	} elseif (!$ignore) {
217		$status = DB_STATUS_SKIPPED;
218	} else {
219		$status = DB_STATUS_SUCCESS;
220	}
221
222	db_install_add_cache($status, $sql);
223	return $status;
224}
225
226function db_install_add_key($table, $type, $key, $columns, $using = '') {
227	if (!is_array($columns)) {
228		$columns = array($columns);
229	}
230
231	$type = strtoupper($type);
232	if ($type == 'KEY' && $key == 'PRIMARY') {
233		$sql = 'ALTER TABLE `' . $table . '` ADD ' . $key . ' ' . $type . '(' . implode(',', $columns) . ')';
234	} else {
235		$sql = 'ALTER TABLE `' . $table . '` ADD ' . $type . ' ' . $key . '(' . implode(',', $columns) . ')';
236	}
237
238	if (!empty($using)) {
239		$sql .= ' USING ' . $using;
240	}
241
242	$status = DB_STATUS_SKIPPED;
243	if (db_index_matches($table, $key, $columns, false) !== 0) {
244		if (db_index_exists($table, $key)) {
245			$status = db_install_drop_key($table, $type, $key);
246		}
247
248		if ($status != DB_STATUS_ERROR) {
249			$status = db_install_execute($sql);
250		}
251	}
252
253	db_install_add_cache($status, $sql);
254	return $status;
255}
256
257function db_install_drop_key($table, $type, $key) {
258	$type = strtoupper(str_ireplace('UNIQUE ', '', $type));
259	if ($type == 'KEY' && $key == 'PRIMARY') {
260		$sql = "ALTER TABLE $table DROP $key $type;";
261	} else {
262		$sql = "ALTER TABLE $table DROP $type $key";
263	}
264
265	$status = DB_STATUS_SKIPPED;
266	if (db_index_exists($table, $key, false)) {
267		$status = db_install_execute($sql);
268	}
269
270	db_install_add_cache($status, $sql);
271	return $status;
272}
273
274function db_install_drop_table($table) {
275	$sql = 'DROP TABLE `' . $table . '`';
276
277	$status = DB_STATUS_SKIPPED;
278	if (db_table_exists($table, false)) {
279		$status = db_install_execute($sql, array(), false) ? DB_STATUS_SUCCESS : DB_STATUS_ERROR;
280	}
281
282	db_install_add_cache($status, $sql);
283	return $status;
284}
285
286function db_install_rename_table($table, $newname) {
287	$sql = 'RENAME TABLE `' . $table . '` TO `' . $newname . '`';
288
289	$status = DB_STATUS_SKIPPED;
290	if (db_table_exists($table, false) && !db_table_exists($newname, false)) {
291		$status = db_install_execute($sql, array(), false) ? DB_STATUS_SUCCESS : DB_STATUS_ERROR;
292	}
293
294	db_install_add_cache($status, $sql);
295	return $status;
296}
297
298function db_install_drop_column($table, $column) {
299	$sql = 'ALTER TABLE `' . $table . '` DROP `' . $column . '`';
300
301	$status = DB_STATUS_SKIPPED;
302	if (db_column_exists($table, $column, false)) {
303		$status = db_remove_column($table, $column) ? DB_STATUS_SUCCESS : DB_STATUS_ERROR;
304	}
305
306	db_install_add_cache($status, $sql);
307	return $status;
308}
309
310function db_install_add_cache($status, $sql, $params = NULL) {
311	global $cacti_upgrade_version, $database_last_error, $database_upgrade_status;
312
313	set_config_option('install_updated', microtime(true));
314
315	$status_char = '?';
316	$status_array = array(
317		DB_STATUS_SKIPPED => '-',
318		DB_STATUS_SUCCESS => '+',
319		DB_STATUS_WARNING => '!',
320		DB_STATUS_ERROR   => 'x',
321	);
322
323	if (array_key_exists($status, $status_array)) {
324		$status_char = $status_array[$status];
325	}
326
327	echo $status_char;
328	if (!isset($database_upgrade_status)) {
329		$database_upgrade_status = array();
330	}
331
332	// add query to upgrade results array by version to the cli global session
333	if (!isset($database_upgrade_status[$cacti_upgrade_version])) {
334		$database_upgrade_status[$cacti_upgrade_version] = array();
335	}
336
337	$query = clean_up_lines($sql);
338	$actual = 0;
339	$expected = substr_count($query, '?');
340
341	if (cacti_sizeof($params)) {
342		foreach ($params as $arg) {
343			$pos = strpos($query, '?');
344			if ($pos !== false) {
345				$actual++;
346				$query = substr_replace($query, "'$arg'", $pos, 1);
347			}
348		}
349	}
350
351	$sql = clean_up_lines($query);
352	if ($actual !== $expected) {
353		$sql .= "\n [[ WARNING: $expected parameters expected, $actual provided ]]";
354	}
355
356	$database_upgrade_status[$cacti_upgrade_version][] = array('status' => $status, 'sql' => $sql, 'error' => $database_last_error);
357
358	$cacheFile = '';
359	if (isset($database_upgrade_status['file'])) {
360		$cacheFile = $database_upgrade_status['file'];
361	}
362
363	if (!empty($cacheFile)) {
364		log_install_high('cache','<[version]> ' . $cacti_upgrade_version . ' <[status]> ' . $status . ' <[sql]> ' . clean_up_lines($sql) . ' <[error]> ' . $database_last_error);
365		file_put_contents($cacheFile, '<[version]> ' . $cacti_upgrade_version . ' <[status]> ' . $status . ' <[sql]> ' . clean_up_lines($sql) . ' <[error]> ' . $database_last_error . PHP_EOL, FILE_APPEND);
366	}
367}
368
369function find_search_paths($os = 'unix') {
370	global $config;
371
372	if ($os == 'win32') {
373		$search_suffix = ';';
374		$search_slash  = '\\';
375		$search_paths  = array(
376			'c:/usr/bin',
377			'c:/cacti',
378			'c:/rrdtool',
379			'c:/spine',
380			'c:/php',
381			'c:/net-snmp/bin',
382			'c:/progra~1/net-snmp/bin',
383			'c:/progra~1/php',
384			'c:/progra~1/spine',
385			'c:/progra~1/spine/bin',
386			'd:/usr/bin',
387			'd:/cacti',
388			'd:/rrdtool',
389			'd:/spine',
390			'd:/php',
391			'd:/net-snmp/bin',
392			'd:/progra~1/net-snmp/bin',
393			'd:/progra~1/php',
394			'd:/progra~1/spine',
395			'd:/progra~1/spine/bin'
396		);
397	} else {
398		$search_suffix = ':';
399		$search_slash  = '';
400		$search_paths  = array(
401			'/bin',
402			'/sbin',
403			'/usr/bin',
404			'/usr/sbin',
405			'/usr/local/bin',
406			'/usr/local/sbin',
407			'/usr/local/spine/bin',
408			'/usr/spine/bin'
409		);
410	}
411
412	$env_path = getenv('PATH');
413	if ($env_path) {
414		$env_paths = explode($search_suffix,$env_path);
415		if (!empty($search_slash)) {
416			foreach ($env_paths as $env_key => $env_folder) {
417				$env_paths[$env_key] = str_replace($search_slash, '/', $env_folder);
418			}
419		}
420		$search_paths = array_merge($env_paths, $search_paths);
421	}
422
423	$env_php = getenv('PHP_BINDIR');
424	if ($env_php) {
425		$search_paths = array_merge(explode($search_suffix,$env_php), $search_paths);
426	}
427
428	if (!empty($config['php_path'])) {
429		$search_paths = array_merge(explode($search_suffix,$config['php_path']), $search_paths);
430	}
431
432	// Filter out any blank lines and then make sure those remaining are unique
433	$search_paths = array_unique(array_filter($search_paths, function($value) { return !is_null($value) && $value !== ''; }));
434	return $search_paths;
435}
436
437function db_install_swap_setting($old_setting, $new_setting) {
438	$exists = db_install_fetch_cell('SELECT COUNT(*) FROM settings WHERE name = ?', array($new_setting));
439	if (empty($exists['data'])) {
440		db_install_execute('UPDATE `settings` SET name = ? WHERE name = ?', array($new_setting, $old_setting));
441	} else {
442		$old_value = db_install_fetch_cell('SELECT value FROM settings WHERE NAME = ?', array($old_setting));
443		db_install_execute('UPDATE `settings` SET value = ? WHERE name = ?', array($old_value['data'], $new_setting));
444		db_install_execute('DELETE FROM `settings` WHERE name = ?', array($old_setting));
445	}
446}
447
448function find_best_path($binary_name) {
449	global $config;
450
451	$search_paths = find_search_paths($config['cacti_server_os']);
452
453	if (cacti_sizeof($search_paths)) {
454		foreach($search_paths as $path) {
455			$desired_path = $path . '/' . $binary_name;
456			if ((@file_exists($desired_path)) && (@is_readable($desired_path))) {
457				return $desired_path;
458			}
459		}
460	}
461	return '';
462}
463
464function install_setup_get_templates() {
465	global $config;
466
467	@ini_set('zlib.output_compression', '0');
468
469	$templates = array(
470		'Cisco_Router.xml.gz',
471		'Generic_SNMP_Device.xml.gz',
472		'Local_Linux_Machine.xml.gz',
473		'NetSNMP_Device.xml.gz',
474		'Windows_Device.xml.gz',
475		'Cacti_Stats.xml.gz'
476	);
477
478	$path = $config['base_path'] . '/install/templates';
479	$info = array();
480	$canUnpack = (extension_loaded('simplexml') && extension_loaded('zlib'));
481
482	foreach ($templates as $xmlfile) {
483		if ($canUnpack) {
484			//Loading Template Information from package
485			$filename = "compress.zlib://$path/$xmlfile";
486
487			$xml    = file_get_contents($filename);;
488			$xmlget = simplexml_load_string($xml);
489			$data   = to_array($xmlget);
490
491			if (is_array($data['info']['author'])) {
492				$data['info']['author'] = '1';
493			}
494
495			if (is_array($data['info']['email'])) {
496				$data['info']['email'] = '2';
497			}
498
499			if (is_array($data['info']['description'])) {
500				$data['info']['description'] = '3';
501			}
502
503			if (is_array($data['info']['homepage'])) {
504				$data['info']['homepage'] = '4';
505			}
506
507			$data['info']['filename'] = $xmlfile;
508			$data['info']['name']     = $xmlfile;
509			$info[] = $data['info'];
510		} else {
511			// Loading Template Information from package
512			$myinfo = @json_decode(shell_exec(cacti_escapeshellcmd(read_config_option('path_php_binary')) . ' -q ' . cacti_escapeshellarg($config['base_path'] . '/cli/import_package.php') . ' --filename=' . cacti_escapeshellarg("/$path/$xmlfile") . ' --info-only'), true);
513			$myinfo['filename'] = $xmlfile;
514			$info[] = $myinfo;
515			$info[] = array('filename' => $xmlfile, 'name' => $xmlfile);
516		}
517	}
518
519	return $info;
520}
521
522function install_setup_get_tables() {
523	/* ensure all tables are utf8 enabled */
524	$db_tables = db_fetch_assoc("SHOW TABLES");
525	if ($db_tables === false) {
526		return false;
527	}
528
529	$t = array();
530	foreach ($db_tables as $tables) {
531		foreach ($tables as $table) {
532			$table_status = db_fetch_row("SHOW TABLE STATUS LIKE '$table'");
533
534			$collation  = '';
535			$engine     = '';
536			$rows       = 0;
537			$row_format = '';
538
539			if ($table_status !== false) {
540				if (isset($table_status['Collation']) && $table_status['Collation'] != 'utf8mb4_unicode_ci') {
541					$collation = $table_status['Collation'];
542				}
543
544				if (isset($table_status['Engine']) && $table_status['Engine'] == 'MyISAM') {
545					$engine = $table_status['Engine'];
546				}
547
548				if (isset($table_status['Rows'])) {
549					$rows = $table_status['Rows'];
550				}
551
552				if (isset($table_status['Row_format']) && $table_status['Row_format'] == 'Compact' && $table_status['Engine'] == 'InnoDB') {
553					$row_format = 'Dynamic';
554				}
555			}
556
557			if ($table_status === false || $collation != '' || $engine != '' || $row_format != '') {
558				$t[$table]['Name']       = $table;
559				$t[$table]['Collation']  = $table_status['Collation'];
560				$t[$table]['Engine']     = $table_status['Engine'];
561				$t[$table]['Rows']       = $rows;
562				$t[$table]['Row_format'] = $table_status['Row_format'];
563			}
564		}
565	}
566
567	return $t;
568}
569
570function to_array ($data) {
571	if (is_object($data)) {
572		$data = get_object_vars($data);
573	}
574	return (is_array($data)) ? array_map(__FUNCTION__,$data) : $data;
575}
576
577/* Here, we define each name, default value, type, and path check for each value
578we want the user to input. The "name" field must exist in the 'settings' table for
579this to work. Cacti also uses different default values depending on what OS it is
580running on. */
581
582function install_tool_path($name, $defaultPaths) {
583	global $config, $settings;
584
585	$os = $config['cacti_server_os'];
586	if (!isset($defaultPaths[$os])) {
587		return false;
588	}
589
590	$tool = array(
591		'friendly_name' => $name,
592		'description' => __('Path for %s', $name),
593		'method' => 'filepath',
594		'max_length' => 255,
595		'default' => ''
596	);
597
598	log_install_debug('file', "$name: Locations ($os), Paths: " . clean_up_lines(var_export($defaultPaths, true)));
599	if (isset($settings) && isset($settings['path']) && isset($settings['path']['path_'.$name])) {
600		$tool = $settings['path']['path_'.$name];
601	} elseif (isset($settings) && isset($settings['mail']) && isset($settings['mail'][$name])) {
602		$tool = $settings['mail'][$name];
603	}
604
605	$which_tool = '';
606	if (config_value_exists('path_' . $name)) {
607		$which_tool = read_config_option('path_'.$name, true);
608		log_install_high('file', "Using config location: $which_tool");
609	}
610
611	if (empty($which_tool) && isset($defaultPaths[$os])) {
612		$defaultPath = $defaultPaths[$os];
613		$basename = basename($defaultPath);
614		log_install_debug('file', "Searching best path with location: $defaultPath");
615		$which_tool = find_best_path($basename);
616		log_install_debug('file', "Searching best path with location return: $which_tool");
617	}
618
619	if (empty($which_tool)) {
620		$which_tool = $defaultPath;
621		log_install_high('file', "Nothing found defaulting to $defaultPath");
622	}
623
624	$tool['default'] = $which_tool;
625	return $tool;
626}
627
628function install_file_paths() {
629	global $config, $settings;
630
631	$input = array();
632
633	/* PHP Binary Path */
634	$input['path_php_binary'] = install_tool_path('php_binary',
635		array(
636			'unix'  => '/bin/php',
637			'win32' => 'c:/php/php.exe'
638		));
639
640	// Workaround to support xampp
641	if ($config['cacti_server_os'] == 'win32') {
642		$paths = array('c:/php/php.exe', 'd:/php/php.exe', 'c:/xampp/php/php.exe', 'd:/xampp/php/php.exe');
643		foreach($paths as $path) {
644			if (file_exists($path)) {
645				$input['path_php_binary']['default'] = $path;
646				break;
647			}
648		}
649	}
650
651	/* RRDtool Binary Path */
652	$input['path_rrdtool'] = install_tool_path('rrdtool',
653		array(
654			'unix'  => '/usr/local/bin/rrdtool',
655			'win32' => 'c:/rrdtool/rrdtool.exe'
656		));
657
658	/* snmpwalk Binary Path */
659	$input['path_snmpwalk'] = install_tool_path('snmpwalk',
660		array(
661			'unix'  => '/usr/local/bin/snmpwalk',
662			'win32' => 'c:/net-snmp/bin/snmpwalk.exe'
663		));
664
665	/* snmpget Binary Path */
666	$input['path_snmpget'] = install_tool_path('snmpget',
667		array(
668			'unix'  => '/usr/local/bin/snmpget',
669			'win32' => 'c:/net-snmp/bin/snmpget.exe'
670		));
671
672	/* snmpbulkwalk Binary Path */
673	$input['path_snmpbulkwalk'] = install_tool_path('snmpbulkwalk',
674		array(
675			'unix'  => '/usr/local/bin/snmpbulkwalk',
676			'win32' => 'c:/net-snmp/bin/snmpbulkwalk.exe'
677		));
678
679	/* snmpgetnext Binary Path */
680	$input['path_snmpgetnext'] = install_tool_path('snmpgetnext',
681		array(
682			'unix'  => '/usr/local/bin/snmpgetnext',
683			'win32' => 'c:/net-snmp/bin/snmpgetnext.exe'
684		));
685
686	/* snmptrap Binary Path */
687	$input['path_snmptrap'] = install_tool_path('snmptrap',
688		array(
689			'unix'  => '/usr/local/bin/snmptrap',
690			'win32' => 'c:/net-snmp/bin/snmptrap.exe'
691		));
692
693	/* sendmail Binary Path */
694	$input['settings_sendmail_path'] = install_tool_path('settings_sendmail_path',
695		array(
696			'unix'  => '/usr/sbin/sendmail',
697		));
698
699	/* spine Binary Path */
700	$input['path_spine'] = install_tool_path('spine',
701		array(
702			'unix'  => '/usr/local/spine/bin/spine',
703			'win32' => 'c:/spine/bin/spine.exe'
704		));
705
706	$input['path_spine_config'] = $settings['path']['path_spine_config'];
707
708	/* log file path */
709	if (!config_value_exists('path_cactilog')) {
710		$input['path_cactilog'] = $settings['path']['path_cactilog'];
711	} else {
712		$input['path_cactilog'] = $settings['path']['path_cactilog'];
713		$input['path_cactilog']['default'] = read_config_option('path_cactilog');
714	}
715
716	if (empty($input['path_cactilog']['default'])) {
717		$input['path_cactilog']['default'] = '/var/log/cacti/log';
718	}
719
720	/* stderr log file path */
721	if (!config_value_exists('path_cactilog')) {
722		$input['path_stderrlog'] = $settings['path']['path_stderrlog'];
723		if (empty($input['path_stderrlog']['default'])) {
724			$input['path_stderrlog']['default'] = $config['base_path'] . '/log/cacti.stderr.log';
725		}
726	} else {
727		$input['path_stderrlog'] = $settings['path']['path_stderrlog'];
728		$input['path_stderrlog']['default'] = read_config_option('path_stderrlog');
729	}
730
731	/* RRDtool Version */
732	if ((@file_exists($input['path_rrdtool']['default'])) && (($config['cacti_server_os'] == 'win32') || (is_executable($input['path_rrdtool']['default']))) ) {
733		$input['rrdtool_version'] = $settings['general']['rrdtool_version'];
734
735		$temp_ver = get_installed_rrdtool_version();
736
737		if (!empty($temp_ver)) {
738			$input['rrdtool_version']['default'] = $temp_ver;
739		}
740	}
741
742	foreach (array_keys($input) as $key) {
743		if ($input[$key] === false) {
744			unset($input[$key]);
745		}
746	}
747
748	return $input;
749}
750
751function remote_update_config_file() {
752	global $config, $rdatabase_type, $rdatabase_hostname, $rdatabase_username,
753		$rdatabase_password, $rdatabase_default, $rdatabase_type, $rdatabase_port, $rdatabase_retries,
754		$rdatabase_ssl, $rdatabase_ssl_key, $rdatabase_ssl_cert, $rdatabase_ssl_ca;
755
756	global $database_type, $database_hostname, $database_username,
757		$database_password, $database_default, $database_type, $database_port, $database_retries,
758		$database_ssl, $database_ssl_key, $database_ssl_cert, $database_ssl_ca;
759
760	$failure     = '';
761	$newfile     = array();
762	$config_file = $config['base_path'] . '/include/config.php';
763
764	$connection = db_connect_real(
765		$rdatabase_hostname,
766		$rdatabase_username,
767		$rdatabase_password,
768		$rdatabase_default,
769		$rdatabase_type,
770		$rdatabase_port,
771		$rdatabase_retries,
772		$rdatabase_ssl,
773		$rdatabase_ssl_key,
774		$rdatabase_ssl_cert,
775		$rdatabase_ssl_ca
776	);
777
778	if (is_object($connection)) {
779		if (function_exists('gethostname')) {
780			$hostname = gethostname();
781		} else {
782			$hostname = php_uname('n');
783		}
784
785		// Check for an existing poller
786		$poller_id = db_fetch_cell_prepared('SELECT id
787			FROM poller
788			WHERE hostname = ?',
789			array($hostname), true, $connection);
790
791		if (empty($poller_id)) {
792			$save['name'] = __('New Poller');
793			$save['hostname']  = $hostname;
794			$save['dbdefault'] = $database_default;
795			$save['dbhost']    = $database_hostname;
796			$save['dbuser']    = $database_username;
797			$save['dbpass']    = $database_password;
798			$save['dbport']    = $database_port;
799			$save['dbretries'] = $database_retries;
800			$save['dbssl']     = $database_ssl ? 'on' : '';
801			$save['dbsslkey']  = $database_ssl_key;
802			$save['dbsslcert'] = $database_ssl_cert;
803			$save['dbsslca']   = $database_ssl_ca;
804
805			$poller_id = sql_save($save, 'poller', 'id', true, $connection);
806		}
807
808		if (!empty($poller_id)) {
809			if (is_writable($config_file)) {
810				$file_array = file($config_file);
811
812				if (cacti_sizeof($file_array)) {
813					foreach($file_array as $line) {
814						if (strpos(trim($line), "\$poller_id") !== false) {
815							$newfile[] = "\$poller_id = $poller_id;" . PHP_EOL;
816						} else {
817							$newfile[] = $line;
818						}
819					}
820
821					$fp = fopen($config_file, 'w');
822					foreach($newfile as $line) {
823						fwrite($fp, $line);
824					}
825					fclose($fp);
826				} else {
827					$failure = 'Failed to read configuration file';
828				}
829			} else {
830				$failure = 'Configuration file is not writable';
831			}
832		} else {
833			$failure = 'Unable to obtain poller id for this server';
834		}
835
836		db_close($connection);
837	} else {
838		$failure = 'Failed to connect database';
839	}
840
841	return $failure;
842}
843
844function import_colors() {
845	global $config;
846
847	if (!file_exists(dirname(__FILE__) . '/colors.csv')) {
848		return false;
849	}
850
851	$contents = file(dirname(__FILE__) . '/colors.csv');
852
853	if (cacti_count($contents)) {
854		foreach($contents as $line) {
855			$line    = trim($line);
856			$parts   = explode(',',$line);
857			$natural = $parts[0];
858			$hex     = $parts[1];
859			$name    = $parts[2];
860
861			$id = db_fetch_cell("SELECT hex FROM colors WHERE hex='$hex'");
862			if (!empty($id)) {
863				db_execute("UPDATE colors SET name='$name', read_only='on' WHERE hex='$hex'");
864			} else {
865				db_execute("INSERT IGNORE INTO colors (name, hex, read_only) VALUES ('$name', '$hex', 'on')");
866			}
867		}
868	}
869
870	return true;
871}
872
873function log_install_debug($section, $string) {
874	log_install_and_file(POLLER_VERBOSITY_DEBUG, $string, $section);
875}
876
877function log_install_low($section, $string) {
878	log_install_and_file(POLLER_VERBOSITY_LOW, $string, $section);
879}
880
881function log_install_medium($section, $string) {
882	log_install_and_file(POLLER_VERBOSITY_MEDIUM, $string, $section);
883}
884
885function log_install_high($section, $string) {
886	log_install_and_file(POLLER_VERBOSITY_HIGH, $string, $section);
887}
888
889function log_install_always($section, $string) {
890	log_install_and_file(POLLER_VERBOSITY_NONE, $string, $section);
891}
892
893function log_install_and_file($level, $string, $section = '') {
894	$level = log_install_level_sanitize($level);
895	$name = 'INSTALL:';
896	if (!empty($section)) {
897		$name = 'INSTALL-' . strtoupper($section) . ':';
898	}
899	cacti_log(log_install_level_name($level) . ': ' . $string, false, $name, $level);
900	log_install_to_file($section, $string, FILE_APPEND, $level);
901}
902
903function log_install_section_level($section) {
904	$log_level = POLLER_VERBOSITY_NONE;
905	$log_install = log_install_level('log_install', POLLER_VERBOSITY_NONE);
906	$log_section = log_install_level('log_install_'.$section, POLLER_VERBOSITY_NONE);
907
908	if ($log_install > $log_level) {
909		$log_level = $log_install;
910	}
911
912	if ($log_section > $log_level) {
913		$log_level = $log_section;
914	}
915	return $log_level;
916}
917
918function log_install_level($option, $default_level) {
919	$level = read_config_option($option, true);
920	return log_install_level_sanitize($level, $default_level, $option);
921}
922
923function log_install_level_sanitize($level, $default_level = POLLER_VERBOSITY_NONE, $option = '') {
924	if (empty($level) || !is_numeric($level)) {
925		$level = $default_level;
926	}
927
928	if ($level < POLLER_VERBOSITY_NONE) {
929		echo 'Level too low - "' . $level . '"' . PHP_EOL;
930		$level = POLLER_VERBOSITY_NONE;
931	} else if ($level > POLLER_VERBOSITY_DEBUG) {
932		echo 'Level too high - "' . $level . '"' . PHP_EOL;
933		$level = POLLER_VERBOSITY_DEBUG;
934	}
935	return $level;
936}
937
938function log_install_level_name($level) {
939	$name = 'Unknown (' . $level . ')';
940	switch ($level) {
941		case POLLER_VERBOSITY_NONE:
942			$name = 'always';
943			break;
944		case POLLER_VERBOSITY_LOW:
945			$name = 'general';
946			break;
947		case POLLER_VERBOSITY_MEDIUM:
948			$name = 'info';
949			break;
950		case POLLER_VERBOSITY_HIGH:
951			$name = 'notice';
952			break;
953		case POLLER_VERBOSITY_DEBUG:
954			$name = 'debug';
955			break;
956	}
957	return $name;
958}
959
960function log_install_to_file($section, $data, $flags = FILE_APPEND, $level = POLLER_VERBOSITY_DEBUG, $force = false) {
961	global $config, $debug;
962	$log_level = log_install_section_level($section);
963
964	$can_log = $level <= $log_level;
965	$day = date('Y-m-d');
966	$time = date('H:i:s');
967	$levelname = log_install_level_name($level);
968	$sectionname = empty($section) ? 'global' : $section;
969
970	$format_cli  = '[%s] [ %15s %-7s ] %s%s';
971	$format_log1 = '[%s %s] [ %-7s ] %s%s';
972	$format_log2 = '[%s %s] [ %15s %-7s ] %s%s';
973
974	if (($force || $can_log) && defined('log_install_echo')) {
975		printf($format_cli, $time, $sectionname, $levelname, $data, PHP_EOL);
976	}
977
978	if ($can_log) {
979		if (empty($section)) {
980			$section = 'general';
981		}
982		$logfile = 'install' . '-' . $section;
983		file_put_contents($config['base_path'] . '/log/' . $logfile . '.log', sprintf($format_log1, $day, $time, $levelname, $data, PHP_EOL), $flags);
984		file_put_contents($config['base_path'] . '/log/install-complete.log', sprintf($format_log2, $day, $time, $sectionname, $levelname, $data, PHP_EOL), $flags);
985	}
986}
987
988/** repair_automation() - Repairs mangled automation graph rules based
989 *  upon the change in the way that Cacti imports the Graph Templates after
990 *  Cacti 1.2.4.
991 **/
992function repair_automation() {
993	log_install_always('', 'Repairing Automation Rules');
994
995	$hash_array = array(
996		array(
997			'name' => 'Traffic 64 bit Server',
998			'automation_id' => 1,
999			'snmp_query_graph_id' => 9,
1000			'snmp_query_id' => 1,
1001			'snmp_query_hash' => 'd75e406fdeca4fcef45b8be3a9a63cbc',
1002			'snmp_query_graph_hash'=> 'ab93b588c29731ab15db601ca0bc9dec',
1003		),
1004		array(
1005			'name' => 'Traffic 64 bit Server Linux',
1006			'automation_id' => 2,
1007			'snmp_query_graph_id' => 9,
1008			'snmp_query_id' => 1,
1009			'snmp_query_hash' => 'd75e406fdeca4fcef45b8be3a9a63cbc',
1010			'snmp_query_graph_hash'=> 'ab93b588c29731ab15db601ca0bc9dec',
1011		),
1012		array(
1013			'name' => 'Disk Space',
1014			'automation_id' => 3,
1015			'snmp_query_graph_id' => 18,
1016			'snmp_query_id' => 8,
1017			'snmp_query_hash' => '9343eab1f4d88b0e61ffc9d020f35414',
1018			'snmp_query_graph_hash'=> '46c4ee688932cf6370459527eceb8ef3',
1019		)
1020	);
1021
1022	foreach($hash_array as $item) {
1023		$exists = db_fetch_row_prepared('SELECT *
1024			FROM automation_graph_rules
1025			WHERE id = ?
1026			AND name = ?',
1027			array(
1028				$item['automation_id'],
1029				$item['name']
1030			)
1031		);
1032
1033		if (cacti_sizeof($exists)) {
1034			$exists_snmp_query_id = db_fetch_cell_prepared('SELECT id
1035				FROM snmp_query
1036				WHERE hash = ?',
1037				array($item['snmp_query_hash']));
1038
1039			$exists_snmp_query_graph_id = db_fetch_cell_prepared('SELECT id
1040				FROM snmp_query_graph
1041				WHERE hash = ?',
1042				array($item['snmp_query_graph_hash']));
1043
1044			db_execute_prepared('UPDATE automation_graph_rules
1045				SET snmp_query_id = ?, graph_type_id = ?
1046				WHERE id = ?',
1047				array(
1048					$exists_snmp_query_id,
1049					$exists_snmp_query_graph_id,
1050					$item['automation_id']
1051				)
1052			);
1053		}
1054	}
1055}
1056
1057function install_full_sync() {
1058	global $config;
1059
1060	include_once($config['base_path'] . '/lib/poller.php');
1061
1062	$pinterval = read_config_option('poller_interval');
1063	$gap_time  = $pinterval * 2;
1064
1065	/* counter arrays */
1066	$failed    = array();
1067	$success   = array();
1068	$skipped   = array();
1069	$timeout   = array();
1070
1071	$pollers = db_fetch_assoc('SELECT id, status, UNIX_TIMESTAMP() - UNIX_TIMESTAMP(last_update) as gap
1072		FROM poller
1073		WHERE id > 1
1074		AND disabled = ""');
1075
1076	if (cacti_sizeof($pollers)) {
1077		foreach($pollers as $poller) {
1078			if (($poller['status'] == POLLER_STATUS_NEW) ||
1079				($poller['status'] == POLLER_STATUS_DOWN) ||
1080				($poller['status'] == POLLER_STATUS_DISABLED)) {
1081				$skipped[] = $poller['id'];
1082			} elseif ($gap < $gap_time) {
1083				if (replicate_out($poller['id'])) {
1084					$success[] = $poller['id'];
1085
1086					db_execute_prepared('UPDATE poller
1087						SET last_sync = NOW()
1088						WHERE id = ?',
1089						array($id));
1090				} else {
1091					$failed[] = $poller['id'];
1092				}
1093			} else {
1094				$timeout[] = $poller['id'];
1095			}
1096		}
1097	}
1098
1099	return array(
1100		'success' => $success,
1101		'failed'  => $failed,
1102		'skipped' => $skipped,
1103		'timeout' => $timeout,
1104		'total'   => cacti_sizeof($pollers)
1105	);
1106}
1107
1108