diff options
| author | Tristan Zur <tzur@web.web.ccwn.org> | 2014-03-27 22:27:47 +0100 |
|---|---|---|
| committer | Tristan Zur <tzur@web.web.ccwn.org> | 2014-03-27 22:27:47 +0100 |
| commit | b62676ca5d3d6f6ba3f019ea3f99722e165a98d8 (patch) | |
| tree | 86722cb80f07d4569f90088eeaea2fc2f6e2ef94 /hugo/libraries/config/validate.lib.php | |
Diffstat (limited to 'hugo/libraries/config/validate.lib.php')
| -rw-r--r-- | hugo/libraries/config/validate.lib.php | 584 |
1 files changed, 584 insertions, 0 deletions
diff --git a/hugo/libraries/config/validate.lib.php b/hugo/libraries/config/validate.lib.php new file mode 100644 index 0000000..8c62013 --- /dev/null +++ b/hugo/libraries/config/validate.lib.php @@ -0,0 +1,584 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Various validation functions + * + * Validation function takes two argument: id for which it is called + * and array of fields' values (usually values for entire formset, as defined + * in forms.inc.php). + * The function must always return an array with an error (or error array) + * assigned to a form element (formset name or field path). Even if there are + * no errors, key must be set with an empty value. + * + * Valdiation functions are assigned in $cfg_db['_validators'] (config.values.php). + * + * @package PhpMyAdmin + */ + +/** + * Returns validator list + * + * @return array + */ +function PMA_config_get_validators() +{ + static $validators = null; + + if ($validators === null) { + $cf = ConfigFile::getInstance(); + $validators = $cf->getDbEntry('_validators', array()); + if (!defined('PMA_SETUP')) { + // not in setup script: load additional validators for user + // preferences we need original config values not overwritten + // by user preferences, creating a new PMA_Config instance is a + // better idea than hacking into its code + $org_cfg = $cf->getOrgConfigObj(); + $uvs = $cf->getDbEntry('_userValidators', array()); + foreach ($uvs as $field => $uv_list) { + $uv_list = (array)$uv_list; + foreach ($uv_list as &$uv) { + if (!is_array($uv)) { + continue; + } + for ($i = 1; $i < count($uv); $i++) { + if (substr($uv[$i], 0, 6) == 'value:') { + $uv[$i] = PMA_arrayRead( + substr($uv[$i], 6), $org_cfg->settings + ); + } + } + } + $validators[$field] = isset($validators[$field]) + ? array_merge((array)$validators[$field], $uv_list) + : $uv_list; + } + } + } + return $validators; +} + +/** + * Runs validation $validator_id on values $values and returns error list. + * + * Return values: + * o array, keys - field path or formset id, values - array of errors + * when $isPostSource is true values is an empty array to allow for error list + * cleanup in HTML documen + * o false - when no validators match name(s) given by $validator_id + * + * @param string|array $validator_id ID of validator(s) to run + * @param array &$values Values to validate + * @param bool $isPostSource tells whether $values are directly from + * POST request + * + * @return bool|array + */ +function PMA_config_validate($validator_id, &$values, $isPostSource) +{ + // find validators + $validator_id = (array) $validator_id; + $validators = PMA_config_get_validators(); + $vids = array(); + $cf = ConfigFile::getInstance(); + foreach ($validator_id as &$vid) { + $vid = $cf->getCanonicalPath($vid); + if (isset($validators[$vid])) { + $vids[] = $vid; + } + } + if (empty($vids)) { + return false; + } + + // create argument list with canonical paths and remember path mapping + $arguments = array(); + $key_map = array(); + foreach ($values as $k => $v) { + $k2 = $isPostSource ? str_replace('-', '/', $k) : $k; + $k2 = strpos($k2, '/') ? $cf->getCanonicalPath($k2) : $k2; + $key_map[$k2] = $k; + $arguments[$k2] = $v; + } + + // validate + $result = array(); + foreach ($vids as $vid) { + // call appropriate validation functions + foreach ((array)$validators[$vid] as $validator) { + $vdef = (array) $validator; + $vname = array_shift($vdef); + $args = array_merge(array($vid, &$arguments), $vdef); + $r = call_user_func_array($vname, $args); + + // merge results + if (is_array($r)) { + foreach ($r as $key => $error_list) { + // skip empty values if $isPostSource is false + if (!$isPostSource && empty($error_list)) { + continue; + } + if (!isset($result[$key])) { + $result[$key] = array(); + } + $result[$key] = array_merge($result[$key], (array)$error_list); + } + } + } + } + + // restore original paths + $new_result = array(); + foreach ($result as $k => $v) { + $k2 = isset($key_map[$k]) ? $key_map[$k] : $k; + $new_result[$k2] = $v; + } + return empty($new_result) ? true : $new_result; +} + +/** + * Empty error handler, used to temporarily restore PHP internal error handler + * + * @return bool + */ +function PMA_null_error_handler() +{ + return false; +} + +/** + * Ensures that $php_errormsg variable will be registered in case of an error + * and enables output buffering (when $start = true). + * Called with $start = false disables output buffering end restores + * html_errors and track_errors. + * + * @param boolean $start Whether to start buffering + * + * @return void + */ +function test_php_errormsg($start = true) +{ + static $old_html_errors, $old_track_errors, $old_error_reporting; + static $old_display_errors; + if ($start) { + $old_html_errors = ini_get('html_errors'); + $old_track_errors = ini_get('track_errors'); + $old_display_errors = ini_get('display_errors'); + $old_error_reporting = error_reporting(E_ALL); + ini_set('html_errors', false); + ini_set('track_errors', true); + ini_set('display_errors', true); + set_error_handler("PMA_null_error_handler"); + ob_start(); + } else { + ob_end_clean(); + restore_error_handler(); + error_reporting($old_error_reporting); + ini_set('html_errors', $old_html_errors); + ini_set('track_errors', $old_track_errors); + ini_set('display_errors', $old_display_errors); + } +} + +/** + * Test database connection + * + * @param string $extension 'drizzle', 'mysql' or 'mysqli' + * @param string $connect_type 'tcp' or 'socket' + * @param string $host host name + * @param string $port tcp port to use + * @param string $socket socket to use + * @param string $user username to use + * @param string $pass password to use + * @param string $error_key key to use in return array + * + * @return bool|array + */ +function test_db_connection( + $extension, + $connect_type, + $host, + $port, + $socket, + $user, + $pass = null, + $error_key = 'Server' +) { + // test_php_errormsg(); + $socket = empty($socket) || $connect_type == 'tcp' ? null : $socket; + $port = empty($port) || $connect_type == 'socket' ? null : ':' . $port; + $error = null; + if ($extension == 'drizzle') { + while (1) { + $drizzle = @drizzle_create(); + if (!$drizzle) { + $error = __('Could not initialize Drizzle connection library'); + break; + } + $conn = $socket + ? @drizzle_con_add_uds($socket, $user, $pass, null, 0) + : @drizzle_con_add_tcp( + $drizzle, $host, $port, $user, $pass, null, 0 + ); + if (!$conn) { + $error = __('Could not connect to Drizzle server'); + drizzle_free($drizzle); + break; + } + // connection object is set up but we have to send some query + // to actually connect + $res = @drizzle_query($conn, 'SELECT 1'); + if (!$res) { + $error = __('Could not connect to Drizzle server'); + } else { + drizzle_result_free($res); + } + drizzle_con_free($conn); + drizzle_free($drizzle); + break; + } + } else if ($extension == 'mysql') { + $conn = @mysql_connect($host . $socket . $port, $user, $pass); + if (!$conn) { + $error = __('Could not connect to MySQL server'); + } else { + mysql_close($conn); + } + } else { + $conn = @mysqli_connect($host, $user, $pass, null, $port, $socket); + if (!$conn) { + $error = __('Could not connect to MySQL server'); + } else { + mysqli_close($conn); + } + } + // test_php_errormsg(false); + if (isset($php_errormsg)) { + $error .= " - $php_errormsg"; + } + return is_null($error) ? true : array($error_key => $error); +} + +/** + * Validate server config + * + * @param string $path path to config, not used + * @param array $values config values + * + * @return array + */ +function validate_server($path, $values) +{ + $result = array( + 'Server' => '', + 'Servers/1/user' => '', + 'Servers/1/SignonSession' => '', + 'Servers/1/SignonURL' => '' + ); + $error = false; + if ($values['Servers/1/auth_type'] == 'config' + && empty($values['Servers/1/user']) + ) { + $result['Servers/1/user'] + = __('Empty username while using config authentication method'); + $error = true; + } + if ($values['Servers/1/auth_type'] == 'signon' + && empty($values['Servers/1/SignonSession']) + ) { + $result['Servers/1/SignonSession'] = __( + 'Empty signon session name ' + . 'while using signon authentication method' + ); + $error = true; + } + if ($values['Servers/1/auth_type'] == 'signon' + && empty($values['Servers/1/SignonURL']) + ) { + $result['Servers/1/SignonURL'] + = __('Empty signon URL while using signon authentication method'); + $error = true; + } + + if (!$error && $values['Servers/1/auth_type'] == 'config') { + $password = $values['Servers/1/nopassword'] ? null + : $values['Servers/1/password']; + $test = test_db_connection( + $values['Servers/1/extension'], + $values['Servers/1/connect_type'], + $values['Servers/1/host'], + $values['Servers/1/port'], + $values['Servers/1/socket'], + $values['Servers/1/user'], + $password, + 'Server' + ); + if ($test !== true) { + $result = array_merge($result, $test); + } + } + return $result; +} + +/** + * Validate pmadb config + * + * @param string $path path to config, not used + * @param array $values config values + * + * @return array + */ +function validate_pmadb($path, $values) +{ + $result = array( + 'Server_pmadb' => '', + 'Servers/1/controluser' => '', + 'Servers/1/controlpass' => '' + ); + $error = false; + + if ($values['Servers/1/pmadb'] == '') { + return $result; + } + + $result = array(); + if ($values['Servers/1/controluser'] == '') { + $result['Servers/1/controluser'] + = __('Empty phpMyAdmin control user while using pmadb'); + $error = true; + } + if ($values['Servers/1/controlpass'] == '') { + $result['Servers/1/controlpass'] + = __('Empty phpMyAdmin control user password while using pmadb'); + $error = true; + } + if (!$error) { + $test = test_db_connection( + $values['Servers/1/extension'], $values['Servers/1/connect_type'], + $values['Servers/1/host'], $values['Servers/1/port'], + $values['Servers/1/socket'], $values['Servers/1/controluser'], + $values['Servers/1/controlpass'], 'Server_pmadb' + ); + if ($test !== true) { + $result = array_merge($result, $test); + } + } + return $result; +} + + +/** + * Validates regular expression + * + * @param string $path path to config + * @param array $values config values + * + * @return array + */ +function validate_regex($path, $values) +{ + $result = array($path => ''); + + if ($values[$path] == '') { + return $result; + } + + test_php_errormsg(); + + $matches = array(); + // in libraries/List_Database.class.php _checkHideDatabase(), + // a '/' is used as the delimiter for hide_db + preg_match('/' . $values[$path] . '/', '', $matches); + + test_php_errormsg(false); + + if (isset($php_errormsg)) { + $error = preg_replace('/^preg_match\(\): /', '', $php_errormsg); + return array($path => $error); + } + + return $result; +} + +/** + * Validates TrustedProxies field + * + * @param string $path path to config + * @param array $values config values + * + * @return array + */ +function validate_trusted_proxies($path, $values) +{ + $result = array($path => array()); + + if (empty($values[$path])) { + return $result; + } + + if (is_array($values[$path])) { + // value already processed by FormDisplay::save + $lines = array(); + foreach ($values[$path] as $ip => $v) { + $lines[] = preg_match('/^-\d+$/', $ip) + ? $v + : $ip . ': ' . $v; + } + } else { + // AJAX validation + $lines = explode("\n", $values[$path]); + } + foreach ($lines as $line) { + $line = trim($line); + $matches = array(); + // we catch anything that may (or may not) be an IP + if (!preg_match("/^(.+):(?:[ ]?)\\w+$/", $line, $matches)) { + $result[$path][] = __('Incorrect value') . ': ' . htmlspecialchars($line); + continue; + } + // now let's check whether we really have an IP address + if (filter_var($matches[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false + && filter_var($matches[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false + ) { + $ip = htmlspecialchars(trim($matches[1])); + $result[$path][] = sprintf(__('Incorrect IP address: %s'), $ip); + continue; + } + } + + return $result; +} + +/** + * Tests integer value + * + * @param string $path path to config + * @param array $values config values + * @param bool $allow_neg allow negative values + * @param bool $allow_zero allow zero + * @param int $max_value max allowed value + * @param string $error_string error message key: + * $GLOBALS["strConfig$error_lang_key"] + * + * @return string empty string if test is successful + */ +function test_number( + $path, + $values, + $allow_neg, + $allow_zero, + $max_value, + $error_string +) { + if ($values[$path] === '') { + return ''; + } + + if (intval($values[$path]) != $values[$path] + || (!$allow_neg && $values[$path] < 0) + || (!$allow_zero && $values[$path] == 0) + || $values[$path] > $max_value + ) { + return $error_string; + } + + return ''; +} + +/** + * Validates port number + * + * @param string $path path to config + * @param array $values config values + * + * @return array + */ +function validate_port_number($path, $values) +{ + return array( + $path => test_number( + $path, + $values, + false, + false, + 65535, + __('Not a valid port number') + ) + ); +} + +/** + * Validates positive number + * + * @param string $path path to config + * @param array $values config values + * + * @return array + */ +function validate_positive_number($path, $values) +{ + return array( + $path => test_number( + $path, + $values, + false, + false, + PHP_INT_MAX, + __('Not a positive number') + ) + ); +} + +/** + * Validates non-negative number + * + * @param string $path path to config + * @param array $values config values + * + * @return array + */ +function validate_non_negative_number($path, $values) +{ + return array( + $path => test_number( + $path, + $values, + false, + true, + PHP_INT_MAX, + __('Not a non-negative number') + ) + ); +} + +/** + * Validates value according to given regular expression + * Pattern and modifiers must be a valid for PCRE <b>and</b> JavaScript RegExp + * + * @param string $path path to config + * @param array $values config values + * @param string $regex regullar expression to match + * + * @return array + */ +function validate_by_regex($path, $values, $regex) +{ + $result = preg_match($regex, $values[$path]); + return array($path => ($result ? '' : __('Incorrect value'))); +} + +/** + * Validates upper bound for numeric inputs + * + * @param string $path path to config + * @param array $values config values + * @param int $max_value maximal allowed value + * + * @return array + */ +function validate_upper_bound($path, $values, $max_value) +{ + $result = $values[$path] <= $max_value; + return array($path => ($result ? '' + : sprintf(__('Value must be equal or lower than %s'), $max_value))); +} +?> |
