diff --git a/libraries/config.values.php b/libraries/config.values.php index 4a496296c8..da9cce8dfb 100644 --- a/libraries/config.values.php +++ b/libraries/config.values.php @@ -193,7 +193,7 @@ $cfg_db['_overrides']['Servers/1/extension'] = extension_loaded('mysqli') ? 'mysqli' : 'mysql'; /** - * Basic validator assignments (functions from libraries/config/validate.lib.php + * Basic validator assignments (functions from libraries/config/Validator.class.php * and 'validators' object in js/config.js) * Use only full paths and form ids */ diff --git a/libraries/config/FormDisplay.class.php b/libraries/config/FormDisplay.class.php index 7cc7fdac98..3b155ff4e8 100644 --- a/libraries/config/FormDisplay.class.php +++ b/libraries/config/FormDisplay.class.php @@ -17,7 +17,7 @@ * Core libraries. */ require_once './libraries/config/FormDisplay.tpl.php'; -require_once './libraries/config/validate.lib.php'; +require_once './libraries/config/Validator.class.php'; require_once './libraries/js_escape.lib.php'; /** @@ -91,7 +91,7 @@ class FormDisplay 'error_invalid_value' => __('Incorrect value'), 'error_value_lte' => __('Value must be equal or lower than %s')); // initialize validators - PMA_config_get_validators(); + PMA_Validator::config_get_validators(); } /** @@ -164,7 +164,7 @@ class FormDisplay } // run validation - $errors = PMA_config_validate($paths, $values, false); + $errors = PMA_Validator::config_validate($paths, $values, false); // change error keys from canonical paths to work paths if (is_array($errors) && count($errors) > 0) { @@ -198,7 +198,7 @@ class FormDisplay $js = array(); $js_default = array(); $tabbed_form = $tabbed_form && (count($this->_forms) > 1); - $validators = PMA_config_get_validators(); + $validators = PMA_Validator::config_get_validators(); PMA_displayFormTop(); diff --git a/libraries/config/FormDisplay.tpl.php b/libraries/config/FormDisplay.tpl.php index f0e0318745..8203ce3d22 100644 --- a/libraries/config/FormDisplay.tpl.php +++ b/libraries/config/FormDisplay.tpl.php @@ -133,6 +133,10 @@ function PMA_displayInput($path, $name, $type, $value, $description = '', global $_FormDisplayGroup; static $icons; // An array of IMG tags used further below in the function + if (defined('TESTSUITE')) { + $icons = null; + } + $is_setup_script = defined('PMA_SETUP'); if ($icons === null) { // if the static variables have not been initialised $icons = array(); diff --git a/libraries/config/Validator.class.php b/libraries/config/Validator.class.php new file mode 100644 index 0000000000..2cfed3da7c --- /dev/null +++ b/libraries/config/Validator.class.php @@ -0,0 +1,587 @@ +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 + */ + public static function config_validate($validator_id, &$values, $isPostSource) + { + // find validators + $validator_id = (array) $validator_id; + $validators = static::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 + */ + public static function 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 + */ + public static function testPHPErrorMsg($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_Validator", "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 + */ + public static function testDBConnection( + $extension, + $connect_type, + $host, + $port, + $socket, + $user, + $pass = null, + $error_key = 'Server' + ) { + // static::testPHPErrorMsg(); + $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); + } + } + // static::testPHPErrorMsg(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 + */ + public static function validateServer($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 = static::testDBConnection( + $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 + */ + public static function validatePMAStorage($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 = static::testDBConnection( + $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 + */ + public static function validateRegex($path, $values) + { + $result = array($path => ''); + + if ($values[$path] == '') { + return $result; + } + + static::testPHPErrorMsg(); + + $matches = array(); + // in libraries/List_Database.class.php _checkHideDatabase(), + // a '/' is used as the delimiter for hide_db + preg_match('/' . $values[$path] . '/', '', $matches); + + static::testPHPErrorMsg(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 + */ + public static function validateTrustedProxies($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:') . ' ' . $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 + */ + public static function validateNumber( + $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 + */ + public static function validatePortNumber($path, $values) + { + return array( + $path => static::validateNumber( + $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 + */ + public static function validatePositiveNumber($path, $values) + { + return array( + $path => static::validateNumber( + $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 + */ + public static function validateNonNegativeNumber($path, $values) + { + return array( + $path => static::validateNumber( + $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 and JavaScript RegExp + * + * @param string $path path to config + * @param array $values config values + * @param string $regex regullar expression to match + * + * @return array + */ + public static function validateByRegex($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 + */ + public static function validateUpperBound($path, $values, $max_value) + { + $result = $values[$path] <= $max_value; + return array($path => ($result ? '' + : sprintf(__('Value must be equal or lower than %s'), $max_value))); + } +} +?> diff --git a/libraries/config/validate.lib.php b/libraries/config/validate.lib.php deleted file mode 100644 index 08092e621e..0000000000 --- a/libraries/config/validate.lib.php +++ /dev/null @@ -1,584 +0,0 @@ -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 PMA_testPHPErrorMsg($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 PMA_testDBConnection( - $extension, - $connect_type, - $host, - $port, - $socket, - $user, - $pass = null, - $error_key = 'Server' -) { - // PMA_testPHPErrorMsg(); - $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); - } - } - // PMA_testPHPErrorMsg(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 PMA_validateServer($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 = PMA_testDBConnection( - $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 PMA_validatePMAStorage($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 = PMA_testDBConnection( - $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 PMA_validateRegex($path, $values) -{ - $result = array($path => ''); - - if ($values[$path] == '') { - return $result; - } - - PMA_testPHPErrorMsg(); - - $matches = array(); - // in libraries/List_Database.class.php _checkHideDatabase(), - // a '/' is used as the delimiter for hide_db - preg_match('/' . $values[$path] . '/', '', $matches); - - PMA_testPHPErrorMsg(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 PMA_validateTrustedProxies($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:') . ' ' . $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 PMA_validateNumber( - $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 PMA_validatePortNumber($path, $values) -{ - return array( - $path => PMA_validateNumber( - $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 PMA_validatePositiveNumber($path, $values) -{ - return array( - $path => PMA_validateNumber( - $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 PMA_validateNonNegativeNumber($path, $values) -{ - return array( - $path => PMA_validateNumber( - $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 and JavaScript RegExp - * - * @param string $path path to config - * @param array $values config values - * @param string $regex regullar expression to match - * - * @return array - */ -function PMA_validateByRegex($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 PMA_validateUpperBound($path, $values, $max_value) -{ - $result = $values[$path] <= $max_value; - return array($path => ($result ? '' - : sprintf(__('Value must be equal or lower than %s'), $max_value))); -} -?> diff --git a/setup/validate.php b/setup/validate.php index 2cb8c93ca8..393af94deb 100644 --- a/setup/validate.php +++ b/setup/validate.php @@ -12,7 +12,7 @@ require './lib/common.inc.php'; $validators = array(); -require './libraries/config/validate.lib.php'; +require './libraries/config/Validator.class.php'; header('Content-type: application/json'); @@ -22,7 +22,7 @@ if (!($values instanceof stdClass)) { PMA_fatalError(__('Wrong data')); } $values = (array)$values; -$result = PMA_config_validate($vids, $values, true); +$result = PMA_Validator::config_validate($vids, $values, true); if ($result === false) { $result = 'Wrong data or no validation for ' . $vids; } diff --git a/test/classes/config/PMA_FormDisplay_test.php b/test/classes/config/PMA_FormDisplay_test.php new file mode 100644 index 0000000000..1e682b22de --- /dev/null +++ b/test/classes/config/PMA_FormDisplay_test.php @@ -0,0 +1,593 @@ +getPath(); + $GLOBALS['pmaThemeImage'] = 'theme/'; + $GLOBALS['PMA_Config'] = new PMA_Config(); + $GLOBALS['PMA_Config']->enableBc(); + $GLOBALS['server'] = 0; + $this->object = new FormDisplay(); + } + + /** + * tearDown for test cases + * + * @return void + */ + protected function tearDown() + { + unset($this->object); + } + + /** + * Test for FormDisplay::__constructor + * + * @return void + */ + public function testFormDisplayContructor() + { + $this->assertCount( + 5, + $this->readAttribute($this->object, '_jsLangStrings') + ); + } + + /** + * Test for FormDisplay::registerForm + * + * @return void + */ + public function testRegisterForm() + { + $reflection = new \ReflectionClass('FormDisplay'); + + $attrForms = $reflection->getProperty('_forms'); + $attrForms->setAccessible(true); + + $array = array( + "Servers" => array( + "1" => array( + 'test' => 1, + 1 => ':group:end' + ) + ) + ); + + $this->object->registerForm('pma_testform', $array, 2); + $_forms = $attrForms->getValue($this->object); + $this->assertInstanceOf( + 'Form', + $_forms['pma_testform'] + ); + + $this->assertEquals( + array( + "Servers/2/test" => "Servers/1/test", + "Servers/2/:group:end:0" => "Servers/1/:group:end:0" + ), + $this->readAttribute($this->object, '_systemPaths') + ); + + $this->assertEquals( + array( + "Servers/2/test" => "Servers-2-test", + "Servers/2/:group:end:0" => "Servers-2-:group:end:0" + ), + $this->readAttribute($this->object, '_translatedPaths') + ); + } + + /** + * Test for FormDisplay::process + * + * @return void + */ + public function testProcess() + { + $this->assertFalse( + $this->object->process(true, true) + ); + + $this->object = $this->getMockBuilder('FormDisplay') + ->disableOriginalConstructor() + ->setMethods(array('save')) + ->getMock(); + + $attrForms = new \ReflectionProperty('FormDisplay', '_forms'); + $attrForms->setAccessible(true); + $attrForms->setValue($this->object, array(1, 2, 3)); + + $this->object->expects($this->once()) + ->method('save') + ->with(array(0, 1, 2), false) + ->will($this->returnValue(true)); + + $this->assertTrue( + $this->object->process(false, false) + ); + + $attrForms->setValue($this->object, array()); + + $this->assertFalse( + $this->object->process(false, false) + ); + } + + /** + * Test for FormDisplay::displayErrors + * + * @return void + */ + public function testDisplayErrors() + { + $reflection = new \ReflectionClass('FormDisplay'); + + $attrIsValidated = $reflection->getProperty('_isValidated'); + $attrIsValidated->setAccessible(true); + $attrIsValidated->setValue($this->object, true); + + $attrIsValidated = $reflection->getProperty('_errors'); + $attrIsValidated->setAccessible(true); + $attrIsValidated->setValue($this->object, array()); + + $this->assertNull( + $this->object->displayErrors() + ); + + $arr = array( + "Servers/1/test" => array('e1'), + "foobar" => array('e2', 'e3') + ); + + $sysArr = array( + "Servers/1/test" => "Servers/1/test2" + ); + + $attrSystemPaths = $reflection->getProperty('_systemPaths'); + $attrSystemPaths->setAccessible(true); + $attrSystemPaths->setValue($this->object, $sysArr); + + $attrIsValidated->setValue($this->object, $arr); + + $GLOBALS['strConfigForm_foobar'] = 'foobar123'; + + $this->expectOutputString( + '