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
25/* api_data_source_crc_update - update hash stored in settings table to inform
26   remote pollers to update their caches
27   @arg $poller_id - the id of the poller impacted by hash update
28   @arg $variable  - the hash variable prefix for the replication setting. */
29function api_data_source_cache_crc_update($poller_id, $variable = 'poller_replicate_data_source_cache_crc') {
30	$hash = hash('ripemd160', date('Y-m-d H:i:s') . rand() . $poller_id);
31
32	db_execute_prepared("REPLACE INTO settings
33		SET value = ?, name='$variable" . '_' . "$poller_id'",
34		array($hash));
35}
36
37/* api_data_source_deletable - tells you if a data source can be removed
38   @arg $local_data_id - the id of the poller impacted by hash update */
39function api_data_source_deletable($local_data_id) {
40	$graphs = db_fetch_cell_prepared('SELECT COUNT(DISTINCT gti.local_graph_id)
41		FROM data_local AS dl
42		INNER JOIN data_template_rrd AS dtr
43		ON dl.id=dtr.local_data_id
44		LEFT JOIN graph_templates_item AS gti
45		ON gti.task_item_id=dtr.id
46		WHERE dl.id = ?
47		AND gti.id IS NOT NULL',
48		array($local_data_id));
49
50	if ($graphs > 0) {
51		return false;
52	} else {
53		return true;
54	}
55}
56
57function api_data_source_remove($local_data_id) {
58	if (empty($local_data_id)) {
59		return;
60	}
61
62	api_plugin_hook_function('data_source_remove', array($local_data_id));
63
64	$autoclean = read_config_option('rrd_autoclean');
65	$acmethod  = read_config_option('rrd_autoclean_method');
66
67	if ($autoclean == 'on') {
68		$dsinfo = db_fetch_row_prepared('SELECT local_data_id, data_source_path
69			FROM data_template_data
70			WHERE local_data_id = ?', array($local_data_id));
71
72		if (cacti_sizeof($dsinfo)) {
73			$filename = str_replace('<path_cacti>/', '', $dsinfo['data_source_path']);
74			db_execute_prepared('INSERT INTO data_source_purge_action
75				(local_data_id, name, action) VALUES (?, ?, ?)
76				ON DUPLICATE KEY UPDATE action=VALUES(action)',
77				array($local_data_id, $filename, $acmethod));
78		}
79	}
80
81	$data_template_data_id = db_fetch_cell_prepared('SELECT id
82		FROM data_template_data
83		WHERE local_data_id = ?', array($local_data_id));
84
85	$poller_id = db_fetch_cell_prepared('SELECT poller_id
86		FROM host AS h
87		INNER JOIN data_local AS dl
88		ON h.id=dl.host_id
89		WHERE dl.id = ?',
90		array($local_data_id));
91
92	if (!empty($data_template_data_id)) {
93		db_execute_prepared('DELETE
94			FROM data_input_data
95			WHERE data_template_data_id = ?',
96				array($data_template_data_id));
97
98		if (($rcnn_id = poller_push_to_remote_db_connect($poller_id, true)) !== false) {
99			db_execute_prepared('DELETE
100				FROM data_input_data
101				WHERE data_template_data_id = ?',
102				array($data_template_data_id), true, $rcnn_id);
103		}
104	}
105
106	/* base data */
107	db_execute_prepared('DELETE FROM data_template_data
108		WHERE local_data_id = ?', array($local_data_id));
109
110	db_execute_prepared('DELETE FROM data_template_rrd
111		WHERE local_data_id = ?', array($local_data_id));
112
113	db_execute_prepared('DELETE FROM poller_item
114		WHERE local_data_id = ?', array($local_data_id));
115
116	db_execute_prepared('DELETE FROM data_local
117		WHERE id = ?', array($local_data_id));
118
119	db_execute_prepared('DELETE FROM data_debug
120		WHERE datasource = ?', array($local_data_id));
121
122	/* dsstats */
123	db_execute_prepared('DELETE FROM data_source_stats_daily
124		WHERE local_data_id = ?', array($local_data_id));
125
126	db_execute_prepared('DELETE FROM data_source_stats_hourly
127		WHERE local_data_id = ?', array($local_data_id));
128
129	db_execute_prepared('DELETE FROM data_source_stats_hourly_cache
130		WHERE local_data_id = ?', array($local_data_id));
131
132	db_execute_prepared('DELETE FROM data_source_stats_hourly_last
133		WHERE local_data_id = ?', array($local_data_id));
134
135	db_execute_prepared('DELETE FROM data_source_stats_monthly
136		WHERE local_data_id = ?', array($local_data_id));
137
138	db_execute_prepared('DELETE FROM data_source_stats_weekly
139		WHERE local_data_id = ?', array($local_data_id));
140
141	db_execute_prepared('DELETE FROM data_source_stats_yearly
142		WHERE local_data_id = ?', array($local_data_id));
143
144	/* boost */
145	db_execute_prepared('DELETE FROM poller_output
146		WHERE local_data_id = ?', array($local_data_id));
147
148	db_execute_prepared('DELETE FROM poller_output_boost
149		WHERE local_data_id = ?', array($local_data_id));
150
151	if (($rcnn_id = poller_push_to_remote_db_connect($poller_id, true)) !== false) {
152		/* base data */
153		db_execute_prepared('DELETE FROM data_template_data
154			WHERE local_data_id = ?', array($local_data_id), true, $rcnn_id);
155
156		db_execute_prepared('DELETE FROM data_template_rrd
157			WHERE local_data_id = ?', array($local_data_id), true, $rcnn_id);
158
159		db_execute_prepared('DELETE FROM poller_item
160			WHERE local_data_id = ?', array($local_data_id), true, $rcnn_id);
161
162		db_execute_prepared('DELETE FROM data_local
163			WHERE id = ?', array($local_data_id), true, $rcnn_id);
164
165		/* boost */
166		db_execute_prepared('DELETE FROM poller_output
167			WHERE local_data_id = ?', array($local_data_id), true, $rcnn_id);
168
169		db_execute_prepared('DELETE FROM poller_output_boost
170			WHERE local_data_id = ?', array($local_data_id), true, $rcnn_id);
171	}
172
173	/* update the database to document the cache change */
174	api_data_source_cache_crc_update($poller_id);
175}
176
177function api_data_source_remove_multi($local_data_ids) {
178	// Shortcut out if no data
179	if (!cacti_sizeof($local_data_ids)) {
180		return;
181	}
182
183	api_plugin_hook_function('data_source_remove', $local_data_ids);
184
185	$autoclean = read_config_option('rrd_autoclean');
186	$acmethod  = read_config_option('rrd_autoclean_method');
187
188	$local_data_ids_chunks = array_chunk($local_data_ids, 1000);
189	foreach ($local_data_ids_chunks as $ids_to_delete) {
190		$poller_ids = get_remote_poller_ids_from_data_sources($ids_to_delete);
191
192		if (is_array($ids_to_delete)) {
193			cacti_log("Found as an array");
194			$ids_to_delete = implode(', ', $ids_to_delete);
195		}
196
197		$data_template_data_ids = db_fetch_assoc('SELECT id
198			FROM data_template_data
199			WHERE local_data_id IN (' . $ids_to_delete . ')');
200
201		if (cacti_sizeof($data_template_data_ids)) {
202			$dtd_ids_to_delete = array();
203
204			foreach ($data_template_data_ids as $data_template_data_id) {
205				$dtd_ids_to_delete[] = $data_template_data_id['id'];
206
207				if (cacti_sizeof($dtd_ids_to_delete) >= 1000) {
208					db_execute('DELETE FROM data_input_data
209						WHERE data_template_data_id IN (' . implode(',', $dtd_ids_to_delete) . ')');
210
211					if (cacti_sizeof($poller_ids)) {
212						foreach ($poller_ids as $poller_id) {
213							if (($rcnn_id = poller_push_to_remote_db_connect($poller_id, true)) !== false) {
214								db_execute('DELETE FROM data_input_data
215									WHERE data_template_data_id IN (' . implode(',', $dtd_ids_to_delete) . ')', true, $rcnn_id);
216							}
217						}
218					}
219
220					$dtd_ids_to_delete = array();
221				}
222			}
223
224			if (cacti_sizeof($dtd_ids_to_delete)) {
225				db_execute('DELETE FROM data_input_data
226					WHERE data_template_data_id IN (' . implode(',', $dtd_ids_to_delete) . ')');
227
228				if (cacti_sizeof($poller_ids)) {
229					foreach ($poller_ids as $poller_id) {
230						if (($rcnn_id = poller_push_to_remote_db_connect($poller_id, true)) !== false) {
231							db_execute('DELETE FROM data_input_data
232								WHERE data_template_data_id IN (' . implode(',', $dtd_ids_to_delete) . ')', true, $rcnn_id);
233						}
234					}
235				}
236			}
237
238		}
239
240		/* core data */
241		db_execute('DELETE FROM data_template_data
242			WHERE local_data_id IN (' . $ids_to_delete . ')');
243
244		db_execute('DELETE FROM data_template_rrd
245			WHERE local_data_id IN (' . $ids_to_delete . ')');
246
247		db_execute('DELETE FROM poller_item
248			WHERE local_data_id IN (' . $ids_to_delete . ')');
249
250		db_execute('DELETE FROM data_local
251			WHERE id IN (' . $ids_to_delete . ')');
252
253		/* dsstats */
254		db_execute('DELETE FROM data_source_stats_daily
255			WHERE local_data_id IN(' . $ids_to_delete . ')');
256
257		db_execute('DELETE FROM data_source_stats_hourly
258			WHERE local_data_id IN(' . $ids_to_delete . ')');
259
260		db_execute('DELETE FROM data_source_stats_hourly_cache
261			WHERE local_data_id IN(' . $ids_to_delete . ')');
262
263		db_execute('DELETE FROM data_source_stats_hourly_last
264			WHERE local_data_id IN(' . $ids_to_delete . ')');
265
266		db_execute('DELETE FROM data_source_stats_monthly
267			WHERE local_data_id IN(' . $ids_to_delete . ')');
268
269		db_execute('DELETE FROM data_source_stats_weekly
270			WHERE local_data_id IN(' . $ids_to_delete . ')');
271
272		db_execute('DELETE FROM data_source_stats_yearly
273			WHERE local_data_id IN(' . $ids_to_delete . ')');
274
275		/* boost */
276		db_execute('DELETE FROM poller_output
277			WHERE local_data_id IN (' . $ids_to_delete . ')');
278
279		db_execute('DELETE FROM poller_output_boost
280			WHERE local_data_id IN (' . $ids_to_delete . ')');
281
282		if ($autoclean == 'on') {
283			db_execute("INSERT INTO data_source_purge_action (local_data_id, name, action)
284				SELECT local_data_id, REPLACE(data_source_path, '<path_cacti>/', ''), '" . $acmethod . "'
285				FROM data_template_data
286				WHERE local_data_id IN (" . $ids_to_delete . ')
287				ON DUPLICATE KEY UPDATE action=VALUES(action)');
288		}
289
290		if (cacti_sizeof($poller_ids)) {
291			foreach ($poller_ids as $poller_id) {
292				if (($rcnn_id = poller_push_to_remote_db_connect($poller_id, true)) !== false) {
293					/* core data */
294					db_execute('DELETE FROM data_template_data
295						WHERE local_data_id IN (' . $ids_to_delete . ')', true, $rcnn_id);
296
297					db_execute('DELETE FROM data_template_rrd
298						WHERE local_data_id IN (' . $ids_to_delete . ')', true, $rcnn_id);
299
300					db_execute('DELETE FROM poller_item
301						WHERE local_data_id IN (' . $ids_to_delete . ')', true, $rcnn_id);
302
303					db_execute('DELETE FROM data_local
304						WHERE id IN (' . $ids_to_delete . ')', true, $rcnn_id);
305
306					/* boost */
307					db_execute('DELETE FROM poller_output
308						WHERE local_data_id IN (' . $ids_to_delete . ')', true, $rcnn_id);
309
310					db_execute('DELETE FROM poller_output_boost
311						WHERE local_data_id IN (' . $ids_to_delete . ')', true, $rcnn_id);
312				}
313
314				api_data_source_cache_crc_update($poller_id);
315			}
316		}
317	}
318}
319
320function api_data_source_enable($local_data_id) {
321	db_execute_prepared("UPDATE data_template_data
322		SET active = 'on'
323		WHERE local_data_id = ?",
324		array($local_data_id));
325
326	$device_id = db_fetch_cell_prepared('SELECT host_id
327		FROM data_local
328		WHERE id = ?',
329		array($local_data_id));
330
331	if (($rcnn_id = poller_push_to_remote_db_connect($device_id)) !== false) {
332		db_execute_prepared("UPDATE data_template_data
333			SET active = 'on'
334			WHERE local_data_id = ?",
335			array($local_data_id), true, $rcnn_id);
336	}
337
338	update_poller_cache($local_data_id, true);
339 }
340
341function api_data_source_disable($local_data_id) {
342	db_execute_prepared('DELETE FROM poller_item
343		WHERE local_data_id = ?',
344		array($local_data_id));
345
346	db_execute_prepared("UPDATE data_template_data
347		SET active=''
348		WHERE local_data_id = ?",
349		array($local_data_id));
350
351	$device_id = db_fetch_cell_prepared('SELECT host_id
352		FROM data_local
353		WHERE id = ?',
354		array($local_data_id));
355
356	if (($rcnn_id = poller_push_to_remote_db_connect($device_id)) !== false) {
357		db_execute_prepared('DELETE FROM poller_item
358			WHERE local_data_id = ?',
359			array($local_data_id), true, $rcnn_id);
360
361		db_execute_prepared("UPDATE data_template_data
362			SET active=''
363			WHERE local_data_id = ?",
364			array($local_data_id), true, $rcnn_id);
365	}
366}
367
368function api_data_source_disable_multi($local_data_ids) {
369	/* initialize variables */
370	$ids_to_disable = '';
371	$i = 0;
372
373	/* build the array */
374	if (cacti_sizeof($local_data_ids)) {
375		foreach ($local_data_ids as $local_data_id) {
376			if ($i == 0) {
377				$ids_to_disable .= $local_data_id;
378			} else {
379				$ids_to_disable .= ', ' . $local_data_id;
380			}
381
382			$i++;
383
384			if (!($i % 1000)) {
385				$poller_ids = array_rekey(db_fetch_assoc('SELECT poller_id
386					FROM poller_item
387					WHERE local_data_id IN(' . $ids_to_disable . ')'), 'poller_id', 'poller_id');
388
389				db_execute("DELETE FROM poller_item WHERE local_data_id IN ($ids_to_disable)");
390				db_execute("UPDATE data_template_data SET active='' WHERE local_data_id IN ($ids_to_disable)");
391
392				if (cacti_sizeof($poller_ids)) {
393					foreach ($poller_ids as $poller_id) {
394						if (($rcnn_id = poller_push_to_remote_db_connect($poller_id, true)) !== false) {
395							db_execute("DELETE FROM poller_item WHERE local_data_id IN ($ids_to_disable)", true, $rcnn_id);
396							db_execute("UPDATE data_template_data SET active='' WHERE local_data_id IN ($ids_to_disable)", true, $rcnn_id);
397						}
398					}
399				}
400
401				$i = 0;
402				$ids_to_disable = '';
403			}
404		}
405
406		if ($i > 0) {
407			$poller_ids = array_rekey(
408				db_fetch_assoc('SELECT poller_id
409					FROM poller_item
410					WHERE local_data_id IN(' . $ids_to_disable .')'),
411				'poller_id', 'poller_id'
412			);
413
414			db_execute("DELETE FROM poller_item WHERE local_data_id IN ($ids_to_disable)");
415			db_execute("UPDATE data_template_data SET active='' WHERE local_data_id IN ($ids_to_disable)");
416
417			if (cacti_sizeof($poller_ids)) {
418				foreach ($poller_ids as $poller_id) {
419					if (($rcnn_id = poller_push_to_remote_db_connect($poller_id, true)) !== false) {
420						db_execute("DELETE FROM poller_item WHERE local_data_id IN ($ids_to_disable)", true, $rcnn_id);
421						db_execute("UPDATE data_template_data SET active='' WHERE local_data_id IN ($ids_to_disable)", true, $rcnn_id);
422					}
423				}
424			}
425		}
426	}
427
428	if (cacti_sizeof($poller_ids)) {
429		foreach ($poller_ids as $poller_id) {
430			api_data_source_cache_crc_update($poller_id);
431		}
432	}
433}
434
435function api_data_source_get_interface_speed($data_local) {
436	$ifHighSpeed = db_fetch_cell_prepared('SELECT field_value
437		FROM host_snmp_cache
438		WHERE host_id = ?
439		AND snmp_query_id = ?
440		AND snmp_index = ?
441		AND field_name="ifHighSpeed"',
442		array($data_local['host_id'], $data_local['snmp_query_id'], $data_local['snmp_index'])
443	);
444
445	$ifSpeed = db_fetch_cell_prepared('SELECT field_value
446		FROM host_snmp_cache
447		WHERE host_id = ?
448		AND snmp_query_id = ?
449		AND snmp_index = ?
450		AND field_name="ifSpeed"',
451		array($data_local['host_id'], $data_local['snmp_query_id'], $data_local['snmp_index'])
452	);
453
454	if (!empty($ifHighSpeed)) {
455		$speed = $ifHighSpeed * 1000000;
456
457		if (read_config_option('data_source_trace') == 'on') {
458			cacti_log('Interface Speed Detected by ifHighSpeed: "' . $speed . '"', false, 'DSTRACE');
459		}
460	} elseif (!empty($ifSpeed)) {
461		$speed = $ifSpeed;
462
463		if (read_config_option('data_source_trace') == 'on') {
464			cacti_log('Interface Speed Detected by ifSpeed: "' . $speed . '"', false, 'DSTRACE');
465		}
466	} else {
467		$speed = read_config_option('default_interface_speed');
468
469		if (empty($speed)) {
470			$speed = '10000000000000';
471
472			if (read_config_option('data_source_trace') == 'on') {
473				cacti_log('Interface Speed Detected by Default: "' . $speed . '"', false, 'DSTRACE');
474			}
475		} else {
476			$speed = $speed * 1000000;
477
478			if (read_config_option('data_source_trace') == 'on') {
479				cacti_log('Interface Speed Detected by Settings: "' . $speed . '"', false, 'DSTRACE');
480			}
481		}
482	}
483
484	return $speed;
485}
486
487function api_data_source_change_host($data_sources, $device_id) {
488	if (cacti_sizeof($data_sources)) {
489		foreach($data_sources as $data_source) {
490			db_execute_prepared('UPDATE data_local
491				SET host_id = ?
492				WHERE id = ?',
493				array($device_id, $data_source));
494
495			if (($rcnn_id = poller_push_to_remote_db_connect($device_id)) !== false) {
496				db_execute_prepared('UPDATE data_local
497					SET host_id = ?
498					WHERE id = ?',
499					array($device_id, $data_source), true, $rcnn_id);
500			}
501
502			push_out_host($device_id, $data_source);
503
504			update_data_source_title_cache($data_source);
505		}
506	}
507}
508
509function api_reapply_suggested_data_source_data($local_data_id) {
510	$data_template_data_id = db_fetch_cell_prepared('SELECT id
511		FROM data_template_data
512		WHERE local_data_id = ?',
513		array($local_data_id));
514
515	if (empty($data_template_data_id)) {
516		return;
517	}
518
519	/* require query type data sources only (snmp_query_id > 0) */
520	$data_local = db_fetch_row_prepared('SELECT id, host_id,
521		data_template_id, snmp_query_id, snmp_index
522		FROM data_local
523		WHERE snmp_query_id > 0
524		AND id = ?',
525		array($local_data_id));
526
527	/* if this is not a data query graph, simply return */
528	if (!isset($data_local['host_id'])) {
529		return;
530	}
531
532	$snmp_query_graph_id = db_fetch_cell_prepared("SELECT did.value
533		FROM data_input_data AS did
534		INNER JOIN data_input_fields AS dif
535		ON did.data_input_field_id = dif.id
536		INNER JOIN data_template_data AS dtd
537		ON dtd.id = did.data_template_data_id
538		WHERE dif.type_code = 'output_type'
539		AND dtd.local_data_id = ?",
540		array($data_local['id']));
541
542	/* no snmp query graph id found */
543	if ($snmp_query_graph_id == 0) {
544		return;
545	}
546
547	$svs = db_fetch_assoc_prepared("SELECT
548		text, field_name
549		FROM snmp_query_graph_rrd_sv
550		WHERE snmp_query_graph_id = ?
551		AND data_template_id = ?
552		ORDER BY sequence",
553		array($snmp_query_graph_id, $data_local['data_template_id']));
554
555	$matches = array();
556
557	if (cacti_sizeof($svs)) {
558		foreach ($svs as $sv) {
559			$sv['text'] = trim($sv['text']);
560
561			if (($sv['text'] == '|query_ifSpeed|' || $sv['text'] == '|query_ifHighSpeed|') && $sv['field_name'] == 'rrd_maximum') {
562				$subs_string = api_data_source_get_interface_speed($data_local);
563				$sv['text']  = $subs_string;
564			} else {
565				$subs_string = substitute_snmp_query_data($sv['text'],$data_local['host_id'],
566					$data_local['snmp_query_id'], $data_local['snmp_index'],
567					read_config_option('max_data_query_field_length'));
568			}
569
570			/* if there are no '|query' characters, all of the substitutions were successful */
571			if (strpos($subs_string, '|query') === false) {
572				if (in_array($sv['field_name'], $matches)) {
573					continue;
574				}
575
576				if (db_column_exists('data_template_data', $sv['field_name'])) {
577					$matches[] = $sv['field_name'];
578					db_execute_prepared('UPDATE data_template_data
579						SET ' . $sv['field_name'] . ' = ?
580						WHERE local_data_id = ?',
581						array($sv['text'], $local_data_id));
582				} elseif (db_column_exists('data_template_rrd', $sv['field_name'])) {
583					$matches[] = $sv['field_name'];
584					db_execute_prepared('UPDATE data_template_rrd
585						SET ' . $sv['field_name'] . ' = ?
586						WHERE local_data_id = ?',
587						array($sv['text'], $local_data_id));
588				} else {
589					cacti_log('ERROR: Suggested value column error.  Column ' . $sv['field_name'] . ' for Data Template ID ' . $data_local['data_template_id'] . ' is not a compatible field name for tables data_template_data and data_template_rrd.  Please correct this suggested value mapping', false);
590				}
591			}
592		}
593	}
594}
595
596function api_duplicate_data_source($_local_data_id, $_data_template_id, $data_source_title) {
597	global $struct_data_source, $struct_data_source_item;
598
599	if (!empty($_local_data_id)) {
600		$data_local         = db_fetch_row_prepared('SELECT *
601			FROM data_local
602			WHERE id = ?',
603			array($_local_data_id));
604
605		$data_template_data = db_fetch_row_prepared('SELECT *
606			FROM data_template_data
607			WHERE local_data_id = ?',
608			array($_local_data_id));
609
610		$data_template_rrds = db_fetch_assoc_prepared('SELECT *
611			FROM data_template_rrd
612			WHERE local_data_id = ?',
613			array($_local_data_id));
614
615		$data_input_datas   = db_fetch_assoc_prepared('SELECT *
616			FROM data_input_data
617			WHERE data_template_data_id = ?',
618			array($data_template_data['id']));
619
620		/* create new entry: data_local */
621		$save['id']               = 0;
622		$save['data_template_id'] = $data_local['data_template_id'];
623		$save['host_id']          = $data_local['host_id'];
624		$save['snmp_query_id']    = $data_local['snmp_query_id'];
625		$save['snmp_index']       = $data_local['snmp_index'];
626
627		$local_data_id = sql_save($save, 'data_local');
628
629		$data_template_data['name'] = str_replace('<ds_title>', $data_template_data['name'], $data_source_title);
630	} elseif (!empty($_data_template_id)) {
631		$data_template      = db_fetch_row_prepared('SELECT *
632			FROM data_template
633			WHERE id = ?',
634			array($_data_template_id));
635
636		$data_template_data = db_fetch_row_prepared('SELECT *
637			FROM data_template_data
638			WHERE data_template_id = ?
639			AND local_data_id=0',
640			array($_data_template_id));
641
642		$data_template_rrds = db_fetch_assoc_prepared('SELECT *
643			FROM data_template_rrd
644			WHERE data_template_id = ?
645			AND local_data_id=0',
646			array($_data_template_id));
647
648		$data_input_datas   = db_fetch_assoc_prepared('SELECT *
649			FROM data_input_data
650			WHERE data_template_data_id = ?',
651			array($data_template_data['id']));
652
653		/* create new entry: data_template */
654		$save['id']   = 0;
655		$save['hash'] = get_hash_data_template(0);
656		$save['name'] = str_replace('<template_title>', $data_template['name'], $data_source_title);
657
658		$data_template_id = sql_save($save, 'data_template');
659	}
660
661	unset($save);
662	unset($struct_data_source['data_source_path']);
663
664	/* create new entry: data_template_data */
665	$save['id']                          = 0;
666	$save['local_data_id']               = (isset($local_data_id) ? $local_data_id : 0);
667	$save['local_data_template_data_id'] = (isset($data_template_data['local_data_template_data_id']) ? $data_template_data['local_data_template_data_id'] : 0);
668	$save['data_template_id']            = (!empty($_local_data_id) ? $data_template_data['data_template_id'] : $data_template_id);
669	$save['name_cache']                  = $data_template_data['name_cache'];
670
671	foreach ($struct_data_source as $field => $array) {
672		$save[$field] = $data_template_data[$field];
673
674		if ($array['flags'] != 'ALWAYSTEMPLATE') {
675			$save['t_' . $field] = $data_template_data['t_' . $field];
676		}
677	}
678
679	$data_template_data_id = sql_save($save, 'data_template_data');
680
681	/* create new entry(s): data_template_rrd */
682	if (cacti_sizeof($data_template_rrds)) {
683		foreach ($data_template_rrds as $data_template_rrd) {
684			unset($save);
685
686			$save['id']                         = 0;
687			$save['local_data_id']              = (isset($local_data_id) ? $local_data_id : 0);
688			$save['local_data_template_rrd_id'] = (isset($data_template_rrd['local_data_template_rrd_id']) ? $data_template_rrd['local_data_template_rrd_id'] : 0);
689			$save['data_template_id']           = (!empty($_local_data_id) ? $data_template_rrd['data_template_id'] : $data_template_id);
690			if ($save['local_data_id'] == 0) {
691				$save['hash']                   = get_hash_data_template($data_template_rrd['local_data_template_rrd_id'], 'data_template_item');
692			} else {
693				$save['hash'] = '';
694			}
695
696			foreach ($struct_data_source_item as $field => $array) {
697				$save[$field] = $data_template_rrd[$field];
698
699				if (isset($data_template_rrd['t_' . $field])) {
700					$save['t_' . $field] = $data_template_rrd['t_' . $field];
701				}
702			}
703
704			$data_template_rrd_id = sql_save($save, 'data_template_rrd');
705		}
706	}
707
708	/* create new entry(s): data_input_data */
709	if (cacti_sizeof($data_input_datas)) {
710		foreach ($data_input_datas as $data_input_data) {
711			db_execute_prepared('INSERT INTO data_input_data
712				(data_input_field_id, data_template_data_id, t_value, value)
713				VALUES (?, ?, ?, ?)',
714				array($data_input_data['data_input_field_id'], $data_template_data_id, $data_input_data['t_value'], $data_input_data['value']));
715		}
716	}
717
718	if (!empty($_local_data_id)) {
719		update_data_source_title_cache($local_data_id);
720	}
721}
722
723