Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
typo3
qfq
Commits
3bb338a2
Commit
3bb338a2
authored
Feb 02, 2018
by
Elias Villiger
Browse files
Feature #4542 - Working version with client- and server-side decimalFormat validation
parent
a52e56ed
Changes
6
Hide whitespace changes
Inline
Side-by-side
extension/qfq/qfq/AbstractBuildForm.php
View file @
3bb338a2
...
...
@@ -26,6 +26,7 @@ require_once(__DIR__ . '/helper/Support.php');
require_once
(
__DIR__
.
'/helper/OnArray.php'
);
require_once
(
__DIR__
.
'/helper/Ldap.php'
);
require_once
(
__DIR__
.
'/report/Link.php'
);
require_once
(
__DIR__
.
'/helper/Sanitize.php'
);
require_once
(
__DIR__
.
'/report/Report.php'
);
/**
...
...
@@ -41,7 +42,6 @@ abstract class AbstractBuildForm {
protected
$wrap
=
array
();
protected
$symbol
=
array
();
protected
$showDebugInfoFlag
=
false
;
protected
$inputCheckPattern
=
array
();
// protected $feDivClass = array(); // Wrap FormElements in <div class="$feDivClass[type]">
...
...
@@ -156,8 +156,6 @@ abstract class AbstractBuildForm {
$this
->
symbol
[
SYMBOL_SHOW
]
=
"<span class='glyphicon "
.
GLYPH_ICON_SHOW
.
"'></span>"
;
$this
->
symbol
[
SYMBOL_NEW
]
=
"<span class='glyphicon "
.
GLYPH_ICON_NEW
.
"'></span>"
;
$this
->
symbol
[
SYMBOL_DELETE
]
=
"<span class='glyphicon "
.
GLYPH_ICON_DELETE
.
"'></span>"
;
$this
->
inputCheckPattern
=
Sanitize
::
inputCheckPatternArray
();
}
abstract
public
function
fillWrap
();
...
...
@@ -1129,7 +1127,10 @@ abstract class AbstractBuildForm {
$attribute
.
=
$this
->
getAttributeList
(
$formElement
,
[
F_FE_DATA_PATTERN_ERROR
,
F_FE_DATA_REQUIRED_ERROR
,
F_FE_DATA_MATCH_ERROR
,
F_FE_DATA_ERROR
]);
$attribute
.
=
Support
::
doAttribute
(
'data-load'
,
(
$formElement
[
FE_DYNAMIC_UPDATE
]
===
'yes'
)
?
'data-load'
:
''
);
$attribute
.
=
Support
::
doAttribute
(
'title'
,
$formElement
[
FE_TOOLTIP
]);
$attribute
.
=
$this
->
getInputCheckPattern
(
$formElement
[
FE_CHECK_TYPE
],
$formElement
[
FE_CHECK_PATTERN
]);
$pattern
=
Sanitize
::
getInputCheckPattern
(
$formElement
[
FE_CHECK_TYPE
],
$formElement
[
FE_CHECK_PATTERN
],
$formElement
[
FE_DECIMAL_FORMAT
]);
$attribute
.
=
(
$pattern
===
''
)
?
''
:
'pattern="'
.
$pattern
.
'" '
;
$attribute
.
=
$this
->
getAttributeList
(
$formElement
,
[
FE_MIN
,
FE_MAX
]);
$attribute
.
=
$this
->
getAttributeFeMode
(
$formElement
[
FE_MODE
],
false
);
...
...
@@ -1374,47 +1375,6 @@ abstract class AbstractBuildForm {
return
$attribute
;
}
/**
* Construct HTML Input attribute for Client Validation:
*
* type data result
* ------- ----------------------- ----------------------------------------------------------------
* pattern <regexp> pattern="$data"
* digit - pattern="^[0-9]*$"
* email - pattern="^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$"
* alnumx -
*
* For 'pattern' the 'data' will be injected in the attribute string via '%s'.
*
* @param string $type
* @param string $data
*
* @return string
* @throws \qfq\UserFormException
*/
private
function
getInputCheckPattern
(
$type
,
$data
)
{
$attribute
=
''
;
if
(
$type
===
''
)
{
return
''
;
}
switch
(
$type
)
{
case
SANITIZE_ALLOW_PATTERN
:
$attribute
=
'pattern="'
.
$data
.
'" '
;
break
;
case
SANITIZE_ALLOW_ALL
:
break
;
default
:
$attribute
=
'pattern="'
.
$this
->
inputCheckPattern
[
$type
]
.
'" '
;
break
;
}
return
$attribute
;
}
/**
* Set corresponding html attributes readonly/required/disabled, based on $formElement[FE_MODE].
*
...
...
@@ -1642,44 +1602,6 @@ abstract class AbstractBuildForm {
return
$items
;
}
/**
* Get the size and decimal-point precision of a number from the table definition.
* Returns an array with the first item being the size, the second item being the precision.
* Returns null when no info found.
*
* @param string $column
*
* @return array
*/
public
function
getDecimalInfoFromTable
(
$column
)
{
// Get column definition
$fieldTypeDefinition
=
$this
->
store
->
getVar
(
$column
,
STORE_TABLE_COLUMN_TYPES
);
if
(
$fieldTypeDefinition
===
false
)
return
null
;
// not part of the table definition
$fieldTypeInfoArray
=
preg_split
(
"/[()]/"
,
$fieldTypeDefinition
);
switch
(
$fieldTypeInfoArray
[
0
])
{
case
'decimal'
:
case
'float'
:
case
'double'
:
case
'real'
:
$sizeAndPrecision
=
explode
(
","
,
$fieldTypeInfoArray
[
1
]);
return
[
$sizeAndPrecision
[
0
],
$sizeAndPrecision
[
1
]
];
case
'int'
:
case
'tinyint'
:
case
'smallint'
:
case
'mediumint'
:
case
'bigint'
:
return
[
$fieldTypeInfoArray
[
1
],
0
];
default
:
return
null
;
}
}
/**
* For CheckBox's with only one checkbox: if no parameter:checked|unchecked is defined, take defaults:
*
...
...
@@ -3181,7 +3103,10 @@ abstract class AbstractBuildForm {
$attribute
.
=
$this
->
getAttributeList
(
$formElement
,
[
FE_INPUT_AUTOCOMPLETE
,
'autofocus'
,
'placeholder'
]);
$attribute
.
=
Support
::
doAttribute
(
'data-load'
,
(
$formElement
[
FE_DYNAMIC_UPDATE
]
===
'yes'
)
?
'data-load'
:
''
);
$attribute
.
=
Support
::
doAttribute
(
'title'
,
$formElement
[
FE_TOOLTIP
]);
$attribute
.
=
$this
->
getInputCheckPattern
(
$formElement
[
FE_CHECK_TYPE
],
$formElement
[
FE_CHECK_PATTERN
]);
$pattern
=
Sanitize
::
getInputCheckPattern
(
$formElement
[
FE_CHECK_TYPE
],
$formElement
[
FE_CHECK_PATTERN
]);
$attribute
.
=
(
$pattern
===
''
)
?
''
:
'pattern="'
.
$pattern
.
'" '
;
$attribute
.
=
$this
->
getAttributeList
(
$formElement
,
[
FE_MIN
,
FE_MAX
]);
$json
=
$this
->
getFormElementForJson
(
$htmlFormElementName
,
$value
,
$formElement
);
...
...
extension/qfq/qfq/helper/Sanitize.php
View file @
3bb338a2
...
...
@@ -41,10 +41,40 @@ class Sanitize {
* @throws UserFormException
* @throws \qfq\CodeException
*/
public
static
function
sanitize
(
$value
,
$sanitizeClass
=
SANITIZE_DEFAULT
,
$pattern
=
''
,
$decimalFormat
=
null
,
$mode
=
SANITIZE_EMPTY_STRING
)
{
// Prepare pattern check
switch
(
$sanitizeClass
)
{
public
static
function
sanitize
(
$value
,
$sanitizeClass
=
SANITIZE_DEFAULT
,
$pattern
=
''
,
$decimalFormat
=
''
,
$mode
=
SANITIZE_EMPTY_STRING
)
{
$pattern
=
self
::
getInputCheckPattern
(
$sanitizeClass
,
$pattern
,
$decimalFormat
);
// Pattern check
if
(
$pattern
===
''
||
preg_match
(
"/
$pattern
/"
,
$value
)
===
1
)
{
return
$value
;
}
// check failed
if
(
$mode
===
SANITIZE_EXCEPTION
)
{
$errorCode
=
ERROR_PATTERN_VIOLATION
;
$errorText
=
"Value '
$value
' violates checkrule "
.
$sanitizeClass
.
" with pattern '
$pattern
'."
;
throw
new
UserFormException
(
$errorText
,
$errorCode
);
}
return
SANITIZE_VIOLATE
.
$sanitizeClass
.
SANITIZE_VIOLATE
;
}
/**
* Returns the final validation pattern based on a given $checkType, $pattern, and $decimalFormat
* @param string $checkType
* @param string $pattern
* @param string $decimalFormat e.g. "10,2"
*
* @return string
* @throws CodeException
*/
public
static
function
getInputCheckPattern
(
$checkType
=
SANITIZE_DEFAULT
,
$pattern
=
''
,
$decimalFormat
=
''
)
{
switch
(
$checkType
)
{
case
SANITIZE_ALLOW_PATTERN
:
return
$pattern
;
case
SANITIZE_ALLOW_ALL
:
$pattern
=
''
;
break
;
case
SANITIZE_ALLOW_DIGIT
:
...
...
@@ -53,37 +83,21 @@ class Sanitize {
case
SANITIZE_ALLOW_ALNUMX
:
case
SANITIZE_ALLOW_ALLBUT
:
$arr
=
self
::
inputCheckPatternArray
();
$pattern
=
$arr
[
$
sanitizeClass
];
$pattern
=
$arr
[
$
checkType
];
break
;
case
SANITIZE_ALLOW_ALL
:
// no checkType specified.
return
$value
;
default
:
throw
new
CodeException
(
"Unknown checkType: "
.
$
sanitizeClass
,
ERROR_UNKNOWN_CHECKTYPE
);
throw
new
CodeException
(
"Unknown checkType: "
.
$
checkType
,
ERROR_UNKNOWN_CHECKTYPE
);
}
// decimalFormat
if
(
$decimalFormat
!==
null
)
{
if
(
$sanitizeClass
!==
SANITIZE_ALLOW_PATTERN
&&
$sanitizeClass
!==
SANITIZE_ALLOW_DIGIT
)
{
// overwrite pattern
$pattern
=
self
::
getDecimalFormatPattern
(
$decimalFormat
);
}
}
// Pattern check
if
(
$pattern
===
''
||
preg_match
(
"/
$pattern
/"
,
$value
)
===
1
)
{
return
$value
;
}
// check failed
if
(
$mode
===
SANITIZE_EXCEPTION
)
{
$errorCode
=
ERROR_PATTERN_VIOLATION
;
$errorText
=
"Value '
$value
' violates checkrule "
.
$sanitizeClass
.
" with pattern '
$pattern
'."
;
throw
new
UserFormException
(
$errorText
,
$errorCode
);
if
(
$decimalFormat
!=
''
&&
$checkType
!==
SANITIZE_ALLOW_DIGIT
)
{
// overwrite pattern with decimalFormat pattern
$decimalFormatArray
=
explode
(
','
,
$decimalFormat
);
$pattern
=
"^[0-9]
{
0,$decimalFormatArray[0]}(\.[0-9]{0,$decimalFormatArray[1]
}
)?$"
;
}
return
SANITIZE_VIOLATE
.
$sanitizeClass
.
SANITIZE_VIOLATE
;
return
$pattern
;
}
/**
...
...
@@ -98,9 +112,7 @@ class Sanitize {
* @throws UserFormException
* @throws \qfq\CodeException
*/
public
static
function
checkMinMax
(
$value
,
$formElement
,
$mode
=
SANITIZE_EMPTY_STRING
)
{
$min
=
Support
::
setIfNotSet
(
$formElement
,
FE_MIN
);
$max
=
Support
::
setIfNotSet
(
$formElement
,
FE_MAX
);
public
static
function
checkMinMax
(
$value
,
$min
,
$max
,
$mode
=
SANITIZE_EMPTY_STRING
)
{
$errorCode
=
0
;
$errorText
=
''
;
...
...
@@ -124,17 +136,6 @@ class Sanitize {
return
''
;
}
/**
* Returns the regexp pattern to match a decimal number with the format in $decimalFormat.
*
* @param array $decimalFormat with [ size, precision ]
*
* @return string
*/
public
static
function
getDecimalFormatPattern
(
$decimalFormat
)
{
return
"^[0-9]
{
0,$decimalFormat[0]}(\.[0-9]{0,$decimalFormat[1]
}
)?$"
;
}
/**
* @return array
*/
...
...
@@ -152,7 +153,7 @@ class Sanitize {
}
/**
* San
a
tizes a filename. Copied from http://www.phpit.net/code/filename-safe/
* San
i
tizes a filename. Copied from http://www.phpit.net/code/filename-safe/
*
* @param $filename
*
...
...
extension/qfq/qfq/helper/Support.php
View file @
3bb338a2
...
...
@@ -767,6 +767,27 @@ class Support {
break
;
}
self
::
setIfNotSet
(
$formElement
,
FE_MIN
);
self
::
setIfNotSet
(
$formElement
,
FE_MAX
);
// decimalFormat
if
(
isset
(
$formElement
[
FE_DECIMAL_FORMAT
]))
{
if
(
$formElement
[
FE_DECIMAL_FORMAT
]
===
''
)
{
// Get decimal format from column definition
$fieldTypeDefinition
=
$store
->
getVar
(
$formElement
[
FE_NAME
],
STORE_TABLE_COLUMN_TYPES
);
if
(
$fieldTypeDefinition
!==
false
)
{
$fieldTypeInfoArray
=
preg_split
(
"/[()]/"
,
$fieldTypeDefinition
);
if
(
$fieldTypeInfoArray
[
0
]
===
'decimal'
)
$formElement
[
FE_DECIMAL_FORMAT
]
=
$fieldTypeInfoArray
[
1
];
}
}
else
{
// Decimal format is defined in parameter field
if
(
!
preg_match
(
"/^[0-9]+,[0-9]+$/"
,
$formElement
[
FE_DECIMAL_FORMAT
]))
throw
new
UserFormException
(
"Invalid decimalFormat."
,
ERROR_INVALID_DECIMAL_FORMAT
);
}
}
self
::
setIfNotSet
(
$formElement
,
FE_DECIMAL_FORMAT
);
return
$formElement
;
}
...
...
extension/qfq/qfq/store/FillStoreForm.php
View file @
3bb338a2
...
...
@@ -237,28 +237,10 @@ class FillStoreForm {
$val
=
Support
::
unWrapTag
(
'<p>'
,
$val
);
}
$decimalFormat
=
null
;
if
(
isset
(
$formElement
[
FE_DECIMAL_FORMAT
]))
{
// Read decimal format from parameter field
if
(
preg_match
(
"/^([0-9]*)(,[0-9]+)?$"
,
$formElement
[
FE_DECIMAL_FORMAT
])
&&
$formElement
[
FE_DECIMAL_FORMAT
]
!=
''
)
{
$decimalFormat
=
explode
(
','
,
$formElement
[
FE_DECIMAL_FORMAT
]);
if
(
$decimalFormat
[
0
]
===
''
)
$decimalFormat
[
0
]
=
10
;
// default size
if
(
count
(
$decimalFormat
)
==
1
)
$decimalFormat
[
1
]
=
2
;
// default precision
}
else
{
throw
new
UserFormException
(
"Invalid decimalFormat."
,
ERROR_INVALID_DECIMAL_FORMAT
);
}
}
else
{
// Get decimal format from column definition
$decimalFormat
=
AbstractBuildForm
::
getDecimalInfoFromTable
(
$formElement
[
FE_NAME
]);
}
// Check only if there is something.
if
(
$val
!==
''
)
{
$val
=
Sanitize
::
sanitize
(
$val
,
$formElement
[
FE_CHECK_TYPE
],
$formElement
[
FE_CHECK_PATTERN
],
$
decimalFormat
,
SANITIZE_EXCEPTION
);
$
formElement
[
FE_DECIMAL_FORMAT
]
,
SANITIZE_EXCEPTION
);
if
(
$formElement
[
FE_ENCODE
]
===
FE_ENCODE_SPECIALCHAR
)
{
// $val = htmlspecialchars($val, ENT_QUOTES);
$val
=
Support
::
htmlEntityEncodeDecode
(
MODE_ENCODE
,
$val
);
...
...
@@ -268,7 +250,7 @@ class FillStoreForm {
}
if
(
$val
!==
''
)
$val
=
Sanitize
::
checkMinMax
(
$val
,
$formElement
,
SANITIZE_EXCEPTION
);
$val
=
Sanitize
::
checkMinMax
(
$val
,
$formElement
[
FE_MIN
],
$formElement
[
FE_MAX
]
,
SANITIZE_EXCEPTION
);
$newValues
[
$formElement
[
FE_NAME
]]
=
$val
;
}
...
...
extension/qfq/qfq/store/Store.php
View file @
3bb338a2
...
...
@@ -478,7 +478,7 @@ class Store {
$sanitizeClass
=
SANITIZE_ALLOW_ALL
;
}
return
\
qfq\Sanitize
::
sanitize
(
$rawVal
,
$sanitizeClass
,
''
,
null
,
SANITIZE_EMPTY_STRING
);
return
\
qfq\Sanitize
::
sanitize
(
$rawVal
,
$sanitizeClass
,
''
,
''
,
SANITIZE_EMPTY_STRING
);
}
else
{
if
(
$store
==
STORE_SIP
&&
(
substr
(
$key
,
0
,
$len
)
==
SIP_PREFIX_BASE64
))
{
$rawVal
=
base64_decode
(
$rawVal
);
...
...
extension/qfq/tests/phpunit/SanitizeTest.php
View file @
3bb338a2
...
...
@@ -94,19 +94,19 @@ class SanitizeTest extends \PHPUnit_Framework_TestCase {
# Check numerical min/max
$val
=
56
;
$this
->
assertEquals
(
''
,
Sanitize
::
checkMinMax
(
$val
,
[
FE_MIN
=>
"0"
,
FE_MAX
=>
"2"
]
),
$msg
);
$this
->
assertEquals
(
$val
,
Sanitize
::
checkMinMax
(
$val
,
[
FE_MIN
=>
"0"
]
),
$msg
);
$this
->
assertEquals
(
$val
,
Sanitize
::
checkMinMax
(
$val
,
[
FE_MAX
=>
"56"
]
),
$msg
);
$this
->
assertEquals
(
''
,
Sanitize
::
checkMinMax
(
$val
,
"0"
,
"2"
),
$msg
);
$this
->
assertEquals
(
$val
,
Sanitize
::
checkMinMax
(
$val
,
"0"
,
""
),
$msg
);
$this
->
assertEquals
(
$val
,
Sanitize
::
checkMinMax
(
$val
,
""
,
"56"
),
$msg
);
$this
->
assertEquals
(
''
,
Sanitize
::
checkMinMax
(
$val
,
[
FE_MIN
=>
"57"
]
),
$msg
);
$this
->
assertEquals
(
''
,
Sanitize
::
checkMinMax
(
$val
,
[
FE_MAX
=>
"2"
]
),
$msg
);
$this
->
assertEquals
(
$val
,
Sanitize
::
checkMinMax
(
$val
,
[
FE_MIN
=>
"0"
,
FE_MAX
=>
"200"
]
),
$msg
);
$this
->
assertEquals
(
$val
,
Sanitize
::
checkMinMax
(
$val
,
[
FE_MIN
=>
"-100"
,
FE_MAX
=>
"200"
]
),
$msg
);
$this
->
assertEquals
(
''
,
Sanitize
::
checkMinMax
(
$val
,
"57"
,
""
),
$msg
);
$this
->
assertEquals
(
''
,
Sanitize
::
checkMinMax
(
$val
,
""
,
"2"
),
$msg
);
$this
->
assertEquals
(
$val
,
Sanitize
::
checkMinMax
(
$val
,
"0"
,
"200"
),
$msg
);
$this
->
assertEquals
(
$val
,
Sanitize
::
checkMinMax
(
$val
,
"-100"
,
"200"
),
$msg
);
$val
=
-
56
;
$this
->
assertEquals
(
''
,
Sanitize
::
checkMinMax
(
$val
,
[
FE_MIN
=>
"0"
,
FE_MAX
=>
"2"
]
),
$msg
);
$this
->
assertEquals
(
''
,
Sanitize
::
checkMinMax
(
$val
,
[
FE_MIN
=>
"0"
,
FE_MAX
=>
"200"
]
),
$msg
);
$this
->
assertEquals
(
$val
,
Sanitize
::
checkMinMax
(
$val
,
[
FE_MIN
=>
"-100"
,
FE_MAX
=>
"200"
]
),
$msg
);
$this
->
assertEquals
(
''
,
Sanitize
::
checkMinMax
(
$val
,
"0"
,
"2"
),
$msg
);
$this
->
assertEquals
(
''
,
Sanitize
::
checkMinMax
(
$val
,
"0"
,
"200"
),
$msg
);
$this
->
assertEquals
(
$val
,
Sanitize
::
checkMinMax
(
$val
,
"-100"
,
"200"
),
$msg
);
# Check min/max dates
$msg
=
"SANITIZE_MIN_MAX Date fails"
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment