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/*
26 * Standard HTML form elements
27 */
28
29/* draw_edit_form - draws an html edit form
30   @arg $array - an array that contains all of the information needed to draw
31     the html form. see the arrays contained in include/global_settings.php
32     for the extact syntax of this array */
33function draw_edit_form($array) {
34	if (cacti_sizeof($array) > 0) {
35		foreach ($array as $top_branch => $top_children) {
36			if ($top_branch == 'config') {
37				$config_array = $top_children;
38			} elseif ($top_branch == 'fields') {
39				$fields_array = $top_children;
40			}
41		}
42	}
43
44	if (cacti_sizeof($fields_array) > 0) {
45		if (!isset($config_array['no_form_tag'])) {
46			print "<form class='cactiForm' method='post' autocomplete='off' action='" . ((isset($config_array['post_to'])) ? $config_array['post_to'] : get_current_page()) . "'" . ((isset($config_array['form_name'])) ? " name='" . $config_array['form_name'] . "'" : '') . ((isset($config_array['enctype'])) ? " enctype='" . $config_array['enctype'] . "'" : '') . ">\n";
47		}
48
49		$i = 0;
50		$row_class = 'odd';
51
52		foreach ($fields_array as $field_name => $field_array) {
53			if ($field_array['method'] == 'hidden') {
54				print '<div class="hidden formRow">';
55				form_hidden_box($field_name, $field_array['value'], ((isset($field_array['default'])) ? $field_array['default'] : ''), true);
56				print '</div>';
57			} elseif ($field_array['method'] == 'hidden_zero') {
58				print '<div class="hidden formRow">';
59				form_hidden_box($field_name, $field_array['value'], '0', true);
60				print '</div>';
61			} elseif ($field_array['method'] == 'spacer') {
62				$collapsible = (isset($field_array['collapsible']) && $field_array['collapsible'] == 'true');
63
64				print "<div class='spacer formHeader" . ($collapsible ? ' collapsible':'') . "' id='row_$field_name'><div class='formHeaderText'>" . html_escape($field_array['friendly_name']);
65				print '<div class="formTooltip">' . (isset($field_array['description']) ? display_tooltip($field_array['description']):'') . '</div>';
66				print ($collapsible ? "<div class='formHeaderAnchor'><i class='fa fa-angle-double-up'></i></div>":'') . '</div></div>';
67			} else {
68				// Make a row using a div
69				if (isset($config_array['force_row_color'])) {
70					print "<div id='row_$field_name' class='formRow even-alternate $row_class'>";
71				} else {
72					print "<div id='row_$field_name' class='formRow $row_class'>";
73					if ($row_class == 'even') {
74						$row_class = 'odd';
75					} else {
76						$row_class = 'even';
77					}
78				}
79
80				// Make a form cell
81				print "<div class='formColumnLeft'>";
82
83				print "<div class='formFieldName'>";
84
85				if (isset($field_array['sub_checkbox'])) {
86					form_checkbox($field_array['sub_checkbox']['name'],
87						$field_array['sub_checkbox']['value'],
88						'',
89						((isset($field_array['sub_checkbox']['default'])) 	? $field_array['sub_checkbox']['default'] : ''),
90						((isset($field_array['sub_checkbox']['form_id'])) 	? $field_array['sub_checkbox']['form_id'] : ''),
91						((isset($field_array['sub_checkbox']['class'])) 	? $field_array['sub_checkbox']['class'] : ''),
92						((isset($field_array['sub_checkbox']['on_change'])) ? $field_array['sub_checkbox']['on_change'] : ''),
93						((isset($field_array['sub_checkbox']['friendly_name'])) ? $field_array['sub_checkbox']['friendly_name'] : ''));
94				}
95
96				print html_escape($field_array['friendly_name']);
97
98				if (read_config_option('hide_form_description') == 'on') {
99					print '<br><span class="formFieldDescription">' . ((isset($field_array['description'])) ? $field_array['description'] : '') . "</span>\n";
100				} else {
101					print '<div class="formTooltip">';
102					print display_tooltip((isset($field_array['description'])) ? $field_array['description'] : '');
103					print '</div>';
104				}
105
106				print '</div>';
107
108				// End form cell
109				print '</div>';
110
111				// New form column for content
112				print '<div class="formColumnRight"><div class="formData">';
113
114				draw_edit_control($field_name, $field_array);
115
116				// End content column
117				print '</div></div>';
118
119				// End form row
120				print '</div>';
121			}
122
123			$i++;
124		}
125	}
126}
127
128/* draw_edit_control - draws a single control to be used on an html edit form
129   @arg $field_name - the name of the control
130   @arg $field_array - an array containing data for this control. see include/global_form.php
131     for more specific syntax */
132function draw_edit_control($field_name, &$field_array) {
133	switch ($field_array['method']) {
134	case 'textbox':
135		form_text_box(
136			$field_name,
137			$field_array['value'],
138			((isset($field_array['default'])) ? $field_array['default'] : ''),
139			$field_array['max_length'],
140			((isset($field_array['size'])) ? $field_array['size'] : '40'),
141			'text',
142			((isset($field_array['form_id'])) ? $field_array['form_id'] : ''),
143			((isset($field_array['placeholder'])) ? $field_array['placeholder'] : '')
144		);
145
146		break;
147	case 'filepath':
148		form_filepath_box($field_name,
149			$field_array['value'],
150			((isset($field_array['default'])) ? $field_array['default'] : ''),
151			$field_array['max_length'],
152			((isset($field_array['size'])) ? $field_array['size'] : '40'),
153			'text',
154			((isset($field_array['form_id'])) ? $field_array['form_id'] : '')
155		);
156
157		break;
158	case 'dirpath':
159		form_dirpath_box(
160			$field_name,
161			$field_array['value'],
162			((isset($field_array['default'])) ? $field_array['default'] : ''),
163			$field_array['max_length'],
164			((isset($field_array['size'])) ? $field_array['size'] : '40'),
165			'text',
166			((isset($field_array['form_id'])) ? $field_array['form_id'] : '')
167		);
168
169		break;
170	case 'textbox_password':
171		form_text_box(
172			$field_name,
173			$field_array['value'],
174			((isset($field_array['default'])) ? $field_array['default'] : ''),
175			$field_array['max_length'],
176			((isset($field_array['size'])) ? $field_array['size'] : '40'),
177			'password',
178			((isset($field_array['form_id'])) ? $field_array['form_id'] : ''),
179			'********'
180		);
181
182		print '<br>';
183
184		form_text_box(
185			$field_name . '_confirm',
186			$field_array['value'],
187			((isset($field_array['default'])) ? $field_array['default'] : ''),
188			$field_array['max_length'],
189			((isset($field_array['size'])) ? $field_array['size'] : '40'),
190			'password',
191			((isset($field_array['form_id'])) ? $field_array['form_id'] : ''),
192			'********'
193		);
194
195		break;
196	case 'textarea':
197		form_text_area(
198			$field_name,
199			$field_array['value'],
200			$field_array['textarea_rows'],
201			$field_array['textarea_cols'],
202			((isset($field_array['default'])) ? $field_array['default'] : ''),
203			((isset($field_array['class'])) ? $field_array['class'] : ''),
204			((isset($field_array['on_change'])) ? $field_array['on_change'] : ''),
205			((isset($field_array['placeholder'])) ? $field_array['placeholder'] : '')
206		);
207
208		break;
209	case 'drop_array':
210		form_dropdown(
211			$field_name,
212			$field_array['array'],
213			'',
214			'',
215			$field_array['value'],
216			((isset($field_array['none_value'])) ? $field_array['none_value'] : ''),
217			((isset($field_array['default'])) ? $field_array['default'] : ''),
218			((isset($field_array['class'])) ? $field_array['class'] : ''),
219			((isset($field_array['on_change'])) ? $field_array['on_change'] : '')
220		);
221
222		break;
223	case 'drop_language':
224		form_droplanguage(
225			$field_name,
226			'',
227			'',
228			$field_array['value'],
229			((isset($field_array['none_value'])) ? $field_array['none_value'] : ''),
230			((isset($field_array['default'])) ? $field_array['default'] : ''),
231			((isset($field_array['class'])) ? $field_array['class'] : ''),
232			((isset($field_array['on_change'])) ? $field_array['on_change'] : '')
233		);
234
235		break;
236	case 'drop_files':
237		$array_files = array();
238
239		if (isset($field_array['directory'])) {
240			$dir = $field_array['directory'];
241
242			if (is_dir($dir) && is_readable($dir)) {
243				if (function_exists('scandir')) {
244					$files = scandir($dir);
245				} elseif ($dh = opendir($dir)) {
246					while (($file = readdir($dh)) !== false) {
247						$files[] = $file;
248					}
249					closedir($dh);
250				}
251
252				if (cacti_sizeof($files)) {
253				foreach($files as $file) {
254					if (is_readable($dir . '/' . $file) && $file != '.' && $file != '..') {
255						if (!in_array($file, $field_array['exclusions'])) {
256							$array_files[basename($file)] = basename($file);
257						}
258					}
259				}
260				}
261			}
262		}
263
264		form_dropdown(
265			$field_name,
266			$array_files,
267			'',
268			'',
269			$field_array['value'],
270			((isset($field_array['none_value'])) ? $field_array['none_value'] : ''),
271			((isset($field_array['default'])) ? $field_array['default'] : ''),
272			((isset($field_array['class'])) ? $field_array['class'] : ''),
273			((isset($field_array['on_change'])) ? $field_array['on_change'] : '')
274		);
275
276		break;
277	case 'drop_sql':
278		form_dropdown(
279			$field_name,
280			db_fetch_assoc($field_array['sql']),
281			'name',
282			'id',
283			$field_array['value'],
284			((isset($field_array['none_value'])) ? $field_array['none_value'] : ''),
285			((isset($field_array['default'])) ? $field_array['default'] : ''),
286			((isset($field_array['class'])) ? $field_array['class'] : ''),
287			((isset($field_array['on_change'])) ? $field_array['on_change'] : '')
288		);
289
290		break;
291	case 'drop_callback':
292		form_callback(
293			$field_name,
294			$field_array['sql'],
295			'name',
296			'id',
297			$field_array['action'],
298			$field_array['id'],
299			$field_array['value'],
300			((isset($field_array['none_value'])) ? $field_array['none_value'] : ''),
301			((isset($field_array['default'])) ? $field_array['default'] : ''),
302			((isset($field_array['class'])) ? $field_array['class'] : ''),
303			((isset($field_array['on_change'])) ? $field_array['on_change'] : '')
304		);
305
306		break;
307	case 'drop_multi':
308		form_multi_dropdown(
309			$field_name,
310			$field_array['array'],
311			(isset($field_array['sql']) ? db_fetch_assoc($field_array['sql']):$field_array['value']),
312			'id',
313			((isset($field_array['class'])) ? $field_array['class'] : ''),
314			((isset($field_array['on_change'])) ? $field_array['on_change'] : '')
315		);
316
317		break;
318	case 'drop_tree':
319		grow_dropdown_tree(
320			$field_array['tree_id'],
321			'0',
322			$field_name,
323			$field_array['value']
324		);
325
326		break;
327	case 'drop_color':
328		form_color_dropdown(
329			$field_name,
330			$field_array['value'],
331			__('None'),
332			((isset($field_array['default'])) ? $field_array['default'] : ''),
333			((isset($field_array['class'])) ? $field_array['class'] : ''),
334			((isset($field_array['on_change'])) ? $field_array['on_change'] : '')
335		);
336
337		break;
338	case 'checkbox':
339		form_checkbox(
340			$field_name,
341			$field_array['value'],
342			$field_array['friendly_name'],
343			((isset($field_array['default'])) ? $field_array['default'] : ''),
344			((isset($field_array['form_id'])) ? $field_array['form_id'] : ''),
345			((isset($field_array['class'])) ? $field_array['class'] : ''),
346			((isset($field_array['on_change'])) ? $field_array['on_change'] : ''),
347			$field_array['friendly_name']
348		);
349
350		break;
351	case 'checkbox_group':
352		if (isset($field_array['type']) && $field_array['type'] == 'flex') {
353			print "</td></tr><tr><td><div id='${field_name}_group' class='checkboxgroup1 flexContainer'>" . PHP_EOL;
354		} else {
355			print "<div id='${field_name}_group' class='checkboxgroup1'>" . PHP_EOL;
356		}
357
358		foreach ($field_array['items'] as $check_name => $check_array) {
359			if (isset($field_array['type']) && $field_array['type'] == 'flex') {
360				print '<div class="flexChild">';
361			}
362
363			form_checkbox(
364				$check_name,
365				$check_array['value'],
366				$check_array['friendly_name'],
367				((isset($check_array['default'])) ? $check_array['default'] : ''),
368				((isset($check_array['form_id'])) ? $check_array['form_id'] : ''),
369				((isset($field_array['class'])) ? $field_array['class'] : ''),
370				((isset($check_array['on_change'])) ? $check_array['on_change'] : (((isset($field_array['on_change'])) ? $field_array['on_change'] : ''))),
371				$field_array['friendly_name'],
372				true
373			);
374
375			if (isset($field_array['type']) && $field_array['type'] == 'flex') {
376				print '</div>';
377			} else {
378				print '<br>';
379			}
380		}
381
382		if (isset($field_array['type']) && $field_array['type'] == 'flex') {
383			print '</div>' . PHP_EOL;
384		} else {
385			print '</div>' . PHP_EOL;
386		}
387
388		break;
389	case 'radio':
390		print "<div style='formRadio'>" . PHP_EOL;
391
392		foreach ($field_array['items'] as $radio_index => $radio_array) {
393			form_radio_button(
394				$field_name,
395				$field_array['value'],
396				$radio_array['radio_value'],
397				$radio_array['radio_caption'],
398				((isset($field_array['default'])) ? $field_array['default'] : ''),
399				((isset($field_array['class'])) ? $field_array['class'] : ''),
400				((isset($field_array['on_change'])) ? $field_array['on_change'] : '')
401			);
402
403			print '<br>';
404		}
405
406		print '</div>' . PHP_EOL;
407
408		break;
409	case 'custom':
410		print $field_array['value'];
411
412		break;
413	case 'template_checkbox':
414		print '<em>' . html_boolean_friendly($field_array['value']) . '</em>';
415
416		form_hidden_box($field_name, $field_array['value'], '', true);
417
418		break;
419	case 'template_drop_array':
420		print '<em>' . $field_array['array'][$field_array['value']] . '</em>';
421
422		form_hidden_box($field_name, $field_array['value'], '', true);
423
424		break;
425	case 'font':
426		form_font_box(
427			$field_name,
428			$field_array['value'],
429			((isset($field_array['default'])) ? $field_array['default'] : ''),
430			$field_array['max_length'],
431			((isset($field_array['size'])) ? $field_array['size'] : '40'), 'text',
432			((isset($field_array['form_id'])) ? $field_array['form_id'] : ''),
433			((isset($field_array['placeholder'])) ? $field_array['placeholder'] : '')
434		);
435
436		break;
437	case 'file':
438		form_file($field_name,
439			((isset($field_array['size'])) ? $field_array['size'] : '40'),
440			((isset($field_array['accept'])) ? $field_array['accept'] : ''));
441
442		break;
443	case 'button':
444		form_button(
445			$field_name,
446			((isset($field_array['value'])) ? $field_array['value'] : ''),
447			((isset($field_array['title'])) ? $field_array['title'] : ''),
448			((isset($field_array['on_click'])) ? $field_array['on_click'] : '')
449		);
450
451		break;
452	case 'submit':
453		form_submit(
454			$field_name,
455			((isset($field_array['value'])) ? $field_array['value'] : ''),
456			((isset($field_array['title'])) ? $field_array['title'] : ''),
457			((isset($field_array['on_click'])) ? $field_array['on_click'] : '')
458		);
459
460		break;
461	default:
462		if (isset($field_array['value'])) {
463			print '<em>' . html_escape($field_array['value']) . '</em>';
464
465			form_hidden_box($field_name, $field_array['value'], '', true);
466		} else {
467			cacti_log('ERROR: Field Name: ' . $field_name . ' includes Method: ' . $field_array['method'] . ' does not include a value \'value\' element.', false);
468		}
469
470		break;
471	}
472}
473
474/* form_button - draws a standard button form element
475   @arg $form_name - the name of this form element
476   @arg $value - the display value for the button
477   @arg $title - the hover title for the button
478   @arg $action - the onClick action for the button */
479function form_button($form_name, $value, $title = '', $action = '') {
480	print "<input type='button' class='ui-button ui-corner-all ui-widget' " .
481		"id='$form_name' " .
482		"name='$form_name' " .
483		"value='" . html_escape($value) . "' " .
484		($action!='' ? "onClick='$action'":"") .
485		($title!='' ? "title='" . html_escape($title) . "'":"") . ">";
486}
487
488/* form_button - draws a standard button form element
489   @arg $form_name - the name of this form element
490   @arg $value - the display value for the button
491   @arg $title - the hover title for the button
492   @arg $action - the onClick action for the button */
493function form_submit($form_name, $value, $title = '', $action = '') {
494	print "<input type='submit' class='ui-button ui-corner-all ui-widget' " .
495		"id='$form_name' " .
496		"name='$form_name' " .
497		"value='" . html_escape($value) . "' " .
498		($action!='' ? "onClick='$action'":"") .
499		($title!='' ? "title='" . html_escape($title) . "'":"") . ">";
500}
501
502/* form_file - draws a standard html file input element
503   @arg $form_name - the name of this form element
504   @arg $form_size - the size (width) of the textbox
505   @arg $form_accept - the file types permitted
506 */
507function form_file($form_name, $form_size = 30, $form_accept = '') {
508	print "<div>\n";
509	print "<label class='import_label' for='$form_name'>" . __('Select a File'). "</label>\n";
510	print "<input type='file'";
511
512	if (isset($_SESSION['sess_error_fields']) && !empty($_SESSION['sess_error_fields'][$form_name])) {
513		print " class='import_button ui-state-default ui-corner-all txtErrorTextBox'";
514		unset($_SESSION['sess_error_fields'][$form_name]);
515	} else {
516		print " class='import_button ui-state-default ui-corner-all'";
517	}
518
519	print " id='$form_name' name='$form_name' size='$form_size'" . ($form_accept != '' ? " accept='$form_accept'":'') . ">\n";
520	print "<span class='import_text'></span>\n";
521	print "</div>\n";
522}
523
524/* form_filepath_box - draws a standard html textbox and provides status of a files existence
525   @arg $form_name - the name of this form element
526   @arg $form_previous_value - the current value of this form element
527   @arg $form_default_value - the value of this form element to use if there is
528     no current value available
529   @arg $form_max_length - the maximum number of characters that can be entered
530     into this textbox
531   @arg $form_size - the size (width) of the textbox
532   @arg $type - the type of textbox, either 'text' or 'password'
533   @arg $current_id - used to determine if a current value for this form element
534     exists or not. a $current_id of '0' indicates that no current value exists,
535     a non-zero value indicates that a current value does exist
536   @arg data - array containing 'text' element for display and if 'error' element present, shows failure */
537function form_filepath_box($form_name, $form_previous_value, $form_default_value, $form_max_length, $form_size = 30, $type = 'text', $current_id = 0, $data = false) {
538	if (($form_previous_value == '') && (empty($current_id))) {
539		$form_previous_value = $form_default_value;
540	}
541
542	print "<input type='$type'";
543
544	$extra_text = '';
545	$extra_color = '';
546	$extra_class = '';
547	$error_class = '';
548	if (is_array($data)) {
549		$extra_text = $data['text'];
550		$extra_class = (isset($data['error']) ? 'fa-times-circle' : 'fa-check-circle');
551		$extra_color = (isset($data['error']) ? 'red' : 'green');
552		$error_class = (isset($data['error']) ? 'txtErrorTextBox' : '');
553	} else {
554		if (isset($_SESSION['sess_field_values'])) {
555			if (!empty($_SESSION['sess_field_values'][$form_name])) {
556				$form_previous_value = $_SESSION['sess_field_values'][$form_name];
557			}
558		}
559
560		if (isset($_SESSION['sess_error_fields'])) {
561			if (!empty($_SESSION['sess_error_fields'][$form_name])) {
562				$error_class = 'txtErrorTextBox';
563				unset($_SESSION['sess_error_fields'][$form_name]);
564			}
565		}
566
567		if ($form_previous_value == '') {
568			$extra_text  = '';
569		} else if (is_file(trim($form_previous_value))) {
570			$extra_class = 'fa-check-circle';
571			$extra_color = 'green';
572			$extra_text  = __esc('File Found');
573		} else if (is_dir(trim($form_previous_value))) {
574			$extra_class = 'fa-times-circle';
575			$extra_color = 'red';
576			$extra_text  = __esc('Path is a Directory and not a File');
577		} else {
578			$extra_class = 'fa-times-circle';
579			$extra_color = 'red';
580			$extra_text  = __esc('File is Not Found');
581		}
582	}
583
584	$extra_data = '';
585	if ($extra_text != '') {
586		$extra_data = "<span class='cactiTooltipHint fa $extra_class' style='padding:5px;font-size:16px;color:$extra_color' title='$extra_text'></span>";
587	}
588
589	print " class='ui-state-default ui-corner-all$error_class'";
590
591	print " id='$form_name' placeholder='" . __esc('Enter a valid file path') . "' name='$form_name' size='$form_size'" . (!empty($form_max_length) ? " maxlength='$form_max_length'" : '') . " value='" . html_escape($form_previous_value) . "'>" . $extra_data;
592}
593
594/* form_dirpath_box - draws a standard html textbox and provides status of a directories existence
595   @arg $form_name - the name of this form element
596   @arg $form_previous_value - the current value of this form element
597   @arg $form_default_value - the value of this form element to use if there is
598     no current value available
599   @arg $form_max_length - the maximum number of characters that can be entered
600     into this textbox
601   @arg $form_size - the size (width) of the textbox
602   @arg $type - the type of textbox, either 'text' or 'password'
603   @arg $current_id - used to determine if a current value for this form element
604     exists or not. a $current_id of '0' indicates that no current value exists,
605     a non-zero value indicates that a current value does exist */
606function form_dirpath_box($form_name, $form_previous_value, $form_default_value, $form_max_length, $form_size = 30, $type = 'text', $current_id = 0) {
607	if (($form_previous_value == '') && (empty($current_id))) {
608		$form_previous_value = $form_default_value;
609	}
610
611	print "<input type='$type'";
612
613	if (isset($_SESSION['sess_error_fields'])) {
614		if (!empty($_SESSION['sess_error_fields'][$form_name])) {
615			print " class='ui-state-default ui-corner-all txtErrorTextBox'";
616			unset($_SESSION['sess_error_fields'][$form_name]);
617		} else {
618			print " class='ui-state-default ui-corner-all'";
619		}
620	}
621
622	if (isset($_SESSION['sess_field_values'])) {
623		if (!empty($_SESSION['sess_field_values'][$form_name])) {
624			$form_previous_value = $_SESSION['sess_field_values'][$form_name];
625		}
626	}
627
628	if (is_dir($form_previous_value)) {
629		$extra_data = "<span class='cactiTooltipHint fa fa-check-circle' style='padding:5px;font-size:16px;color:green' title='" . __esc('Directory Found') ."'></span>";
630	}else if (is_file($form_previous_value)) {
631		$extra_data = "<span class='cactiTooltipHint fa fa-times-circle' style='padding:5px;font-size:16px;color:red' title='" . __esc('Path is a File and not a Directory'). "></span>";
632	}else if ($form_previous_value == '') {
633		$extra_data = '';
634	} else {
635		$extra_data = "<span class='cactiTooltipHint fa fa-times-circle' style='padding:5px;font-size:16px;color:red' title='" . __esc('Directory is Not found'). "'></span>";
636	}
637
638	print " id='$form_name' name='$form_name' placeholder='" . __esc('Enter a valid directory path'). "' size='$form_size'" . (!empty($form_max_length) ? " maxlength='$form_max_length'" : '') . " value='" . html_escape($form_previous_value) . "'>" . $extra_data;
639}
640
641/* form_text_box - draws a standard html textbox
642   @arg $form_name - the name of this form element
643   @arg $form_previous_value - the current value of this form element
644   @arg $form_default_value - the value of this form element to use if there is
645     no current value available
646   @arg $form_max_length - the maximum number of characters that can be entered
647     into this textbox
648   @arg $form_size - the size (width) of the textbox
649   @arg $type - the type of textbox, either 'text' or 'password'
650   @arg $current_id - used to determine if a current value for this form element
651     exists or not. a $current_id of '0' indicates that no current value exists,
652     a non-zero value indicates that a current value does exist
653   @arg $placeholder - place a placeholder over an empty field
654   @arg $title - use a title attribute when hovering over the textbox
655 */
656function form_text_box($form_name, $form_previous_value, $form_default_value, $form_max_length, $form_size = 30, $type = 'text', $current_id = 0, $placeholder = '', $title = '') {
657	if (($form_previous_value == '') && (empty($current_id))) {
658		$form_previous_value = $form_default_value;
659	}
660
661	if ($type == 'password') {
662		print "<input type='text' style='display:none' value=''><input type='password' style='display:none' autocomplete='current-password' value=''>";
663	}
664
665	print "<input type='$type' " . ($type == 'password' || $type == 'password_confirm' ? 'autocomplete="current-password"':'off') . ($title != '' ? ' title="' . $title . '"':'');
666
667	if (isset($_SESSION['sess_error_fields'])) {
668		if (!empty($_SESSION['sess_error_fields'][$form_name])) {
669			print " class='ui-state-default ui-corner-all txtErrorTextBox'";
670			unset($_SESSION['sess_error_fields'][$form_name]);
671		} else {
672			print " class='ui-state-default ui-corner-all'";
673		}
674	} else {
675		print " class='ui-state-default ui-corner-all'";
676	}
677
678	if (isset($_SESSION['sess_field_values']) && isset($_SESSION['sess_error_fields'])) {
679		if (!empty($_SESSION['sess_field_values'][$form_name])) {
680			$form_previous_value = $_SESSION['sess_field_values'][$form_name];
681		}
682	}
683
684	print " id='$form_name' " . ($placeholder != '' ? "placeholder='" . html_escape($placeholder) . "'":'') . " name='$form_name' size='$form_size'" . (!empty($form_max_length) ? " maxlength='$form_max_length'" : '') . " value='" . html_escape($form_previous_value) . "'>\n";
685}
686
687/* form_hidden_box - draws a standard html hidden element
688   @arg $form_name - the name of this form element
689   @arg $form_previous_value - the current value of this form element
690   @arg $form_default_value - the value of this form element to use if there is
691     no current value available */
692function form_hidden_box($form_name, $form_previous_value, $form_default_value, $in_form = false) {
693	if ($form_previous_value == '') {
694		$form_previous_value = $form_default_value;
695	}
696
697	print "<div style='display:none;'><input style='height:0px;' type='hidden' id='$form_name' name='$form_name' value='" . html_escape($form_previous_value) . "'></div>";
698}
699
700/* form_dropdown - draws a standard html dropdown box
701   @arg $form_name - the name of this form element
702   @arg $form_data - an array containing data for this dropdown. it can be formatted
703     in one of two ways:
704     $array["id"] = "value";
705     -- or --
706     $array[0]["id"] = 43;
707     $array[0]["name"] = "Red";
708   @arg $column_display - used to indentify the key to be used for display data. this
709     is only applicable if the array is formatted using the second method above
710   @arg $column_id - used to indentify the key to be used for id data. this
711     is only applicable if the array is formatted using the second method above
712   @arg $form_previous_value - the current value of this form element
713   @arg $form_none_entry - the name to use for a default 'none' element in the dropdown
714   @arg $form_default_value - the value of this form element to use if there is
715     no current value available
716   @arg $css_class - any css that needs to be applied to this form element
717   @arg $on_change - onChange modifier */
718function form_dropdown($form_name, $form_data, $column_display, $column_id, $form_previous_value, $form_none_entry, $form_default_value, $class = '', $on_change = '') {
719	if ($form_previous_value == '') {
720		$form_previous_value = $form_default_value;
721	}
722
723	if (isset($_SESSION['sess_error_fields'])) {
724		if (!empty($_SESSION['sess_error_fields'][$form_name])) {
725			$class .= ($class != '' ? ' ':'') . 'txtErrorTextBox';
726			unset($_SESSION['sess_error_fields'][$form_name]);
727		}
728	}
729
730	if (isset($_SESSION['sess_field_values'])) {
731		if (!empty($_SESSION['sess_field_values'][$form_name])) {
732			$form_previous_value = $_SESSION['sess_field_values'][$form_name];
733		}
734	}
735
736	if ($class != '') {
737		$class = " class='$class' ";
738	}
739
740	if ($on_change != '') {
741		$on_change = " onChange='$on_change' ";
742	}
743
744	print "<select id='" . html_escape($form_name) . "' name='" . html_escape($form_name) . "'" . $class . $on_change . '>';
745
746	if (!empty($form_none_entry)) {
747		print "<option value='0'" . (empty($form_previous_value) ? ' selected' : '') . ">$form_none_entry</option>\n";
748	}
749
750	html_create_list($form_data, $column_display, $column_id, html_escape($form_previous_value));
751
752	print "</select>\n";
753}
754
755function form_droplanguage($form_name, $column_display, $column_id, $form_previous_value, $form_none_entry, $form_default_value, $class = '', $on_change = '') {
756	if ($form_previous_value == '') {
757		$form_previous_value = $form_default_value;
758	}
759
760	if (isset($_SESSION['sess_error_fields'])) {
761		if (!empty($_SESSION['sess_error_fields'][$form_name])) {
762			$class .= ($class != '' ? ' ':'') . 'txtErrorTextBox';
763			unset($_SESSION['sess_error_fields'][$form_name]);
764		}
765	}
766
767	if (isset($_SESSION['sess_field_values'])) {
768		if (!empty($_SESSION['sess_field_values'][$form_name])) {
769			$form_previous_value = $_SESSION['sess_field_values'][$form_name];
770		}
771	}
772
773	if ($class != '') {
774		$class = " class='$class' ";
775	}
776
777	if ($on_change != '') {
778		$on_change = " onChange='$on_change' ";
779	}
780
781	$languages = get_installed_locales();
782
783	print "<select id='" . html_escape($form_name) . "' name='" . html_escape($form_name) . "'" . $class . $on_change . '>';
784
785	foreach ($languages as $key => $value) {
786		$selected = '';
787		if ($form_previous_value == $key) {
788			$selected = ' selected';
789		}
790
791		$flags = explode('-', $key);
792
793		if (cacti_count($flags) > 1) {
794			$flagName = strtolower($flags[1]);
795		} else {
796			$flagName = strtolower($flags[0]);
797		}
798
799		print '<option value=\'' . $key . '\'' . $selected . ' data-class=\'flag-icon-' . $flagName . '\'><span class="flag-icon flag-icon-squared flag-icon-' . $flagName . '"></span>' . __($value) . '</option>';
800	}
801
802	print '</select>';
803}
804
805function form_callback($form_name, $classic_sql, $column_display, $column_id, $callback, $previous_id, $previous_value, $none_entry, $default_value, $class = '', $on_change = '') {
806	if ($previous_value == '') {
807		$previous_value = $default_value;
808	}
809
810	if (isset($_SESSION['sess_error_fields'])) {
811		if (!empty($_SESSION['sess_error_fields'][$form_name])) {
812			$class .= ($class != '' ? ' ':'') . 'txtErrorTextBox';
813			unset($_SESSION['sess_error_fields'][$form_name]);
814		}
815	}
816
817	if (isset($_SESSION['sess_field_values'])) {
818		if (!empty($_SESSION['sess_field_values'][$form_name])) {
819			$previous_value = $_SESSION['sess_field_values'][$form_name];
820		}
821	}
822
823	if ($class != '') {
824		$class = " class='$class' ";
825	}
826
827	$theme = get_selected_theme();
828	if ($theme == 'classic' || read_config_option('autocomplete') > 0) {
829		print "<select id='" . html_escape($form_name) . "' name='" . html_escape($form_name) . "'" . $class . '>';
830
831		if (!empty($none_entry)) {
832			print "<option value='0'" . (empty($previous_value) ? ' selected' : '') . ">$none_entry</option>\n";
833		}
834
835		$form_data = db_fetch_assoc($classic_sql);
836
837		html_create_list($form_data, $column_display, $column_id, html_escape($previous_id));
838
839		print "</select>\n";
840	} else {
841		if (empty($previous_id) && $previous_value == '') {
842			$previous_value = $none_entry;
843		}
844
845		print "<span id='$form_name" . "_wrap' class='autodrop ui-selectmenu-button ui-selectmenu-button-closed ui-corner-all ui-corner-all ui-button ui-widget'>";
846		print "<span id='$form_name" . "_click' style='z-index:4' class='ui-selectmenu-icon ui-icon ui-icon-triangle-1-s'></span>";
847		print "<span class='ui-select-text'>";
848		print "<input type='text' class='ui-state-default ui-corner-all' id='$form_name" . "_input' value='" . html_escape($previous_value) . "'>";
849		print "</span>";
850
851		if (!empty($none_entry) && empty($previous_value)) {
852			$previous_value = $none_entry;
853		}
854
855		print "</span>";
856		print "<input type='hidden' id='" . $form_name . "' name='" . $form_name . "' value='" . html_escape($previous_id) . "'>";
857		?>
858		<script type='text/javascript'>
859		var <?php print $form_name;?>Timer;
860		var <?php print $form_name;?>ClickTimer;
861		var <?php print $form_name;?>Open = false;
862
863		$(function() {
864		    $('#<?php print $form_name;?>_input').autocomplete({
865		        source: '<?php print get_current_page();?>?action=<?php print $callback;?>',
866				autoFocus: true,
867				minLength: 0,
868				select: function(event,ui) {
869					$('#<?php print $form_name;?>_input').val(ui.item.label);
870					if (ui.item.id) {
871						$('#<?php print $form_name;?>').val(ui.item.id);
872					} else {
873						$('#<?php print $form_name;?>').val(ui.item.value);
874					}
875					<?php print $on_change;?>;
876				}
877			}).css('border', 'none').css('background-color', 'transparent');
878
879			$('#<?php print $form_name;?>_wrap').on('dblclick', function() {
880				<?php print $form_name;?>Open = false;
881				clearTimeout(<?php print $form_name;?>Timer);
882				clearTimeout(<?php print $form_name;?>ClickTimer);
883				$('#<?php print $form_name;?>_input').autocomplete('close').select();
884			}).on('click', function() {
885				if (<?php print $form_name;?>Open) {
886					$('#<?php print $form_name;?>_input').autocomplete('close');
887					clearTimeout(<?php print $form_name;?>Timer);
888					<?php print $form_name;?>Open = false;
889				} else {
890					<?php print $form_name;?>ClickTimer = setTimeout(function() {
891						$('#<?php print $form_name;?>_input').autocomplete('search', '');
892						clearTimeout(<?php print $form_name;?>Timer);
893						<?php print $form_name;?>Open = true;
894					}, 200);
895				}
896				$('#<?php print $form_name;?>_input').select();
897			}).on('mouseleave', function() {
898				<?php print $form_name;?>Timer = setTimeout(function() { $('#<?php print $form_name;?>_input').autocomplete('close'); }, 800);
899			});
900
901			width = $('#<?php print $form_name;?>_input').textBoxWidth();
902			if (width < 100) {
903				width = 100;
904			}
905
906			$('#<?php print $form_name;?>_wrap').css('width', width+20);
907			$('#<?php print $form_name;?>_input').css('width', width);
908
909			$('ul[id^="ui-id"]').on('mouseenter', function() {
910				clearTimeout(<?php print $form_name;?>Timer);
911			}).on('mouseleave', function() {
912				<?php print $form_name;?>Timer = setTimeout(function() { $('#<?php print $form_name;?>_input').autocomplete('close'); }, 800);
913			});
914
915			$('ul[id^="ui-id"] > li').each().on('mouseenter', function() {
916				$(this).addClass('ui-state-hover');
917			}).on('mouseleave', function() {
918				$(this).removeClass('ui-state-hover');
919			});
920
921			$('#<?php print $form_name;?>_wrap').on('mouseenter', function() {
922				$(this).addClass('ui-state-hover');
923				$('input#<?php print $form_name;?>_input').addClass('ui-state-hover');
924			}).on('mouseleave', function() {
925				$(this).removeClass('ui-state-hover');
926				$('input#<?php print $form_name;?>_input').removeClass('ui-state-hover');
927			});
928		});
929		</script>
930		<?php
931	}
932}
933
934/** form_checkbox - draws a standard html checkbox
935   @param string $form_name - the name of this form element
936   @param string $form_previous_value - the current value of this form element
937   @param string $form_caption - the text to display to the right of the checkbox
938   @param string $form_default_value - the value of this form element to use if there is
939     no current value available
940   @param int $current_id - used to determine if a current value for this form element
941     exists or not. a $current_id of '0' indicates that no current value exists,
942     a non-zero value indicates that a current value does exist
943   @param string $class - specify a css class
944   @param string $on_change - specify a javascript onchange action
945   @param string $title - specify a title for the checkbox on hover
946   @param boolean $show_label - show the form caption in the checkbox
947*/
948function form_checkbox($form_name, $form_previous_value, $form_caption, $form_default_value, $current_id = 0, $class = '', $on_change = '', $title = '', $show_label = false) {
949	if (($form_previous_value == '') && (empty($current_id))) {
950		$form_previous_value = $form_default_value;
951	}
952
953	if (isset($_SESSION['sess_field_values'])) {
954		if (!empty($_SESSION['sess_field_values'][$form_name])) {
955			$form_previous_value = $_SESSION['sess_field_values'][$form_name];
956		}
957	}
958
959	if ($class != '') {
960		$class = ' ' . trim($class);
961	}
962
963	if ($on_change != '') {
964		$on_change = " onChange='$on_change'";
965	}
966
967	if ($form_previous_value == 'on') {
968		$checked = " checked aria-checked='true'";
969	} else {
970		$checked = " aria-checked='false'";
971	}
972
973	$labelClass = '';
974	if ($show_label) {
975		$labelClass = ' checkboxLabelWanted';
976	}
977
978	print "<span class='nowrap'>";
979	print "<label class='checkboxSwitch' " . ($title != '' ? " title='" . html_escape($title) . "'":'') . '><input ' . ($title != '' ? " title='" . html_escape($title) . "'":'') . " class='formCheckbox$class' type='checkbox' id='$form_name' name='$form_name'" . $on_change . $checked . "><span class='checkboxSlider checkboxRound'></span></label>";
980	print "<label class='checkboxLabel$labelClass' for='$form_name'>" . html_escape($form_caption) . '</label>';
981	print '</span>';
982}
983
984/* form_radio_button - draws a standard html radio button
985   @arg $form_name - the name of this form element
986   @arg $form_previous_value - the current value of this form element (selected or not)
987   @arg $form_current_value - the current value of this form element (element id)
988   @arg $form_caption - the text to display to the right of the checkbox
989   @arg $form_default_value - the value of this form element to use if there is
990     no current value available */
991function form_radio_button($form_name, $form_previous_value, $form_current_value, $form_caption, $form_default_value, $class = '', $on_change = '') {
992	if ($form_previous_value == '') {
993		$form_previous_value = $form_default_value;
994	}
995
996	if (isset($_SESSION['sess_field_values'])) {
997		if (!empty($_SESSION['sess_field_values'][$form_name])) {
998			$form_previous_value = $_SESSION['sess_field_values'][$form_name];
999		}
1000	}
1001
1002	if ($class != '') {
1003		$class = " $class";
1004	}
1005
1006	if ($on_change != '') {
1007		$on_change = " onChange='$on_change' ";
1008	}
1009
1010	if ($form_previous_value == $form_current_value) {
1011		$checked = " checked aria-checked='true'";
1012	} else {
1013		$checked = " aria-checked='false'";
1014	}
1015
1016	$css_id = $form_name . '_' . $form_current_value;
1017
1018
1019	print "<span class='nowrap'>";
1020	print "<label class='radioSwitch'><input value='" . html_escape($form_current_value) .
1021		"' class='formCheckbox$class' type='radio' id='$css_id' name='$form_name'" .
1022		$on_change . $checked . "><span class='radioSlider radioRound'></span></label>";
1023	print "<label class='radioLabelWanted' for='$css_id'>" . html_escape($form_caption) . "</label>";
1024	print "</span>";
1025}
1026
1027/* form_text_area - draws a standard html text area box
1028   @arg $form_name - the name of this form element
1029   @arg $form_previous_value - the current value of this form element (selected or not)
1030   @arg $form_rows - the number of rows in the text area box
1031   @arg $form_columns - the number of columns in the text area box
1032   @arg $form_default_value - the value of this form element to use if there is
1033     no current value available */
1034function form_text_area($form_name, $form_previous_value, $form_rows, $form_columns, $form_default_value, $class = '', $on_change = '', $placeholder = '') {
1035	if ($form_previous_value == '') {
1036		$form_previous_value = $form_default_value;
1037	}
1038
1039	if (isset($_SESSION['sess_error_fields'])) {
1040		if (!empty($_SESSION['sess_error_fields'][$form_name])) {
1041			$class .= ($class != '' ? ' ':'') . 'txtErrorTextBox';
1042			unset($_SESSION['sess_error_fields'][$form_name]);
1043		}
1044	}
1045
1046	if (isset($_SESSION['sess_field_values'])) {
1047		if (!empty($_SESSION['sess_field_values'][$form_name])) {
1048			$form_previous_value = $_SESSION['sess_field_values'][$form_name];
1049		}
1050	}
1051
1052	if ($on_change != '') {
1053		$on_change = " onChange='$on_change' ";
1054	}
1055
1056	if ($placeholder != '') {
1057		$placeholder = " placeholder='" . html_escape($placeholder) . "'";
1058	}
1059
1060	print "<textarea class='$class ui-state-default ui-corner-all' aria-multiline='true' cols='$form_columns' rows='$form_rows' id='$form_name' name='$form_name'" . $on_change . $placeholder . '>' . html_escape($form_previous_value) . "</textarea>\n";
1061}
1062
1063/* form_multi_dropdown - draws a standard html multiple select dropdown
1064   @arg $form_name - the name of this form element
1065   @arg $array_display - an array containing display values for this dropdown. it must
1066     be formatted like:
1067     $array[id] = display;
1068   @arg $sql_previous_values - an array containing keys that should be marked as selected.
1069     it must be formatted like:
1070     $array[0][$column_id] = key
1071   @arg $column_id - the name of the key used to reference the keys above */
1072function form_multi_dropdown($form_name, $array_display, $sql_previous_values, $column_id, $class = '', $on_change = '') {
1073	if (!is_array($sql_previous_values) && $sql_previous_values != '') {
1074		$values = explode(',', $sql_previous_values);
1075		$sql_previous_values = array();
1076		foreach($values as $value) {
1077			$sql_previous_values[][$column_id] = $value;
1078		}
1079	} elseif ($sql_previous_values == '') {
1080		$values = db_fetch_cell_prepared('SELECT value FROM settings WHERE name = ?', array($form_name));
1081		if ($values != '') {
1082			$values = explode(',', $values);
1083			foreach($values as $value) {
1084				$sql_previous_values[][$column_id] = $value;
1085			}
1086		}
1087	}
1088
1089	if (isset($_SESSION['sess_error_fields'])) {
1090		if (!empty($_SESSION['sess_error_fields'][$form_name])) {
1091			$class .= ($class != '' ? ' ':'') . 'txtErrorTextBox';
1092			unset($_SESSION['sess_error_fields'][$form_name]);
1093		}
1094	}
1095
1096	$class = 'multiselect';
1097	if ($class != '') {
1098		$class .= " $class";
1099	}
1100
1101	if ($on_change != '') {
1102		$on_change = " onChange='$on_change' ";
1103	}
1104
1105	print "<select style='height:20px;' size='1' class='$class' id='$form_name' name='$form_name" . "[]' multiple>\n";
1106
1107	foreach (array_keys($array_display) as $id) {
1108		print "<option value='" . $id . "'";
1109
1110		if (is_array($sql_previous_values) && cacti_sizeof($sql_previous_values)) {
1111			for ($i=0; ($i < cacti_count($sql_previous_values)); $i++) {
1112				if ($sql_previous_values[$i][$column_id] == $id) {
1113					print ' selected';
1114				}
1115			}
1116		}
1117
1118		print '>' . html_escape($array_display[$id]);
1119		print "</option>\n";
1120	}
1121
1122	print "</select>\n";
1123}
1124
1125/*
1126 * Second level form elements
1127 */
1128
1129/* form_color_dropdown - draws a dropdown containing a list of colors that uses a bit
1130     of css magic to make the dropdown item background color represent each color in
1131     the list
1132   @arg $form_name - the name of this form element
1133   @arg $form_previous_value - the current value of this form element
1134   @arg $form_none_entry - the name to use for a default 'none' element in the dropdown
1135   @arg $form_default_value - the value of this form element to use if there is
1136     no current value available */
1137function form_color_dropdown($form_name, $form_previous_value, $form_none_entry, $form_default_value, $class = '', $on_change = '') {
1138	if ($form_previous_value == '') {
1139		$form_previous_value = $form_default_value;
1140	}
1141
1142	if ($class != '') {
1143		$class = " class='colordropdown $class' ";
1144	} else {
1145		$class = " class='colordropdown'";
1146	}
1147
1148	$current_color = db_fetch_cell_prepared('SELECT hex
1149		FROM colors
1150		WHERE id = ?',
1151		array($form_previous_value));
1152
1153	if ($on_change != '') {
1154		$on_change = ' ' . $on_change . ';';
1155	}
1156
1157	$on_change = " onChange='this.style.backgroundColor=this.options[this.selectedIndex].style.backgroundColor;$on_change'";
1158
1159	$colors_sql = 'SELECT *
1160		FROM colors
1161		ORDER BY
1162			SUBSTRING(hex,0,2) ASC,
1163			SUBSTRING(hex,2,2) ASC,
1164			SUBSTRING(hex,4,2) ASC';
1165
1166	$colors_list = db_fetch_assoc($colors_sql);
1167
1168	print "<select style='background-color: #$current_color;' id='$form_name' name='$form_name'" . $class . $on_change . ">";
1169
1170	if ($form_none_entry != '') {
1171		print "<option value='0'>$form_none_entry</option>";
1172	}
1173
1174	if (cacti_sizeof($colors_list) > 0) {
1175		foreach ($colors_list as $color) {
1176			if ($color['name'] == '') {
1177				$display = __('Cacti Color (%s)', $color['hex']);
1178			} else {
1179				$display = $color['name'] . ' (' . $color['hex'] . ')';
1180			}
1181
1182			print "<option data-color='" . $color['hex'] . "' style='background-color: #" . $color['hex'] . ";' value='" . $color['id'] . "'";
1183
1184			if ($form_previous_value == $color['id']) {
1185				print ' selected';
1186			}
1187
1188			print '>' . html_escape($display) . '</option>';
1189		}
1190	}
1191
1192	print '</select>';
1193}
1194
1195/* form_font_box - draws a standard html textbox and provides status of a fonts existence
1196   @arg $form_name - the name of this form element
1197   @arg $form_previous_value - the current value of this form element
1198   @arg $form_default_value - the value of this form element to use if there is
1199     no current value available
1200   @arg $form_max_length - the maximum number of characters that can be entered
1201     into this textbox
1202   @arg $form_size - the size (width) of the textbox
1203   @arg $type - the type of textbox, either 'text' or 'password'
1204   @arg $current_id - used to determine if a current value for this form element
1205     exists or not. a $current_id of '0' indicates that no current value exists,
1206     a non-zero value indicates that a current value does exist */
1207function form_font_box($form_name, $form_previous_value, $form_default_value, $form_max_length, $form_size = 30, $type = 'text', $current_id = 0, $placeholder = '') {
1208	global $config;
1209
1210	if (($form_previous_value == '') && (empty($current_id))) {
1211		$form_previous_value = $form_default_value;
1212	}
1213
1214	print "<input type='$type'";
1215
1216	if (isset($_SESSION['sess_error_fields'])) {
1217		if (!empty($_SESSION['sess_error_fields'][$form_name])) {
1218			print " class='ui-state-default ui-corner-all txtErrorTextBox'";
1219			unset($_SESSION['sess_error_fields'][$form_name]);
1220		} else {
1221			print " class='ui-state-default ui-corner-all'";
1222		}
1223	}
1224
1225	if (isset($_SESSION['sess_field_values'])) {
1226		if (!empty($_SESSION['sess_field_values'][$form_name])) {
1227			$form_previous_value = $_SESSION['sess_field_values'][$form_name];
1228		}
1229	}
1230
1231	if ($form_previous_value == '') { # no data: defaults are used; everythings fine
1232		$extra_data = '';
1233	} else {
1234		/* verifying all possible pango font params is too complex to be tested here
1235		 * so we only escape the font
1236		 */
1237		$extra_data = "<span style='color:green'><br>[" . __('NO FONT VERIFICATION POSSIBLE') . ']</span>';
1238	}
1239
1240	print " id='$form_name' " . ($placeholder != '' ? "placeholder='" . html_escape($placeholder) . "'":'') . " name='$form_name' size='$form_size'" . (!empty($form_max_length) ? " maxlength='$form_max_length'" : '') . " value='" . html_escape($form_previous_value) . "'>" . $extra_data;
1241}
1242
1243/* form_confirm - draws a table presenting the user with some choice and allowing
1244     them to either proceed (delete) or cancel
1245   @arg $body_text - the text to prompt the user with on this form
1246   @arg $cancel_url - the url to go to when the user clicks 'cancel'
1247   @arg $action_url - the url to go to when the user clicks 'delete' */
1248function form_confirm($title_text, $body_text, $cancel_url, $action_url) { ?>
1249	<br>
1250	<table style="width:60%;">
1251		<tr>
1252			<td class='even' colspan='10'>
1253				<table>
1254					<tr class='cactiTableTitle'>
1255						<td class='textHeaderDark'><?php print $title_text;?></td>
1256					</tr>
1257					<?php
1258					form_area($body_text);
1259					form_confirm_buttons($action_url, $cancel_url);
1260					?>
1261				</table>
1262			</td>
1263		</tr>
1264	</table>
1265<?php }
1266
1267/* form_confirm_buttons - draws a cancel and delete button suitable for display
1268     on a confirmation form
1269   @arg $cancel_url - the url to go to when the user clicks 'cancel'
1270   @arg $action_url - the url to go to when the user clicks 'delete' */
1271function form_confirm_buttons($action_url, $cancel_url) {
1272	global $config;
1273	?>
1274	<tr>
1275		<td class='right'>
1276			<input type='button' class='ui-button ui-corner-all ui-widget' onClick='cactiReturnTo("<?php print html_escape($config['url_path'] . $cancel_url);?>")' value='<?php print __esc('Cancel');?>'>
1277			<input type='button' class='ui-button ui-corner-all ui-widget' onClick='cactiReturnTo("<?php print html_escape($config['url_path'] . $action_url . '&confirm=true');?>")' value='<?php print __esc('Delete');?>'>
1278		</td>
1279	</tr>
1280<?php }
1281
1282/* form_save_button - draws a (save|create) and cancel button at the bottom of
1283     an html edit form
1284   @arg $cancel_url - the url to go to when the user clicks 'cancel'
1285   @arg $force_type - if specified, will force the 'action' button to be either
1286     'save' or 'create'. otherwise this field should be properly auto-detected */
1287function form_save_button($cancel_url, $force_type = '', $key_field = 'id', $ajax = true) {
1288	$calt = __('Cancel');
1289
1290	if (empty($force_type) || $force_type == 'return') {
1291		if (isempty_request_var($key_field)) {
1292			$alt = __esc('Create');
1293		} else {
1294			$alt = __esc('Save');
1295
1296			if ($force_type != '') {
1297				$calt   = __esc('Return');
1298			} else {
1299				$calt   = __esc('Cancel');
1300			}
1301		}
1302	} elseif ($force_type == 'save') {
1303		$alt = __esc('Save');
1304	} elseif ($force_type == 'create') {
1305		$alt = __esc('Create');
1306	} elseif ($force_type == 'close') {
1307		$alt = __esc('Close');
1308	} elseif ($force_type == 'import') {
1309		$alt = __esc('Import');
1310	} elseif ($force_type == 'export') {
1311		$alt = __esc('Export');
1312	}
1313
1314	if ($force_type != 'import' && $force_type != 'export' && $force_type != 'save' && $force_type != 'close' && $cancel_url != '') {
1315		$cancel_action = "<input type='button' class='ui-button ui-corner-all ui-widget' onClick='cactiReturnTo(\"" . html_escape($cancel_url, ENT_QUOTES) . "\")' value='" . $calt . "'>";
1316	} else {
1317		$cancel_action = '';
1318	}
1319
1320	?>
1321	<table style='width:100%;text-align:center;'>
1322		<tr>
1323			<td class='saveRow'>
1324				<input type='hidden' name='action' value='save'>
1325				<?php print $cancel_action;?>
1326				<input type='submit' class='<?php print $force_type;?> ui-button ui-corner-all ui-widget' id='submit' value='<?php print $alt;?>'>
1327			</td>
1328		</tr>
1329	</table>
1330	<?php
1331
1332	form_end($ajax);
1333}
1334
1335/* form_save_buttons - draws a set of buttons at the end of a form
1336     an html edit form
1337   @arg $buttons - an array of 'id', 'name' buttons */
1338function form_save_buttons($buttons) {
1339	?>
1340	<table style='width:100%;text-align:center;'>
1341		<tr>
1342			<td class='saveRow'>
1343				<input type='hidden' name='action' value='save'>
1344				<?php foreach($buttons as $b) {
1345					print "<input type='button' class='ui-button ui-corner-all ui-widget' id='" . $b['id'] . "' value='" . html_escape($b['value']) . "'>\n";
1346				} ?>
1347			</td>
1348		</tr>
1349	</table>
1350	<?php
1351}
1352
1353/* form_start - draws post form start. To be combined with form_end()
1354   @arg $action - a mandatory php file URI
1355   @arg $id     - an optional id, if empty, one will be generated */
1356function form_start($action, $id = '', $multipart = false) {
1357	global $form_id, $form_action;
1358	static $counter = 1;
1359
1360	if ($id == '') {
1361		$form_id = 'form' . $counter;
1362		$counter++;
1363	} else {
1364		$form_id = trim($id);
1365	}
1366
1367	$form_action = $action;
1368
1369	print "<form class='cactiFormStart' id='$form_id' name='$form_id' action='$form_action' autocomplete='off' method='post'" . ($multipart ? " enctype='multipart/form-data'":'') . ">\n";
1370}
1371
1372/* form_end - draws post form end. To be combined with form_start() */
1373function form_end($ajax = true) {
1374	global $form_id, $form_action;
1375
1376	print '</form>' . PHP_EOL;
1377
1378	if ($ajax) { ?>
1379		<script type='text/javascript'>
1380		var formArray = [];
1381		var changed = false;
1382
1383		function warningMessage(href, type, scroll_or_id) {
1384			title='<?php print __esc('Warning Unsaved Form Data');?>';
1385			returnStr = '<div id="messageContainer" style="display:none">' +
1386				'<h4><?php print __('Unsaved Changes Detected');?></h4>' +
1387				'<p style="display:table-cell;overflow:auto"><?php print __('You have unsaved changes on this form.  If you press &#39;Continue&#39; these changes will be discarded.  Press &#39;Cancel&#39; to continue editing the form.');?></p>' +
1388				'</div>';
1389
1390			$('#messageContainer').remove();
1391			$('body').append(returnStr);
1392
1393			var messageButtons = {
1394				'Cancel': {
1395					text: sessionMessageCancel,
1396					id: 'messageCancel',
1397					click: function() {
1398						$(this).dialog('close');
1399						$('#messageContainer').remove();
1400					}
1401				},
1402				'Continue': {
1403					text: sessionMessageContinue,
1404					id: 'messageContinue',
1405					click: function() {
1406						$('#messageContainer').remove();
1407
1408						if (type == 'noheader') {
1409							loadPageNoHeader(href, scroll_or_id, true);
1410						} else if (type == 'toptab') {
1411							loadTopTab(href, scroll_or_id, true);
1412						} else {
1413							loadPage(href, true);
1414						}
1415					}
1416				}
1417			};
1418
1419			messageWidth = $(window).width();
1420			if (messageWidth > 600) {
1421				messageWidth = 600;
1422			} else {
1423				messageWidth -= 50;
1424			}
1425
1426			$('#messageContainer').dialog({
1427				draggable: true,
1428				resizable: false,
1429				height: 'auto',
1430				minWidth: messageWidth,
1431				maxWidth: 800,
1432				maxHeight: 600,
1433				title: title,
1434				buttons: messageButtons
1435			});
1436		}
1437
1438		$(function() {
1439			formArray['<?php print $form_id;?>'] = $('#<?php print $form_id;?>').serializeForm();
1440			changed = false;
1441
1442			$('#<?php print $form_id;?>').submit(function(event) {
1443				event.preventDefault();
1444
1445				// Enable the form if it's disabled
1446				$(this).find('input, textarea, select').prop('disabled', false);
1447
1448				strURL  = '<?php print $form_action;?>';
1449				strURL += (strURL.indexOf('?') >= 0 ? '&':'?') + 'header=false';
1450
1451				json =  $(this).serializeObject();
1452				$.post(strURL, json).done(function(data) {
1453					checkForLogout(data);
1454					var htmlObject  = $(data);
1455					var matches     = data.match(/<title>(.*?)<\/title>/);
1456
1457					if (matches != null) {
1458						var htmlTitle   = matches[1];
1459						var breadCrumbs = htmlObject.find('#breadcrumbs').html();
1460						var data        = htmlObject.find('#main').html();
1461
1462						$('#main').empty().hide();
1463						$('title').text(htmlTitle);
1464						$('#breadcrumbs').html(breadCrumbs);
1465						$('div[class^="ui-"]').remove();
1466						$('#main').html(data);
1467						applySkin();
1468					} else {
1469						$('#main').empty().hide().html(data);
1470						applySkin();
1471					}
1472
1473					if (isMobile.any() != null) {
1474						window.scrollTo(0,1);
1475					} else {
1476						window.scrollTo(0,0);
1477					}
1478				});
1479			});
1480		});
1481		</script>
1482		<?php
1483	}
1484}
1485
1486