';
}
$i++;
}
if (isset($_SESSION[SESS_ERROR_FIELDS]) && !cacti_sizeof($_SESSION[SESS_ERROR_FIELDS])) {
kill_session_var(SESS_ERROR_FIELDS);
}
}
}
/**
* Draws an edit control based on the specified method and field array.
*
* @param string $field_name - The name of the control.
* @param array $field_array - An array containing data for this
* control. see include/global_form.php
* for more specific syntax.
*
* @return void
*/
function draw_edit_control(string $field_name, array &$field_array) : void {
switch ($field_array['method']) {
case 'textbox':
form_text_box(
$field_name,
$field_array['value'],
($field_array['default'] ?? ''),
$field_array['max_length'],
($field_array['size'] ?? '40'),
($field_array['type'] ?? 'text'),
($field_array['form_id'] ?? ''),
($field_array['placeholder'] ?? '')
);
break;
case 'filepath':
form_filepath_box(
$field_name,
$field_array['value'],
($field_array['default'] ?? ''),
$field_array['max_length'],
($field_array['size'] ?? '40'),
'text',
($field_array['form_id'] ?? '')
);
break;
case 'dirpath':
form_dirpath_box(
$field_name,
$field_array['value'],
($field_array['default'] ?? ''),
$field_array['max_length'],
($field_array['size'] ?? '40'),
'text',
($field_array['form_id'] ?? '')
);
break;
case 'textbox_password':
form_text_box(
$field_name,
$field_array['value'],
($field_array['default'] ?? ''),
$field_array['max_length'],
($field_array['size'] ?? '40'),
'password',
($field_array['form_id'] ?? ''),
'********'
);
if (!isset($field_array['noconfirm'])) {
print '
';
form_text_box(
$field_name . '_confirm',
$field_array['value'],
($field_array['default'] ?? ''),
$field_array['max_length'],
($field_array['size'] ?? '40'),
'password',
($field_array['form_id'] ?? ''),
'********'
);
}
break;
case 'textarea':
form_text_area(
$field_name,
$field_array['value'],
$field_array['textarea_rows'],
$field_array['textarea_cols'],
($field_array['default'] ?? ''),
($field_array['class'] ?? ''),
($field_array['on_change'] ?? ''),
($field_array['placeholder'] ?? '')
);
break;
case 'textcert':
form_cert_box(
$field_name,
$field_array['value'],
($field_array['default'] ?? ''),
$field_array['textarea_rows'],
$field_array['textarea_cols']
);
break;
case 'privkey':
form_privkey_box(
$field_name,
$field_array['value'],
$field_array['textarea_rows'],
$field_array['textarea_cols']
);
break;
case 'drop_array':
form_dropdown(
$field_name,
$field_array['array'],
'',
'',
$field_array['value'],
($field_array['none_value'] ?? ''),
($field_array['default'] ?? ''),
($field_array['class'] ?? ''),
($field_array['on_change'] ?? ''),
($field_array['friendly_name'] ?? '')
);
break;
case 'drop_icon':
form_dropicon(
$field_name,
$field_array['array'],
'',
'',
$field_array['value'],
($field_array['none_value'] ?? ''),
($field_array['default'] ?? ''),
($field_array['class'] ?? ''),
($field_array['on_change'] ?? '')
);
break;
case 'drop_language':
form_droplanguage(
$field_name,
'',
'',
$field_array['value'],
($field_array['none_value'] ?? ''),
($field_array['default'] ?? ''),
($field_array['class'] ?? ''),
($field_array['on_change'] ?? '')
);
break;
case 'drop_files':
$array_files = [];
$files = [];
if (isset($field_array['directory'])) {
$dir = $field_array['directory'];
if (is_dir($dir) && is_readable($dir)) {
if (function_exists('scandir')) {
$files = scandir($dir);
} elseif ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
$files[] = $file;
}
closedir($dh);
}
if (cacti_sizeof($files)) {
foreach ($files as $file) {
if (is_readable($dir . '/' . $file) && $file != '.' && $file != '..') {
if (!in_array($file, $field_array['exclusions'], true)) {
$array_files[basename($file)] = basename($file);
}
}
}
}
}
}
form_dropdown(
$field_name,
$array_files,
'',
'',
$field_array['value'],
($field_array['none_value'] ?? ''),
($field_array['default'] ?? ''),
($field_array['class'] ?? ''),
($field_array['on_change'] ?? ''),
($field_array['friendly_name'] ?? '')
);
break;
case 'drop_sql':
form_dropdown(
$field_name,
db_fetch_assoc($field_array['sql']),
'name',
'id',
$field_array['value'],
($field_array['none_value'] ?? ''),
($field_array['default'] ?? ''),
($field_array['class'] ?? ''),
($field_array['on_change'] ?? ''),
($field_array['friendly_name'] ?? '')
);
break;
case 'drop_callback':
form_callback(
$field_name,
$field_array['sql'],
'name',
'id',
$field_array['action'],
$field_array['id'],
$field_array['value'],
($field_array['none_value'] ?? ''),
($field_array['default'] ?? ''),
($field_array['class'] ?? ''),
($field_array['on_change'] ?? ''),
($field_array['friendly_name'] ?? ''),
($field_array['request_vars'] ?? '')
);
break;
case 'drop_multi':
form_multi_dropdown(
$field_name,
$field_array['array'],
(isset($field_array['sql']) ? db_fetch_assoc($field_array['sql']) : $field_array['value']),
'id',
($field_array['class'] ?? ''),
($field_array['on_change'] ?? ''),
($field_array['select_all_text'] ?? ''),
($field_array['select_count_text'] ?? ''),
($field_array['select_all_value'] ?? '')
);
break;
case 'drop_tree':
grow_dropdown_tree(
$field_array['tree_id'],
'0',
$field_name,
$field_array['value']
);
break;
case 'drop_color':
form_color_dropdown(
$field_name,
$field_array['value'],
__('None'),
($field_array['default'] ?? ''),
($field_array['class'] ?? ''),
($field_array['on_change'] ?? '')
);
break;
case 'checkbox':
form_checkbox(
$field_name,
$field_array['value'],
$field_array['friendly_name'],
($field_array['default'] ?? ''),
($field_array['form_id'] ?? ''),
($field_array['class'] ?? ''),
($field_array['on_change'] ?? ''),
$field_array['friendly_name']
);
break;
case 'checkbox_group':
if (isset($field_array['type']) && $field_array['type'] == 'flex') {
print "
" . PHP_EOL;
} else {
print " " . PHP_EOL;
}
foreach ($field_array['items'] as $check_name => $check_array) {
if (isset($field_array['type']) && $field_array['type'] == 'flex') {
print ' ';
}
form_checkbox(
$check_name,
$check_array['value'],
$check_array['friendly_name'],
($check_array['default'] ?? ''),
($check_array['form_id'] ?? ''),
($field_array['class'] ?? ''),
($check_array['on_change'] ?? $field_array['on_change'] ?? ''),
$field_array['friendly_name'],
true
);
if (isset($field_array['type']) && $field_array['type'] == 'flex') {
print ' ';
} else {
print ' ';
}
}
if (isset($field_array['type']) && $field_array['type'] == 'flex') {
print ' ' . PHP_EOL;
} else {
print ' ' . PHP_EOL;
}
break;
case 'radio':
print "" . PHP_EOL;
foreach ($field_array['items'] as $radio_array) {
form_radio_button(
$field_name,
$field_array['value'],
$radio_array['radio_value'],
$radio_array['radio_caption'],
($field_array['default'] ?? ''),
($field_array['class'] ?? ''),
($field_array['on_change'] ?? '')
);
print ' ';
}
print ' ' . PHP_EOL;
break;
case 'custom':
print $field_array['value'];
break;
case 'template_checkbox':
print '' . html_boolean_friendly($field_array['value']) . '';
form_hidden_box($field_name, $field_array['value'], '', true);
break;
case 'template_drop_array':
print '' . $field_array['array'][$field_array['value']] . '';
form_hidden_box($field_name, $field_array['value'], '', true);
break;
case 'font':
form_font_box(
$field_name,
$field_array['value'],
($field_array['default'] ?? ''),
$field_array['max_length'],
($field_array['size'] ?? '40'),
'text',
($field_array['form_id'] ?? ''),
($field_array['placeholder'] ?? '')
);
break;
case 'file':
form_file(
$field_name,
($field_array['size'] ?? '40'),
($field_array['accept'] ?? '')
);
break;
case 'button':
form_button(
$field_name,
($field_array['value'] ?? ''),
($field_array['title'] ?? ''),
($field_array['on_click'] ?? '')
);
break;
case 'submit':
form_submit(
$field_name,
($field_array['value'] ?? ''),
($field_array['title'] ?? ''),
($field_array['on_click'] ?? '')
);
break;
default:
if (isset($field_array['value'])) {
print '' . htmle($field_array['value']) . '';
form_hidden_box($field_name, $field_array['value'], '', true);
} else {
cacti_log('ERROR: Field Name: ' . $field_name . ' includes Method: ' . $field_array['method'] . ' does not include a value \'value\' element.', false);
}
break;
}
}
/**
* form_button - draws a standard button form element
*
* @param string $form_name - The name of this form element
* @param string $value - The display value for the button
* @param string $title - The hover title for the button
* @param mixed $action - The onClick action for the button
*
* @return void
*/
function form_button(string $form_name, string $value, string $title = '', mixed $action = '') : void {
print "';
}
/**
* Generates an HTML submit button with optional JavaScript action and title.
*
* @param string $form_name - The name and ID of the form element.
* @param string $value - The display text of the submit button.
* @param string $title - The title attribute for the submit button.
* @param mixed $action - JavaScript code to execute on button click.
*
* @return void
*/
function form_submit(string $form_name, string $value, string $title = '', mixed $action = '') : void {
print "';
}
/**
* Draws a standard html file input element
*
* @param string $form_name - The name and ID of the file input element.
* @param int $form_size - The size attribute of the file input element. Default is 30.
* @param string $form_accept - The accept attribute of the file input element, specifying the types of files that the server accepts. Default is an empty string.
*
* @return void
*/
function form_file(string $form_name, int $form_size = 30, string $form_accept = '') : void {
print '';
print "';
print "';
print "";
print ' ';
}
/**
* Draws a standard html textbox and provides status of a files existence
*
* @param string $form_name The name of this form element
* @param mixed $prev_val The current value of this form element
* @param mixed $default_val The value of this form element to use if there is no current value available
* @param mixed $max_length The maximum number of characters that can be entered into this textbox
* @param mixed $form_size The size (width) of the textbox
* @param string $type The type of textbox, either 'text' or 'password'
* @param mixed $current_id Used to determine if a current value for this form element
* exists or not. a $current_id of '0' indicates that no
* current value exists, a non-zero value indicates that
* a current value does exist
* @param mixed $data Array containing 'text' element for display and if
* 'error' element present, shows failure
*
* @return void
*/
function form_filepath_box(string $form_name, mixed $prev_val, mixed $default_val, mixed $max_length,
mixed $form_size = 30, string $type = 'text', mixed $current_id = 0, mixed $data = false) : void {
if (($prev_val == '') && (empty($current_id))) {
$prev_val = $default_val;
}
print "";
}
print " class='ui-state-default ui-corner-all$error_class'";
print " id='$form_name' placeholder='" . __esc('Enter a valid file path') . "' name='$form_name' size='$form_size'" . (!empty($max_length) ? " maxlength='$max_length'" : '') . " value='" . htmle($prev_val) . "'>" . $extra_data;
}
/**
* Draws a standard html textbox and provides status of a directories existence
*
* @param string $form_name The name of this form element
* @param mixed $prev_val The current value of this form element
* @param mixed $default_val The value of this form element to use if there is no current value available
* @param mixed $max_length The maximum number of characters that can be entered into this textbox
* @param mixed $form_size The size (width) of the textbox
* @param string $type The type of textbox, either 'text' or 'password'
* @param mixed $current_id Used to determine if a current value for this form element
* exists or not. a $current_id of '0' indicates that no current value exists,
* a non-zero value indicates that a current value does exist
*
* @return void
*/
function form_dirpath_box(string $form_name, mixed $prev_val, mixed $default_val, mixed $max_length,
mixed $form_size = 30, string $type = 'text', mixed $current_id = 0) : void {
if (($prev_val == '') && (empty($current_id))) {
$prev_val = $default_val;
}
print "";
} elseif (is_file($prev_val)) {
$extra_data = "';
} elseif ($prev_val == '') {
$extra_data = '';
} else {
$extra_data = "";
}
print " id='$form_name' name='$form_name' placeholder='" . __esc('Enter a valid directory path') . "' size='$form_size'" . (!empty($max_length) ? " maxlength='$max_length'" : '') . " value='" . htmle($prev_val) . "'>" . $extra_data;
}
/**
* Draws a textarea for pasting a PEM certificate that, like
* form_privkey_box(), never redisplays the stored value - the textarea is
* always left blank, and leaving it blank on save means "keep the existing
* certificate" rather than clearing it. Like form_filepath_box()/
* form_dirpath_box(), a status indicator next to it shows the certificate's
* expiration date (YYYY-MM-DD) rather than a found/not-found file check.
*
* @param string $form_name The name of this form element
* @param mixed $stored_val The current (PEM) stored value; only used to
* compute the expiration status, never displayed
* @param mixed $default_val The value to check for a stored certificate when there is no current value
* @param int $form_rows The number of rows for the textarea
* @param int $form_columns The number of columns for the textarea
*
* @return void
*/
function form_cert_box(string $form_name, mixed $stored_val, mixed $default_val, int $form_rows, int $form_columns) : void {
if ($stored_val == '') {
$stored_val = $default_val;
}
$error_class = '';
if (isset($_SESSION[SESS_ERROR_FIELDS])) {
if (!empty($_SESSION[SESS_ERROR_FIELDS][$form_name])) {
$error_class = ' txtErrorTextBox';
unset($_SESSION[SESS_ERROR_FIELDS][$form_name]);
}
}
// Unconditionally blank: form_input_validate() writes SESS_FIELD_VALUES
// on every submission (even a successful save), and that save's redirect
// runs before bottom_footer() clears it - repopulating from it here would
// echo the just-submitted certificate back on the very next page load.
$textarea_val = '';
if (trim((string) $stored_val) == '') {
$extra_data = '';
} else {
// @ - openssl_x509_parse() emits a warning for non-PEM input; the
// false return value already tells us the certificate is invalid.
$parsed = @openssl_x509_parse((string) $stored_val);
if ($parsed === false || empty($parsed['validTo_time_t'])) {
$extra_data = "";
} else {
$expires = date('Y-m-d', $parsed['validTo_time_t']);
if ($parsed['validTo_time_t'] < time()) {
$extra_data = "" . __esc('Expired: %s', $expires) . '';
} else {
$extra_data = "" . __esc('Good Till: %s', $expires) . '';
}
}
}
print "' . $extra_data;
}
/**
* Draws a textarea for pasting a private key that, unlike every other
* field, never redisplays its stored value - the textarea is always left
* blank, and leaving it blank on save means "keep the existing key"
* rather than "clear it". The status area (styled like form_cert_box()'s
* expiration date) instead shows whether a key is currently stored.
*
* @param string $form_name The name of this form element
* @param mixed $stored_val The current (still-encrypted) stored value; only its
* presence is used, its content is never displayed
* @param int $form_rows The number of rows for the textarea
* @param int $form_columns The number of columns for the textarea
*
* @return void
*/
function form_privkey_box(string $form_name, mixed $stored_val, int $form_rows, int $form_columns) : void {
$error_class = '';
if (isset($_SESSION[SESS_ERROR_FIELDS])) {
if (!empty($_SESSION[SESS_ERROR_FIELDS][$form_name])) {
$error_class = ' txtErrorTextBox';
unset($_SESSION[SESS_ERROR_FIELDS][$form_name]);
}
}
// Unconditionally blank: form_input_validate() writes SESS_FIELD_VALUES
// on every submission (even a successful save), and that save's redirect
// runs before bottom_footer() clears it - repopulating from it here would
// echo the just-submitted plaintext private key back on the very next
// page load. Never restore this field's value from session.
$textarea_val = '';
if (trim((string) $stored_val) == '') {
$extra_data = "" . __esc('[not set]') . '';
} else {
$extra_data = "" . __esc('[stored]') . '';
}
print "' . $extra_data;
}
/**
* Draws a standard html textbox
*
* @param string $form_name The name of this form element
* @param mixed $prev_val The current value of this form element
* @param mixed $default_val The value of this form element to use if there is no current value available
* @param mixed $max_length The maximum number of characters that can be entered into this textbox
* @param mixed $form_size The size (width) of the textbox
* @param string $type The type of textbox, either 'text' or 'password'
* @param mixed $current_id Used to determine if a current value for this form element
* exists or not. a $current_id of '0' indicates that no current value exists,
* a non-zero value indicates that a current value does exist
* @param string $placeholder Place a placeholder over an empty field
* @param string $title Use a title attribute when hovering over the textbox
*
* @return void
*/
function form_text_box(string $form_name, mixed $prev_val, mixed $default_val, mixed $max_length,
mixed $form_size = 30, string $type = 'text', mixed $current_id = 0, string $placeholder = '', string $title = '') : void {
if (($prev_val == '') && (empty($current_id))) {
$prev_val = $default_val;
}
print "";
}
/**
* Draws a standard html hidden element
*
* @param string $form_name The name of this form element
* @param mixed $prev_val The current value of this form element
* @param mixed $default_val The value of this form element to use if there is no current value available
* @param mixed $in_form
*
* @return void
*/
function form_hidden_box(string $form_name, mixed $prev_val, mixed $default_val, mixed $in_form = false) : void {
if ($prev_val == '') {
$prev_val = $default_val;
}
print "";
}
/**
* Draws a standard html dropdown box
*
* @param string $form_name The name of this form element
* @param array $form_data An array containing data for this dropdown. it can be formatted
* in one of two ways:
* $array["id"] = "value";
* -- or --
* $array[0]["id"] = 43;
* $array[0]["name"] = "Red";
* @param string $column_display Used to identify the key to be used for display data. this
* is only applicable if the array is formatted using
* the second method above
* @param mixed $column_id Used to identify the key to be used for id data. this
* is only applicable if the array is formatted using
* the second method above
* @param mixed $prev_val The current value of this form element
* @param string $none_entry The name to use for a default 'none' element in the dropdown
* @param mixed $default_val The value of this form element to use if there is
* no current value available
* @param string $class any css that needs to be applied to this form element
* @param string $on_change The onChange modifier
* @param string $display_name The display name for this form object
*
* @return void
*/
function form_dropdown(string $form_name, array $form_data, string $column_display, mixed $column_id,
mixed $prev_val, string $none_entry, mixed $default_val, string $class = '',
string $on_change = '', string $display_name = '') : void {
global $form_id;
if ($prev_val == '') {
$prev_val = $default_val;
}
if (isset($_SESSION[SESS_ERROR_FIELDS])) {
if (!empty($_SESSION[SESS_ERROR_FIELDS][$form_name])) {
$class .= ($class != '' ? ' ' : '') . 'txtErrorTextBox';
unset($_SESSION[SESS_ERROR_FIELDS][$form_name]);
}
}
if (isset($_SESSION[SESS_FIELD_VALUES])) {
if (!empty($_SESSION[SESS_FIELD_VALUES][$form_name])) {
$prev_val = $_SESSION[SESS_FIELD_VALUES][$form_name];
}
}
if ($display_name != '') {
$display = " data-defaultLabel='" . htmle($display_name) . "'";
} else {
$display = '';
}
if ($class != '') {
$class = " class='$class' ";
}
if ($on_change != '') {
$on_change = " onChange='$on_change' ";
}
print "';
}
/**
* Draws a standard html dropdown box using icon definitions in the form array.
*
* @param string $form_name The name of this form element
* @param array $form_data An array containing data for this dropdown. It must contain
* the following structure.
*
* $dropdown_array = array(
* 'server' => array(
* 'display' => __('Some Value'),
* 'class' => 'ti ti-server',
* 'style' => 'width:30px;...'
* ),
* ...
* );
*
* @param string $column_display Used to identify the key to be used for display data. this
* is only applicable if the array is formatted using the
* second method above
* @param string $column_id Used to identify the key to be used for id data. this
* is only applicable if the array is formatted using the
* second method above.
* @param mixed $prev_val The current value of this form element
* @param string $none_entry The name to use for a default 'none' element in the dropdown
* @param mixed $default_val The value of this form element to use if there is no current value available
* @param string $class Any css that needs to be applied to this form element
* @param string $on_change The onChange modifier
* @param string $class The CSS Class for the object
*
* @return void
*/
function form_dropicon(string $form_name, array $form_data, string $column_display, string $column_id,
mixed $prev_val, string $none_entry, mixed $default_val, string $class = '', string $on_change = '') : void {
if ($prev_val == '') {
$prev_val = $default_val;
}
if (isset($_SESSION[SESS_ERROR_FIELDS])) {
if (!empty($_SESSION[SESS_ERROR_FIELDS][$form_name])) {
$class .= ($class != '' ? ' ' : '') . 'txtErrorTextBox';
unset($_SESSION[SESS_ERROR_FIELDS][$form_name]);
}
}
if (isset($_SESSION[SESS_FIELD_VALUES])) {
if (!empty($_SESSION[SESS_FIELD_VALUES][$form_name])) {
$prev_val = $_SESSION[SESS_FIELD_VALUES][$form_name];
}
}
if ($class != '') {
$class = " class='drop-icon $class' ";
} else {
$class = " class='drop-icon' ";
}
if ($on_change != '') {
$on_change = " onChange='$on_change' ";
}
print "';
}
/**
* Generates a dropdown selection form element for languages.
*
* @param string $form_name The name attribute for the select element.
* @param string $column_display Not used in the function.
* @param string $column_id Not used in the function.
* @param mixed $prev_val The previously selected value.
* @param string $none_entry Not used in the function.
* @param mixed $default_val The default value if no previous value is set.
* @param string $class Optional. Additional CSS classes for the select element.
* @param string $on_change Optional. JavaScript code to execute on change event.
*
* @return void
*/
function form_droplanguage(string $form_name, string $column_display, string $column_id,
mixed $prev_val, string $none_entry, mixed $default_val, string $class = '',
string $on_change = '') : void {
if ($prev_val == '') {
$prev_val = $default_val;
}
if (isset($_SESSION[SESS_ERROR_FIELDS])) {
if (!empty($_SESSION[SESS_ERROR_FIELDS][$form_name])) {
$class .= ($class != '' ? ' ' : '') . 'txtErrorTextBox';
unset($_SESSION[SESS_ERROR_FIELDS][$form_name]);
}
}
if (isset($_SESSION[SESS_FIELD_VALUES])) {
if (!empty($_SESSION[SESS_FIELD_VALUES][$form_name])) {
$prev_val = $_SESSION[SESS_FIELD_VALUES][$form_name];
}
}
if ($class != '') {
$class = " class='$class' ";
}
if ($on_change != '') {
$on_change = " onChange='$on_change' ";
}
$languages = get_installed_locales();
print "';
}
/**
* Generates a form element based on the provided parameters and configuration.
*
* @param string $form_name The name of the form element.
* @param string $classic_sql The SQL query to fetch data for the form element.
* @param string $column_display The column name to be displayed in the form element.
* @param string $column_id The column name to be used as the value in the form element.
* @param mixed $action The action to be performed on form element change.
* @param string $previous_id The previous ID value of the form element.
* @param mixed $prev_val The previous value of the form element.
* @param string $none_entry The text to display for a "none" entry.
* @param mixed $default_val The default value for the form element.
* @param string $class Optional. Additional CSS classes for the form element.
* @param string $on_change Optional. JavaScript function to call on form element change.
* @param string $display_name Optional. The display name for the column.
* @param string $request_vars Optional. The the request variables to include in the action
*
* @return void
*/
function form_callback(string $form_name, string $classic_sql, string $column_display, string $column_id,
mixed $action, string $previous_id, mixed $prev_val, string $none_entry, mixed $default_val,
string $class = '', string $on_change = '', string $display_name = '', string $request_vars = '') : void {
if ($prev_val == '') {
$prev_val = $default_val;
}
if (isset($_SESSION[SESS_ERROR_FIELDS])) {
if (!empty($_SESSION[SESS_ERROR_FIELDS][$form_name])) {
$class .= ($class != '' ? ' ' : '') . 'txtErrorTextBox';
unset($_SESSION[SESS_ERROR_FIELDS][$form_name]);
}
}
/* A non-zero 'autocomplete' config renders the full option list inline as a
* plain |