Is there a way in which one can filter data that is auto-completed in a form generated by VOLT.
Consider the login form: Email/password.
When I edit the HTML (in the broser) and send the email as an array ('name="email[]") I can sanitize it in PHP and 'cast' as en email:
$loginEmail = $this->request->getPost("email",'string');
$loginEmail = $this->filter->sanitize($loginEmail, "email");
in order to prevent other attacks.
But when making the email field an array VOLT generates an error:
"Notice: Array to string conversion in ..."
VOLT form values are populated automatically...
I know I should disable NOTICES in production but still...
How can I treat this by using VOLT?
EDIT
Template sample:
{{ text_field('id':"email","class":"form-control", "size": 32,"placeholder":'Email address') }}
After a var_dump and setting the email string through validation I get at a certain point:
protected '_viewParams' =>
array (size=5)
'title' => string 'Test' (length=5)
'showSlider' => boolean true
'hideUnlogged' => boolean true
'user' => null
'email' => boolean false
BUT the variables are sent to VOLT in an upper layer because it is still set as an ARRAY.
The only viable solution is to make an object or something and get from a config what validation rules to apply to forms (by name) and rewrite the post variable in public/index.php something like this:
if(isset($_POST['email']))
{
$_POST['email'] = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
}
If anyone has a better solution in which this can be done in a controller rather that this or in a service with event handlers...
You can do anything you wish by implementing a custom filter and doing a proper conversion from array to string.
$filter = new \Phalcon\Filter();
//Using an anonymous function
$filter->add('superSanitisedString', function($value) {
if (is_array($value)) {
$value = empty($value) ? '' : reset($value);
}
return (string) $value;
});
//Sanitize with the "superSanitisedString" filter
$filtered = $filter->sanitize($possibleArray, "superSanitisedString");
But… don't bend the stick too much – this is a clear validation job and then sanitisation. Check that the value is a string, if not – ask to provide one. It's easier and smarter to protect your app from invalid inputs than from idiots who provide that input :)
Edit:
You can use a custom volt filter which can be added as a service, implement a class with a static method to return the sanitized value and use it in the template.
Related
I'm using Laravel for a project and want to know how to validate a particular scenario I'm facing. I would like to do this with the native features of Laravel if this is possible?
I have a form which has two questions (as dropdowns), for which both the answer can either be yes or no, however it should throw a validation error if both of the dropdowns equal to no, but they can both be yes.
I've check the laravel documentation, but was unsure what rule to apply here, if there is one at all that can be used? Would I need to write my own rule in this case?
very simple:
let's say both the fields names are foo and bar respectively.
then:
// Validate for those fields like $rules = ['foo'=>'required', 'bar'=>'required'] etc
// if validation passes, add this (i.e. inside if($validator->passes()))
if($_POST['foo'] == 'no' && $_POST['bar'] == 'no')
{
$messages = new Illuminate\Support\MessageBag;
$messages->add('customError', 'both fields can not be no');
return Redirect::route('route.name')->withErrors($validator);
}
the error messge will appear while retrieving.
if you get confuse, just dump the $error var and check how to retrieve it. even if validation passes but it gets failed in the above code, it won't be any difference than what would have happened if indeed validation failed.
Obviously don't know what your form fields are called, but this should work.
This is using the sometimes() method to add a conditional query, where the field value should not be no if the corresponding field equals no.
$data = array(
'field1' => 'no',
'field2' => 'no'
);
$validator = Validator::make($data, array());
$validator->sometimes('field1', 'not_in:no', function($input) {
return $input->field2 == 'no';
});
$validator->sometimes('field2', 'not_in:no', function($input) {
return $input->field1 == 'no';
});
if ($validator->fails()) {
// will fail in this instance
// changing one of the values in the $data array to yes (or anything else, obvs) will result in a pass
}
Just to note, this will only work in Laravel 4.2+
My question is whether I should use set_value() at all to re-populate a form. It might seem odd to say that, however I am creating a shared controller function and view which can be used to either add a new record or edit an existing one. It seems to make sense to do this since the functionality is so incredibly alike.
As such, if we call up an existing record to edit I do this:
$data['fields'] = $this->customer_model->get_customer($id);
If the form is submitted to save the record, or if we're adding a record for the first time, the form has the potential to reload if the user makes a mistake so I populate $data['fields'] this way instead:
$data['fields'] = array(
'company' => $this->input->post('company') ?: '',
'website' => $this->input->post('website') ?: '',
'credit_limit' => $this->input->post('credit_limit') ?: ''
);
My form element looks like this:
<input type="text" name="company" value="<?php echo set_value('company', $fields['company']); ?>" />
But I'm thinking it may as well look like this:
<input type="text" name="company" value="<?php echo escape_html($fields['company']); ?>" />
Since the form data could come from either user input (when adding or saving) or from the database (when retrieving a record to edit) I cannot rely entirely on post() or set_value() without the 2nd parameter. Furthermore, the second parameter for set_value() will always exist ($fields['company'] in this example) because it's initialized from the start, which is why I am thinking of just using it directly.
Is there a problem with this approach?
If you want to populate form fields on FALSE return of Form Validation or insert data for editing operations, I suggest you to use following helper:
Usage
<input type="text" name="last_name" value="<?=vset_value('last_name','',$rs);?>">
Explanation
$rs here is the $db data for record (if you are sending it to view). To stay at the safe side please include $this->data['rs'] = false; at your controller. If $rs is set and true, helper take results from it and display it. Otherwise it displays if the key exist in $_POST. If both don't exists, it display default value.
Helper
/**
* vayes_helper::vset_value
*
* Retains state of INPUT text after Form Validation
*
* #access public
* #param string name of INPUT tag
* #param string default value for INPUT tag
* #param mixed DB Result (array or object)
* #return string
*/
if(!function_exists('vset_value')) {
function vset_value ($name_of_input,$default_state='',$db_result_array='') {
$CI = &get_instance();
$render_state = $default_state;
if($CI->input->post()) {
$render_state = $CI->input->post($name_of_input);
} else {
if(is_object($db_result_array) && isset($db_result_array->$name_of_input)) {
$render_state = (isset($db_result_array->$name_of_input)) ? $db_result_array->$name_of_input : $default_state;
} else if($db_result_array != '' && array_key_exists($name_of_input,$db_result_array)) {
$render_state = (isset($db_result_array[$name_of_input])) ? $db_result_array[$name_of_input] : $default_state;
}
}
return $render_state;
}
}
If you like the way, let me know. I can supply for more form input type like select, checkbox, etc.
The approach is correct, as mentioned in the CodeIgniter docs. In fact, you don't need to include the second parameter in set_value.
set_value definition:
string set_value(string $field = '', string $default = '')
//$field: If there is a submitted field with this name, its value is returned.
//$default: If there is no matching submitted field, this value is returned.
Yes,You should.
set_value() is used to re-populate a form has failed validation.
There is no additional filtering on it, so it faster.
But, I prefer some times to use $this->input->post() for the secure.
I need help understanding the logic to deal with validating user inputs.
my current state of validating user data is at worst, i feel pretty awkward using these messy lines of codes, have a look at my typical function which i uses it to get input from the user and process it to database.
public function saveUser($arguments = array()) {
//Check if $arguments have all the required values
if($this->isRequired(array('name','email','password','pPhone','gender','roleId'))) {
//$name should could minimum of 5 and maximum of 25 chars, and is a strict character.
$name = $this->isString(5, 25, $this->data['name'], 'STRICT_CHAR');
$email = $this->isEmail($this->data['email']);
$pPhone = $this->isString(5, 12, $this->data['pPhone'], 'STRICT_NUMBER');
$sPhone = (!empty($this->data['sPhone'])) ? $this->isString(5, 12, $this->data['sPhone'], 'STRICT_NUMBER') : 0;
//Check For Duplicate Email Value
$this->duplicate('user_details','email',$email);
//If Static Variable $error is not empty return false
if(!empty(Validation::$error)) { return false; }
//After Validation Insert the value into the database.
$sth = $this->dbh->prepare('INSERT QUERY');
$sth->execute();
}
}
Now is the time i focus on improving my validation code. i would like all my class methods to validate the user inputs before inserting into the database. basically a class methods which takes user input should be able to perform the following.
If class method accepts user input as an array then check for all required inputs from within the array.
Check the Minimum and Maximum Length of the input.
Check for any illegal character.
etc.
I would like to know how to deal with this, and also if there is any PHP Independent Validation Component which can come to my rescue. it would be of great help. if i am doing it wrong please suggest me on improving my code, i won't mind going to any extent as long as it guarantees that my code follows the coding standard.
I will also appreciate if someone could explain me on dealing with validation logic for validating user input for a class method of an object.
Thank you..
PHP 5.2 has a new core extension called "filter functions". You can use this extension to sanitize and validate user data.
For example, to validate an email address:
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo "This (email) email address is considered valid.";
}
As for dealing with validation in general, you want to decouple the validation process from the incoming data and the objects themselves. I use the Lithium PHP framework, and their data validation class is implemented as a nearly independant utility class. Check it out for ideas on how to roll your own: http://li3.me/docs/lithium/util/Validator
Using their class, you get something like this:
// Input data. This can be an $object->data() or $_POST or whatever
$data = array(
'email' => 'someinvalidemailaddress';
);
// Validation rules
$rules = array(
'email' => array(
array('notEmpty', 'message' => 'email is empty'),
array('email', 'message' => 'email is not valid')
)
);
// Perform validation
Validator::check($data, $rules);
// If this were in your object
public validate($data = array(), $rules = array()) {
$data = !empty($data) ? $data : $this->data; // Use whatever data is available
$rules = $this->rules + $rules; // Merge $this's own rules with any passed rules
return Validator::check($data, $rules));
}
// You can have a save method like
public save() {
if ($this->validates()) {
// insert or update
}
}
// And your object would
$user = new User();
$user->data = array('email' => 'whatever');
$user->save();
And there's always Zend Validate. You can look it up at http://framework.zend.com/manual/en/zend.validate.set.html
Create your validation class first...Then when they submit the code. Just include the class on where every you have action set to on the form. You can create a loop to pass the POST or GET data though the instance which validates the input. Then if the input is good, return it(maybe as an array, that's what I do) and pass it to your database.
Example:
$validate = new validation_Class; //new instance of the validation class
$output = foreach($_POST as $input) // loop each input data into the class
{
$validate->$input;
}
Now if your validation class is setup right, you can have all the clean data stored in $output
I have a form element for capturing email addresses. I am using Zend_Validate_EmailAddress on the element, and it generates error messages that aren't very user-friendly.
My first step was to specify new messages that were more user-friendly, but some of the checks simply don't lend themselves to a user-friendly message. I then tried to simply clear those messages after running isValid() on the form and specify my own, but none of the functions I've found will clear the messages.
What I've tried and results
setErrorMessages() - Values set here seem to be ignored altogether
clearErrorMessages() - Seems to be ignored
setErrors() - Adds my message, but leaves the others intact
This is the code that displays the errors in my custom view script:
<?php if ($this->element->hasErrors()): ?>
<?php echo $this->formErrors($this->element->getMessages()); ?>
<?php endif; ?>
MY SOLUTION
I'm awarding Gordon with the answer, because his solution is most complete, but I ended up using the addErrorMessage() function on the element like this:
$element->addValidator('EmailAddress', false, $this->_validate['EmailAddress'])
->addErrorMessage("'%value%' is not a valid email address");
$element->addValidator('Date', false, array('MM/dd/yyyy'))
->addErrorMessage("Date must be in MM/DD/YYYY format");
From the Reference Guide (emphasis mine):
Some developers may wish to provide custom error messages for a validator. The $options argument of the Zend_Form_Element::addValidator() method allows you to do so by providing the key 'messages' and mapping it to an array of key/value pairs for setting the message templates. You will need to know the error codes of the various validation error types for the particular validator.
So you can do:
$form = new Zend_Form;
$username = new Zend_Form_Element_Text('username');
$username->addValidator('regex', false, array(
'/^[a-z]/i',
'messages' => array(
'regexInvalid' => 'foo',
'regexNotMatch' => 'bar',
'regexErrorous' => 'baz'
)
));
$form->addElement($username);
$form->isValid(array('username' => '!foo'));
which will then render 'bar' for the error message, because the regex does not match because it doesnt start with a letter from a-Z.
This is equivalent to using:
$username->setErrorMessages(
array(
'regexNotMatch' => 'The value %value% must start with a-Z',
…
)
);
I've used a different pattern to illustrate how to use the validated value in the pattern.
You can also use setErrors, if you want to delete any default templates, e.g.
$username->setErrors(array('The value must start with a-Z'));
Whatever you do, you have to configure that before validating with isValid. Once the validation is run, the Zend_Form_Element will contain the default error message otherwise. I am not aware of any way to reset that then (though someone might want to correct me on that).
Further quoting the reference guide:
A better option is to use a Zend_Translate_Adapter with your form. Error codes are automatically passed to the adapter by the default Errors decorator; you can then specify your own error message strings by setting up translations for the various error codes of your validators.
All the validation messages can be customized from the file in
http://framework.zend.com/svn/framework/standard/trunk/resources/languages/en
The file should be in APPLICATION_PATH/resources/languages, but can really be placed anywhere as long as you tell Zend_Translate where to find it.
When you define a form element like this
$titel = new Zend_Form_Element_Text ( "titel" );
$titel->setLabel ( "Titel" )->setRequired ( true )
->addValidator ( 'regex', false, array ("/[\pL\pN_\-]+/" ) );
you can specify a error message in your view script
<?php
$form = $this->form;
$errorsMessages =$this->form->getMessages();
?>
<div>
<label>Titel</label> <?php echo $form->titel->renderViewHelper()?>
<?php
if(isset($errorsMessages['titel'])){
echo "<p class='error'>There's something wrong!</p>";
}
?>
</div>
I don't know if this conforms your way but I really like defining my forms this way ;)
One way you can attack it is to create your own custom validator by extending the validator you plan on using and overriding the messages. For instance, looking at Zend_Validate_Alnum, it looks like this:
class Zend_Validate_Alnum extends Zend_Validate_Abstract
{
const INVALID = 'alnumInvalid';
const NOT_ALNUM = 'notAlnum';
const STRING_EMPTY = 'alnumStringEmpty';
[ ... ]
protected $_messageTemplates = array(
self::INVALID => "Invalid type given. String, integer or float expected",
self::NOT_ALNUM => "'%value%' contains characters which are non alphabetic and no digits",
self::STRING_EMPTY => "'%value%' is an empty string",
);
[ ... ]
}
Override the $_messageTemplates array in your own class like this
class My_Validate_Alnum extends Zend_Validate_Alnum
{
protected $_messageTemplates = array(
self::INVALID => "My invalid message",
self::NOT_ALNUM => "foo",
self::STRING_EMPTY => "'%value%' is bar",
);
[ ... ]
}
Then instead of using Zend_Validate_Alnum, use My_Validate_Alnum as your validator. Custom validators are very simple to create.
I have an element. I want to add a custom validator and custom filter to it. The validator makes sure the input is one of several permitted values, then the filter adds some custom values to the input. This means I have to validate the original input first before running the filter. I do it in this order
$element = new Zend_Form_Element_Text('element');
$element->addValidator('PermittedValue', false);
$element->addFilter('TotalHyphen', false);
$this->addElement($element);
but this order isn't being respected. The filter runs first and changes the data, then the validator runs on the filtered data which means it always fails even for valid input. It seems from documentation that this is intentional
Note: Validation Operates On Filtered
Values Zend_Form_Element::isValid()
filters values through the provided
filter chain prior to validation. See
the Filters section for more
information.
How can I specify the order in which validators and filters run?
Sure seems like creating a custom element that supports post-validation filtering would be the way to go. How about this:
/**
* An element that supports post-validation filtering
*/
class My_Form_Element_PostValidateFilterable extends Zend_Form_Element_Text
{
protected $_postValidateFilters = array();
public function setPostValidateFilters(array $filters)
{
$this->_postValidateFilters = $filters;
return $this;
}
public function getPostValidateFilters()
{
return $this->_postValidateFilters;
}
public function isValid($value, $context = null)
{
$isValid = parent::isValid($value, $context);
if ($isValid){
foreach ($this->getPostValidateFilters() as $filter){
$value = $filter->filter($value);
}
$this->setValue($value);
}
return $isValid;
}
}
Usage would be something like this:
$elt = $form->addElement('PostValidateFilterable', 'myElement', array(
'label' => 'MyLabel',
'filters' => array(
'StringTrim',
// etc
),
'validators' => array(
'NotEmpty',
// etc
),
// here comes the good stuff
'postValidateFilters' => array(
new My_Filter_RunAfterValidateOne(),
new My_Filter_RunAfterValidateTwo(),
),
));
This keeps the validation and filtering in the form - keeping the controller thin.
Not tested, just a stab in the dark. And surely you could fatten/modify the API to add/remove filters by key, etc.
Whaddya think?
Maybe don't add the filter at all. Validate the content first in the controller, and then use the filter separately:
$request = $this->getRequest();
if ($request->isPost() && $form->isValid($request->getParams())) {
$filter = new Filter_Whatever();
$val = $filter->filter($request->getParam('element'));
... //call your model or whatever
}
I've never done this, but I suppose this (or something similar) might work.
Good point ! ,
AFAIK filters should or must run before validating the input :
from ZF docs
It's often useful and/or necessary to
perform some normalization on input
prior to validation. For example, you
may want to strip out all HTML, but
run your validations on what remains
to ensure the submission is valid. Or
you may want to trim empty space
surrounding input so that a
StringLength validator will use the
correct length of the input without
counting leading or trailing
whitespace characters.
but if and only if you are in case which can't solve mingos's answer must be the help
What you want to achieve is to change default behavior of how text element is being processed. Thus, I think you could create your own element (e.g. My_Form_Element_Text) that extends Zend_Form_Element_Text and overload its isValid() method.
Specifically you could just change second line in the orginal isValid() method, from $value = $this->getValue(); into $value = $this->getUnfilteredValue();. This way your validation will be performed using unfiltered values.