parametrized validators

valdiation by regular expressions
shorter text fields for numeric inputs
This commit is contained in:
Crack
2010-07-17 11:39:30 +02:00
parent c5bef4d2da
commit afca401bc8
7 changed files with 107 additions and 83 deletions

View File

@@ -169,7 +169,9 @@ var validate = {};
// form validator list // form validator list
var validators = { var validators = {
// regexp: numeric value // regexp: numeric value
_regexp_numeric: new RegExp('^[0-9]+$'), _regexp_numeric: /^[0-9]+$/,
// regexp: extract parts from PCRE expression
_regexp_pcre_extract: /(.)(.*)\1(.*)?/,
/** /**
* Validates positive number * Validates positive number
* *
@@ -210,41 +212,20 @@ var validators = {
return result; return result;
}, },
/** /**
* DefaultPropDisplay validator * Validates value according to given regular expression
* *
* @param {boolean} isKeyUp * @param {boolean} isKeyUp
* @param {string} regexp
*/ */
validate_DefaultPropDisplay: function(isKeyUp) { validate_by_regex: function(isKeyUp, regexp) {
if (isKeyUp && this.value == '') { if (isKeyUp && this.value == '') {
return true; return true;
} }
var valid = this.value.match(/^(?:horizontal|vertical|[0-9]+)$/) != null; // convert PCRE regexp
var parts = regexp.match(validators._regexp_pcre_extract);
var valid = this.value.match(new RegExp(parts[2], parts[3])) != null;
return valid ? true : PMA_messages['error_invalid_value'] return valid ? true : PMA_messages['error_invalid_value']
}, },
/**
* Validates string length - must be 1 character long
*
* @param {boolean} isKeyUp
*/
validate_str1: function (isKeyUp) {
if (isKeyUp && this.value == '') {
return true;
}
var result = this.value.length == 1;
return result ? true : PMA_messages['error_invalid_value'];
},
/**
* Validates string length - must be 0 or 1 character long
*
* @param {boolean} isKeyUp
*/
validate_str01: function (isKeyUp) {
if (isKeyUp && this.value == '') {
return true;
}
var result = this.value.length <= 1;
return result ? true : PMA_messages['error_invalid_value'];
},
// field validators // field validators
_field: { _field: {
}, },
@@ -259,7 +240,7 @@ var validators = {
* @param {String} id field id * @param {String} id field id
* @param {String} type validator (key in validators object) * @param {String} type validator (key in validators object)
* @param {boolean} onKeyUp whether fire on key up * @param {boolean} onKeyUp whether fire on key up
* @param {object} params validation function parameters * @param {Array} params validation function parameters
*/ */
function validateField(id, type, onKeyUp, params) { function validateField(id, type, onKeyUp, params) {
if (typeof validators[type] == 'undefined') { if (typeof validators[type] == 'undefined') {
@@ -390,7 +371,11 @@ function validate_field(field, isKeyUp, errors) {
errors[field_id] = []; errors[field_id] = [];
var functions = getFieldValidators(field_id, isKeyUp); var functions = getFieldValidators(field_id, isKeyUp);
for (var i = 0; i < functions.length; i++) { for (var i = 0; i < functions.length; i++) {
var result = functions[i][0].apply(field[0], [isKeyUp, functions[i][1]]); var args = functions[i][1] != null
? functions[i][1].slice(0)
: [];
args.unshift(isKeyUp);
var result = functions[i][0].apply(field[0], args);
if (result !== true) { if (result !== true) {
if (typeof result == 'string') { if (typeof result == 'string') {
result = [result]; result = [result];

View File

@@ -27,6 +27,7 @@ $cfg_db['Servers'] = array(1 => array(
$cfg_db['RecodingEngine'] = array('auto', 'iconv', 'recode'); $cfg_db['RecodingEngine'] = array('auto', 'iconv', 'recode');
$cfg_db['DefaultCharset'] = $GLOBALS['cfg']['AvailableCharsets']; $cfg_db['DefaultCharset'] = $GLOBALS['cfg']['AvailableCharsets'];
$cfg_db['OBGzip'] = array('auto', true, false); $cfg_db['OBGzip'] = array('auto', true, false);
$cfg_db['MemoryLimit'] = 'short_string';
$cfg_db['ShowTooltipAliasTB'] = array('nested', true, false); $cfg_db['ShowTooltipAliasTB'] = array('nested', true, false);
$cfg_db['DisplayDatabasesList'] = array('auto', true, false); $cfg_db['DisplayDatabasesList'] = array('auto', true, false);
$cfg_db['LeftLogoLinkWindow'] = array('main', 'new'); $cfg_db['LeftLogoLinkWindow'] = array('main', 'new');
@@ -36,6 +37,8 @@ $cfg_db['LeftDefaultTabTable'] = array(
'tbl_select.php', // search page 'tbl_select.php', // search page
'tbl_change.php', // insert row page 'tbl_change.php', // insert row page
'sql.php'); // browse page 'sql.php'); // browse page
$cfg_db['LeftFrameDBSeparator'] = 'short_string';
$cfg_db['LeftFrameTableSeparator'] = 'short_string';
$cfg_db['NavigationBarIconic'] = array(true, false, 'both'); $cfg_db['NavigationBarIconic'] = array(true, false, 'both');
$cfg_db['Order'] = array('ASC', 'DESC', 'SMART'); $cfg_db['Order'] = array('ASC', 'DESC', 'SMART');
$cfg_db['ProtectBinary'] = array(false, 'blob', 'all'); $cfg_db['ProtectBinary'] = array(false, 'blob', 'all');
@@ -77,6 +80,12 @@ $cfg_db['Import']['sql_compatibility'] = $cfg_db['Export']['sql_compatibility']
// can't be read by POSTGRESQL (see our bug #1596328) // can't be read by POSTGRESQL (see our bug #1596328)
//'POSTGRESQL', //'POSTGRESQL',
'TRADITIONAL'); 'TRADITIONAL');
$cfg_db['Import']['csv_terminated'] = 'short_string';
$cfg_db['Import']['csv_enclosed'] = 'short_string';
$cfg_db['Import']['csv_escaped'] = 'short_string';
$cfg_db['Import']['ldi_terminated'] = 'short_string';
$cfg_db['Import']['ldi_enclosed'] = 'short_string';
$cfg_db['Import']['ldi_escaped'] = 'short_string';
$cfg_db['Import']['ldi_local_option'] = array('auto', true, false); $cfg_db['Import']['ldi_local_option'] = array('auto', true, false);
$cfg_db['Export']['format'] = array('codegen', 'csv', 'excel', 'htmlexcel', $cfg_db['Export']['format'] = array('codegen', 'csv', 'excel', 'htmlexcel',
'htmlword', 'latex', 'ods', 'odt', 'pdf', 'sql', 'texytext', 'xls', 'xml', 'htmlword', 'latex', 'ods', 'odt', 'pdf', 'sql', 'texytext', 'xls', 'xml',
@@ -84,9 +93,21 @@ $cfg_db['Export']['format'] = array('codegen', 'csv', 'excel', 'htmlexcel',
$cfg_db['Export']['compression'] = array('none', 'zip', 'gzip', 'bzip2'); $cfg_db['Export']['compression'] = array('none', 'zip', 'gzip', 'bzip2');
$cfg_db['Export']['charset'] = array_merge(array(''), $GLOBALS['cfg']['AvailableCharsets']); $cfg_db['Export']['charset'] = array_merge(array(''), $GLOBALS['cfg']['AvailableCharsets']);
$cfg_db['Export']['codegen_format'] = array('#', 'NHibernate C# DO', 'NHibernate XML'); $cfg_db['Export']['codegen_format'] = array('#', 'NHibernate C# DO', 'NHibernate XML');
$cfg_db['Export']['csv_separator'] = 'short_string';
$cfg_db['Export']['csv_terminated'] = 'short_string';
$cfg_db['Export']['csv_enclosed'] = 'short_string';
$cfg_db['Export']['csv_escaped'] = 'short_string';
$cfg_db['Export']['csv_null'] = 'short_string';
$cfg_db['Export']['excel_null'] = 'short_string';
$cfg_db['Export']['excel_edition'] = array('win' => 'Windows', $cfg_db['Export']['excel_edition'] = array('win' => 'Windows',
'mac_excel2003' => 'Excel 2003 / Macintosh', 'mac_excel2008' => 'Excel 2008 / Macintosh'); 'mac_excel2003' => 'Excel 2003 / Macintosh', 'mac_excel2008' => 'Excel 2008 / Macintosh');
$cfg_db['Export']['sql_type'] = array('INSERT', 'UPDATE', 'REPLACE'); $cfg_db['Export']['sql_type'] = array('INSERT', 'UPDATE', 'REPLACE');
$cfg_db['Export']['xls_null'] = 'short_string';
$cfg_db['Export']['xlsx_null'] = 'short_string';
$cfg_db['Export']['htmlword_null'] = 'short_string';
$cfg_db['Export']['ods_null'] = 'short_string';
$cfg_db['Export']['odt_null'] = 'short_string';
$cfg_db['Export']['texytext_null'] = 'short_string';
/** /**
* Default values overrides * Default values overrides
@@ -104,16 +125,16 @@ $cfg_db['_overrides']['Servers/1/extension'] = extension_loaded('mysqli')
$cfg_db['_validators'] = array( $cfg_db['_validators'] = array(
'CharTextareaCols' => 'validate_positive_number', 'CharTextareaCols' => 'validate_positive_number',
'CharTextareaRows' => 'validate_positive_number', 'CharTextareaRows' => 'validate_positive_number',
'DefaultPropDisplay' => 'validate_DefaultPropDisplay', 'DefaultPropDisplay' => array('validate_by_regex', '/^(?:horizontal|vertical|\d+)$/'),
'ExecTimeLimit' => 'validate_non_negative_number', 'ExecTimeLimit' => 'validate_non_negative_number',
'Export/sql_max_query_size' => 'validate_positive_number', 'Export/sql_max_query_size' => 'validate_positive_number',
'ForeignKeyMaxLimit' => 'validate_positive_number', 'ForeignKeyMaxLimit' => 'validate_positive_number',
'Import/csv_enclosed' => 'validate_str01', 'Import/csv_enclosed' => array('validate_by_regex', '/^.?$/'),
'Import/csv_escaped' => 'validate_str1', 'Import/csv_escaped' => array('validate_by_regex', '/^.$/'),
'Import/csv_terminated' => 'validate_str1', 'Import/csv_terminated' => array('validate_by_regex', '/^.$/'),
'Import/ldi_enclosed' => 'validate_str01', 'Import/ldi_enclosed' => array('validate_by_regex', '/^.?$/'),
'Import/ldi_escaped' => 'validate_str1', 'Import/ldi_escaped' => array('validate_by_regex', '/^.$/'),
'Import/ldi_terminated' => 'validate_str1', 'Import/ldi_terminated' => array('validate_by_regex', '/^.$/'),
'Import/skip_queries' => 'validate_non_negative_number', 'Import/skip_queries' => 'validate_non_negative_number',
'InsertRows' => 'validate_positive_number', 'InsertRows' => 'validate_positive_number',
'LeftFrameTableLevel' => 'validate_positive_number', 'LeftFrameTableLevel' => 'validate_positive_number',
@@ -124,7 +145,7 @@ $cfg_db['_validators'] = array(
'MaxCharactersInDisplayedSQL' => 'validate_positive_number', 'MaxCharactersInDisplayedSQL' => 'validate_positive_number',
'MaxRows' => 'validate_positive_number', 'MaxRows' => 'validate_positive_number',
'MaxTableList' => 'validate_positive_number', 'MaxTableList' => 'validate_positive_number',
'MemoryLimit' => 'validate_non_negative_number', 'MemoryLimit' => array('validate_by_regex', '/^\d+(?:[kmg])?$/i'),
'QueryHistoryMax' => 'validate_positive_number', 'QueryHistoryMax' => 'validate_positive_number',
'QueryWindowWidth' => 'validate_positive_number', 'QueryWindowWidth' => 'validate_positive_number',
'QueryWindowHeight' => 'validate_positive_number', 'QueryWindowHeight' => 'validate_positive_number',

View File

@@ -151,7 +151,7 @@ class FormDisplay
} }
// run validation // run validation
$errors = validate($paths, $values, false); $errors = PMA_config_validate($paths, $values, false);
// change error keys from canonical paths to work paths // change error keys from canonical paths to work paths
if (is_array($errors) && count($errors) > 0) { if (is_array($errors) && count($errors) > 0) {
@@ -259,10 +259,10 @@ class FormDisplay
foreach ($this->js_lang_strings as $strName => $strValue) { foreach ($this->js_lang_strings as $strName => $strValue) {
$js_lang[] = "'$strName': '" . PMA_jsFormat($strValue, false) . '\''; $js_lang[] = "'$strName': '" . PMA_jsFormat($strValue, false) . '\'';
} }
$js[] = '$.extend(PMA_messages, {' . implode(",\n\t", $js_lang) . '})'; $js[] = "$.extend(PMA_messages, {\n\t" . implode(",\n\t", $js_lang) . '})';
} }
$js[] = '$.extend(defaultValues, {' . implode(",\n\t", $js_default) . '})'; $js[] = "$.extend(defaultValues, {\n\t" . implode(",\n\t", $js_default) . '})';
display_js($js); display_js($js);
} }
@@ -309,11 +309,12 @@ class FormDisplay
case 'string': case 'string':
$type = 'text'; $type = 'text';
break; break;
case 'double': case 'short_string':
$type = 'text'; $type = 'short_text';
break; break;
case 'double':
case 'integer': case 'integer':
$type = 'text'; $type = 'number_text';
break; break;
case 'boolean': case 'boolean':
$type = 'checkbox'; $type = 'checkbox';
@@ -353,6 +354,8 @@ class FormDisplay
$js_line = '\'' . $translated_path . '\': '; $js_line = '\'' . $translated_path . '\': ';
switch ($type) { switch ($type) {
case 'text': case 'text':
case 'short_text':
case 'number_text':
$js_line .= '\'' . PMA_escapeJsString($value_default) . '\''; $js_line .= '\'' . PMA_escapeJsString($value_default) . '\'';
break; break;
case 'checkbox': case 'checkbox':
@@ -474,16 +477,17 @@ class FormDisplay
foreach ($form->fields as $field => $system_path) { foreach ($form->fields as $field => $system_path) {
$work_path = array_search($system_path, $this->system_paths); $work_path = array_search($system_path, $this->system_paths);
$key = $this->translated_paths[$work_path]; $key = $this->translated_paths[$work_path];
$type = $form->getOptionType($field);
// skip groups // skip groups
if ($form->getOptionType($field) == 'group') { if ($type == 'group') {
continue; continue;
} }
// ensure the value is set // ensure the value is set
if (!isset($_POST[$key])) { if (!isset($_POST[$key])) {
// checkboxes aren't set by browsers if they're off // checkboxes aren't set by browsers if they're off
if ($form->getOptionType($field) == 'boolean') { if ($type == 'boolean') {
$_POST[$key] = false; $_POST[$key] = false;
} else { } else {
$this->errors[$form->name][] = sprintf( $this->errors[$form->name][] = sprintf(
@@ -505,7 +509,6 @@ class FormDisplay
} }
// cast variables to correct type // cast variables to correct type
$type = $form->getOptionType($field);
switch ($type) { switch ($type) {
case 'double': case 'double':
settype($_POST[$key], 'float'); settype($_POST[$key], 'float');
@@ -524,6 +527,7 @@ class FormDisplay
} }
break; break;
case 'string': case 'string':
case 'short_string':
$_POST[$key] = trim($_POST[$key]); $_POST[$key] = trim($_POST[$key]);
break; break;
case 'array': case 'array':

View File

@@ -43,7 +43,8 @@ function display_form_top($action = null, $method = 'post', $hidden_fields = nul
* *
* @param array $tabs * @param array $tabs
*/ */
function display_tabs_top($tabs) { function display_tabs_top($tabs)
{
?> ?>
<ul class="tabs"> <ul class="tabs">
<?php foreach ($tabs as $tab_id => $tab_name): ?> <?php foreach ($tabs as $tab_id => $tab_name): ?>
@@ -163,7 +164,15 @@ function display_input($path, $name, $description = '', $type, $value, $value_is
<?php <?php
switch ($type) { switch ($type) {
case 'text': case 'text':
echo '<input type="text" size="50" ' . $name_id . $field_class echo '<input type="text" size="60" ' . $name_id . $field_class
. ' value="' . htmlspecialchars($value) . '" />';
break;
case 'short_text':
echo '<input type="text" size="25" ' . $name_id . $field_class
. ' value="' . htmlspecialchars($value) . '" />';
break;
case 'number_text':
echo '<input type="text" size="15" ' . $name_id . $field_class
. ' value="' . htmlspecialchars($value) . '" />'; . ' value="' . htmlspecialchars($value) . '" />';
break; break;
case 'checkbox': case 'checkbox':
@@ -318,7 +327,8 @@ function display_fieldset_bottom_simple()
/** /**
* Closes form tabs * Closes form tabs
*/ */
function display_tabs_bottom() { function display_tabs_bottom()
{
echo "</div>\n"; echo "</div>\n";
} }
@@ -337,8 +347,16 @@ function display_form_bottom()
* @param string $validator * @param string $validator
* @param array $js_array * @param array $js_array
*/ */
function js_validate($field_id, $validator, &$js_array) { function js_validate($field_id, $validator, &$js_array)
$js_array[] = "validateField('$field_id', '$validator', true)"; {
$validator = (array)$validator;
$v_name = array_shift($validator);
$v_args = array();
foreach ($validator as $arg) {
$v_args[] = PMA_escapeJsString($arg);
}
$v_args = $v_args ? ", ['" . implode("', '", $v_args) . "']" : '';
$js_array[] = "validateField('$field_id', '$v_name', true$v_args)";
} }
/** /**
@@ -346,7 +364,8 @@ function js_validate($field_id, $validator, &$js_array) {
* *
* @param array $js_array * @param array $js_array
*/ */
function display_js($js_array) { function display_js($js_array)
{
if (empty($js_array)) { if (empty($js_array)) {
return; return;
} }
@@ -363,7 +382,8 @@ function display_js($js_array) {
* @param string $name * @param string $name
* @param array $error_list * @param array $error_list
*/ */
function display_errors($name, $error_list) { function display_errors($name, $error_list)
{
echo '<dl>'; echo '<dl>';
echo '<dt>' . htmlspecialchars($name) . '</dt>'; echo '<dt>' . htmlspecialchars($name) . '</dt>';
foreach ($error_list as $error) { foreach ($error_list as $error) {

View File

@@ -30,7 +30,7 @@ $forms['Servers']['Server'] = array('Servers' => array(1 => array(
'connect_type', 'connect_type',
'extension', 'extension',
'compress', 'compress',
'auth_type', 'auth_type' => ':group',
'auth_http_realm', 'auth_http_realm',
'user', 'user',
'password', 'password',

View File

@@ -29,7 +29,7 @@
* @param bool $isPostSource tells whether $values are directly from POST request * @param bool $isPostSource tells whether $values are directly from POST request
* @return bool|array * @return bool|array
*/ */
function validate($validator_id, &$values, $isPostSource) function PMA_config_validate($validator_id, &$values, $isPostSource)
{ {
// find validators // find validators
$cf = ConfigFile::getInstance(); $cf = ConfigFile::getInstance();
@@ -59,7 +59,12 @@ function validate($validator_id, &$values, $isPostSource)
// validate // validate
$result = array(); $result = array();
foreach ($vids as $vid) { foreach ($vids as $vid) {
$r = call_user_func($validators[$vid], $vid, $arguments); // call appropriate validation function
$vdef = (array) $validators[$vid];
$vname = array_shift($vdef);
$args = array_merge(array($vid, &$arguments), $vdef);
$r = call_user_func_array($vname, $args);
// merge results // merge results
if (is_array($r)) { if (is_array($r)) {
foreach ($r as $key => $error_list) { foreach ($r as $key => $error_list) {
@@ -299,7 +304,6 @@ function validate_trusted_proxies($path, $values)
return $result; return $result;
} }
/** /**
* Tests integer value * Tests integer value
* *
@@ -361,41 +365,31 @@ function validate_non_negative_number($path, $values)
} }
/** /**
* Validates DefaultPropDisplay field * Validates value according to given regular expression
* Pattern and modifiers must be a valid for PCRE <b>and</b> JavaScript RegExp
* *
* @param string $path * @param string $path
* @param array $values * @param array $values
* @return array * @param string $regex
* @return void
*/ */
function validate_DefaultPropDisplay($path, $values) function validate_by_regex($path, $values, $regex)
{ {
$result = preg_match('/^(?:horizontal|vertical|\d+)$/', $values[$path]); $result = preg_match($regex, $values[$path]);
return array($path => ($result ? '' : __('Incorrect value'))); return array($path => ($result ? '' : __('Incorrect value')));
} }
/** /**
* Validates string length - must be 1 character long * Validates upper bound for numeric inputs
* *
* @param string $path * @param string $path
* @param array $values * @param array $values
* @param int $max_value
* @return array * @return array
*/ */
function validate_str1($path, $values) function validate_upper_bound($path, $values, $max_value)
{ {
$result = strlen($values[$path]) == 1; $result = $values[$path] <= $max_value;
return array($path => ($result ? '' : __('Incorrect value'))); return array($path => ($result ? '' : sprintf(__('Value must be equal or lower than %s'), $max_value)));
}
/**
* Validates string length - must be 0 or 1 character long
*
* @param string $path
* @param array $values
* @return array
*/
function validate_str01($path, $values)
{
$result = strlen($values[$path]) <= 1;
return array($path => ($result ? '' : __('Incorrect value')));
} }
?> ?>

View File

@@ -24,7 +24,7 @@ if (!($values instanceof stdClass)) {
die('Wrong data'); die('Wrong data');
} }
$values = (array)$values; $values = (array)$values;
$result = validate($vids, $values, true); $result = PMA_config_validate($vids, $values, true);
if ($result === false) { if ($result === false) {
$result = 'Wrong data or no validation for ' . $vids; $result = 'Wrong data or no validation for ' . $vids;
} }