diff --git a/setup/lang/english-utf-8.inc.php b/setup/lang/english-utf-8.inc.php index 0d114c831..7eb72bc32 100644 --- a/setup/lang/english-utf-8.inc.php +++ b/setup/lang/english-utf-8.inc.php @@ -79,6 +79,7 @@ $str['error_form'] = 'Submitted form contains errors'; $str['error_missing_field_data'] = 'Missing data for %s'; $str['error_incorrect_port'] = 'Not a valid port number'; $str['error_incorrect_value'] = 'Incorrect value'; +$str['error_incorrect_ip_address'] = 'Incorrect IP address: %s'; $str['error_nan_p'] = 'Not a positive number'; $str['error_nan_nneg'] = 'Not a non-negative number'; $str['error_empty_pmadb_user'] = 'Empty phpMyAdmin control user while using pmadb'; @@ -240,6 +241,7 @@ $str['ForceSSL_name'] = 'Force SSL connection'; $str['ForceSSL_desc'] = 'Force secured connection while using phpMyAdmin'; $str['CheckConfigurationPermissions_name'] = 'Check config file permissions'; $str['TrustedProxies_name'] = 'List of trusted proxies for IP allow/deny'; +$str['TrustedProxies_desc'] = 'Input proxies as [kbd]IP: trusted HTTP header[/kbd]. The following example specifies that phpMyAdmin should trust a HTTP_X_FORWARDED_FOR (X-Forwarded-For) header coming from the proxy 1.2.3.4:[br][kbd]1.2.3.4: HTTP_X_FORWARDED_FOR[/kbd]'; $str['AllowUserDropDatabase_name'] = 'Show "Drop database" link to normal users'; $str['AllowArbitraryServer_name'] = 'Allow login to any MySQL server'; $str['AllowArbitraryServer_desc'] = 'If enabled user can enter any MySQL server in login form for cookie auth'; diff --git a/setup/lib/FormDisplay.class.php b/setup/lib/FormDisplay.class.php index 5acb0e884..737b05e50 100644 --- a/setup/lib/FormDisplay.class.php +++ b/setup/lib/FormDisplay.class.php @@ -295,6 +295,15 @@ class FormDisplay break; } + // TrustedProxies requires changes before displaying + if ($system_path == 'TrustedProxies') { + foreach ($value as $ip => &$v) { + if (!preg_match('/^-\d+$/', $ip)) { + $v = $ip . ': ' . $v; + } + } + } + // send default value to form's JS $js_line = '\'' . $translated_path . '\': '; switch ($type) { @@ -473,6 +482,24 @@ class FormDisplay // save forms if ($allow_partial_save || empty($this->errors)) { foreach ($to_save as $work_path => $path) { + // TrustedProxies requires changes before saving + if ($path == 'TrustedProxies') { + $proxies = array(); + $i = 0; + foreach ($values[$path] as $value) { + $matches = array(); + if (preg_match("/^(.+):(?:[ ]?)(\\w+)$/", $value, $matches)) { + // correct 'IP: HTTP header' pair + $ip = trim($matches[1]); + $proxies[$ip] = trim($matches[2]); + } else { + // save also incorrect values + $proxies["-$i"] = $value; + $i++; + } + } + $values[$path] = $proxies; + } $cf->set($work_path, $values[$path], $path); } } diff --git a/setup/lib/common.inc.php b/setup/lib/common.inc.php index 13d52779d..e6da3b46b 100644 --- a/setup/lib/common.inc.php +++ b/setup/lib/common.inc.php @@ -197,10 +197,10 @@ function PMA_lang($lang_key) */ function PMA_lang_name($canonical_path) { - $lang_key = str_replace('Servers/1/', 'Servers/', $canonical_path) . '_name'; + $lang_key = str_replace('Servers/1/', 'Servers/', $canonical_path) . '_name'; return isset($GLOBALS['str'][$lang_key]) - ? $GLOBALS['str'][$lang_key] - : $lang_key; + ? $GLOBALS['str'][$lang_key] + : $lang_key; } /** @@ -211,10 +211,10 @@ function PMA_lang_name($canonical_path) */ function PMA_lang_desc($canonical_path) { - $lang_key = str_replace('Servers/1/', 'Servers/', $canonical_path) . '_desc'; + $lang_key = str_replace('Servers/1/', 'Servers/', $canonical_path) . '_desc'; return isset($GLOBALS['str'][$lang_key]) - ? $GLOBALS['str'][$lang_key] - : ''; + ? PMA_lang($lang_key) + : ''; } /** diff --git a/setup/lib/config_info.inc.php b/setup/lib/config_info.inc.php index 614d0f149..edccba6a9 100644 --- a/setup/lib/config_info.inc.php +++ b/setup/lib/config_info.inc.php @@ -110,7 +110,7 @@ $persist_keys = array( */ $cfg_db['_overrides'] = array(); $cfg_db['_overrides']['Servers/1/extension'] = extension_loaded('mysqli') - ? 'mysqli' : 'mysql'; + ? 'mysqli' : 'mysql'; /** * Validator assignments (functions from validate.lib.php and 'validators' @@ -122,9 +122,10 @@ $cfg_db['_validators'] = array( 'Server_pmadb' => 'validate_pmadb', 'Servers/1/port' => 'validate_port_number', 'Servers/1/hide_db' => 'validate_regex', + 'TrustedProxies' => 'validate_trusted_proxies', 'LoginCookieValidity' => 'validate_positive_number', 'LoginCookieStore' => 'validate_non_negative_number', - 'QueryHistoryMax' => 'validate_positive_number', + 'QueryHistoryMax' => 'validate_positive_number', 'LeftFrameTableLevel' => 'validate_positive_number', 'MaxRows' => 'validate_positive_number', 'CharTextareaCols' => 'validate_positive_number', diff --git a/setup/lib/validate.lib.php b/setup/lib/validate.lib.php index 4b8265792..3b0c3fae5 100644 --- a/setup/lib/validate.lib.php +++ b/setup/lib/validate.lib.php @@ -8,8 +8,8 @@ * 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_info.inc.php). + * + * Valdiation functions are assigned in $cfg_db['_validators'] (config_info.inc.php). * * @package phpMyAdmin-setup * @author Piotr Przybylski @@ -19,7 +19,7 @@ /** * 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 @@ -252,6 +252,54 @@ function validate_regex($path, $values) return $result; } +/** + * Validates TrustedProxies field + * + * @param string $path + * @param array $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][] = PMA_lang('error_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][] = PMA_lang('error_incorrect_ip_address', $ip); + continue; + } + } + + return $result; +} + + /** * Tests integer value * diff --git a/setup/scripts.js b/setup/scripts.js index 5f0a75aaf..16b05681f 100644 --- a/setup/scripts.js +++ b/setup/scripts.js @@ -241,7 +241,20 @@ var validators = { ajaxValidate(this, 'Servers/1/hide_db', data); } return true; - } + }, + /** + * TrustedProxies field + * + * @param boolean isKeyUp + */ + TrustedProxies: function(isKeyUp) { + if (!isKeyUp && this.value != '') { + var data = {}; + data[this.id] = this.value; + ajaxValidate(this, 'TrustedProxies', data); + } + return true; + }, }, // fieldset validators _fieldset: {