This component is everything you need in order to be sure that the input coming from your users is santitized and the data is safe.
It wraps HtmlPurifier and Codeigniter Security class in a single component that does an awesome job.
Regarding Codeigniter Security class, it has the best xss filter that i know of(excepting html purifier) and it is very fast (comparing to html purifier).
Why including both you may ask, well, the answer is simple, the HtmlPurifier being a large and kind of slow library, it is used only for HTML content cleaning, say a textarea from CKEDITOR or TINYMCE, while Codeigniter XSS filter is used for any other input type because it is way faster and does the job as it should.
Note ¶
This extension is not meant to protect you against sql injection, use Yii's param binding feature for that.
Requirements ¶
Yii 1.1.x
Usage ¶
Say we have a model having a CKEDITOR textarea and other text fields that doesn't allow any html content. We need to use html purifier to be sure the CKEDITOR textarea is treated correctly, but we also need to be sure that the other fields are stripped of html and also cleaned so that the cannot contain dangerous data.
if(isset($_POST['Example']))
{
$purify=array('content');
foreach($_POST['Example'] AS $key=>$value)
{
if(in_array($key, $purify))
$_POST['Example'][$key]=Yii::app()->input->purify($value);
else
$_POST['Example'][$key]=Yii::app()->input->stripClean($value);
}
$model->attributes=$_POST['Example'];
if($model->save())
$this->redirect(array('view','id'=>(int)$model->id));
}
In case our model doesn't have a textarea having HTML content, we can just clean everything from one move:
if(isset($_POST['Example']))
{
// this will apply stripTags() then xssClean() methods to the array.
$_POST['Example']=Yii::app()->input->stripClean($_POST['Example']);
// also you can do:
$_POST['Example']=Yii::app()->input->xssClean($_POST['Example']);
$model->attributes=$_POST['Example'];
if($model->save())
$this->redirect(array('view','id'=>(int)$model->id));
}
Handling $_GET and $_POST. Say you want to get a $_GET/$_POST variable and use it:
$post=Yii::app()->input->post('username');
$get=Yii::app()->input->get('username');
In both cases, the $_POST['username'] and $_GET['username'] are sanitized and returned.
Available methods ¶
/*
* 1) HtmlPurifier Filter.
* Method: purify($str);
*/
$clean=Yii::app()->input->purify($string);
$clean=Yii::app()->input->purify($array);
/*
* 2) XssClean Filter
* Method: xssClean($str);
* This will use the Codeigniter Xss Filter to clean the content
*/
$clean=Yii::app()->input->xssClean($string);
$clean=Yii::app()->input->xssClean($array);
/*
* 3) stripTags($str, $encode=false)
* This is a wrapper for strip_tags but it also supports an array as it's param
*/
$clean=Yii::app()->input->stripTags($string);
$clean=Yii::app()->input->stripTags($array);
/*
* 4) stripClean($str)
* This will use the above stripTags() method, then the xssClean() method.
*/
$clean=Yii::app()->input->stripClean($string);
$clean=Yii::app()->input->stripClean($array);
/*
* 5) stripCleanEncode($str)
* Similar to the above stripClean() method, only it also encodes the input
*/
$clean=Yii::app()->input->stripCleanEncode($string);
$clean=Yii::app()->input->stripCleanEncode($array);
/*
* 6) encode($str)
* A wrapper for CHtml::encode() but also can take an array as param
*/
$clean=Yii::app()->input->encode($string);
$clean=Yii::app()->input->encode($array);
/*
* 7) get($str, $defaultValue='', $xssClean=true)
* The get() method will fetch a $_GET item, clean and return it
*/
$clean=Yii::app()->input->get($string);
/*
* 8) post($str, $defaultValue='', $xssClean=true)
* The post() method will fetch a $_POST item, clean and return it
*/
$clean=Yii::app()->input->post($string);
/*
* 9) getPost($str, $defaultValue='', $xssClean=true)
* The getPost() method will try to fetch a $_GET item, if it doesn't exists, it'll try a $_POST item.
* The returned content is cleaned.
*/
$clean=Yii::app()->input->getPost($string);
Installation: ¶
1)
Extract the archive and paste the contents of the "protected" folder from within the archive over your project protected folder.
The archive protected folder contains :
/config/htmlpurifier.php
/components/CmsInput.php
/vendors/Codeigniter/CI_Security.php
Note on htmlpurifier.php from config folder.
This file is the configuration for HtmlPurifier, so if you want to add extra configuration for the purifier, do it in this file.
2)
Open main.php and make it look like:
'preload'=>array('log', 'input'),
'components'=>array(
[...]
'input'=>array(
'class' => 'CmsInput',
'cleanPost' => false,
'cleanGet' => false,
),
[...]
),
The component has the ability to be used as a global cleaning tool, so that if you set:
'input'=>array(
'class' => 'CmsInput',
'cleanPost' => true,
'cleanGet' => true,
),
The $_GET/$_POST will be cleaned right when the application starts, at the onBeginRequest event.
In case you use this approach (i wouldn't recommend it, but there are cases when you might need it) you should know that the $_GET/$_POST are cleaned using Yii::app()->input->xssClean() which might remove HTML markup that you want to keep. If this happens, you have following methods available to access the original global arrays:
Yii::app()->input->getOriginalPost();//returns the original, uncleaned $_POST array()
Yii::app()->input->getOriginalGet();//returns the original, uncleaned $_GET array()
Changelog ¶
VERSION 1.1
- Added public $cleanMethod, which allows to specify which filter should be used to clean globals.You can use the following methods for cleaning:
->stripCleanEncode();
->stripTags();
->stripClean(); //default one
->xssClean();
->encode();
->purify();
->cleanEncode();
->stripEncode();
- Added stripEncode method, which will strip tags and encode.
- Added cleanEncode method that will xssClean and encode
- Added decode method to decode a string/array
- post/get methods can now retrieve the entire array at once
- getOriginalPost()/getOriginalGet() can retrieve a single key or the entire array
- Fixed a bug in the encode method
- Added logging for global filtering
- The cleaning of the globals is now set to true by default, it is safer this way
- Other various changes.
Changelog for 1.2 ¶
- added getQuery(), a wrapper for get() to be more yii like.
- getPost will now retrieve a value from $_POST, being a post() wrapper to be more yii like.
- fixed a bug in get/post where if the $defaultValue was set and the variable didn't existed it would return an empty string(thanks to Wiseon3 [http://www.yiiframework.com/user/13664/] who pointed it out)
- logging will occur just in debug mode from now on.
- changed the default cleaning method to from stripCleanEncode to stripClean
Changelog for 1.3 ¶
- Updated CodeIgniter Security class
- Improved the stripTags method so that encoded chars won't go through anymore (thanks Jos Wetzels (a.l.g.m.wetzels@gmail.com))
This is a pretty large component, so it might take a while to fully understand how it works, but in the end, it is a tool that is needed to be sure the user input is sanitized and clean.
Also, worth taking a look inside the CmsInput.php file to understand it better.
Fantastic!
Thank you for sharing your terrific extension. I've looked at several different options for this absolutely necessary functionality, and I decided to go with yours. I appreciate the flexibility your extension provides.
Good work!
Thanks
thanks for the kind words, i really appreciate :)
Component updated.
The component has been updated, please take the time and update your files with the new ones and report any bug you might find.
Thanks.
thank you boss!
:)
Very nice!
Thank you for this exceptionally extension.
I changed a little, because sometime I need to allow some tags when I use ->stripTags:
public function stripTags($str, $encode=false, $allowed=false) { if(is_array($str)) { foreach($str AS $k=>$v) $str[$k]=$this->stripTags($v, $encode, $allowed); return $str; } $str=trim(strip_tags($str, $allowed)); if($encode) $str=$this->encode($str); return $str; }
Bug when using stripClean as the $cleanMethod
I found a small bug when using stripClean as the $cleanMethod, namely if you have the $defaultValue=NULL and you get() or post() a variable which doesn't exist it will return an empty string instead of $defaultValue which is set as NULL.
To fix it replace in function get() at the end:
if($clean===true && $this->cleanGetCompleted===false) return $this->$cleanMethod(Yii::app()->request->getQuery($key, $defaultValue)); return Yii::app()->request->getQuery($key, $defaultValue);
with
$value = Yii::app()->request->getQuery($key, $defaultValue); if($clean===true && $this->cleanGetCompleted===false && !empty($value)) return $this->$cleanMethod($value); return $value;
And in function post() at the end:
if($clean===true && $this->cleanPostCompleted===false) return $this->$cleanMethod(Yii::app()->request->getPost($key, $defaultValue)); return Yii::app()->request->getPost($key, $defaultValue);
with
$value = Yii::app()->request->getPost($key, $defaultValue); if($clean===true && $this->cleanPostCompleted===false && !empty($value)) return $this->$cleanMethod($value); return $value;
Thanks
@Wiseon3 - Thanks for pointing this out. I adjusted the file and uploaded a new version with a few other changes (see changelog).
Please let me know in case you find something else.
Bug when using stripClean as the $cleanMethod
@twisted1919 The bug is still present in the new version. Please note that in the code I posted there was an extra condition in the if for post() and get(), namely && !empty($value).
Without this condition you still get an empty string instead of NULL, because applying the function strip_tags() to a NULL element returns an empty string.
...
Ah yes, you are right, i modified the 1.2 archive and uploaded it again, this time with !empty($value) condition.
Documentation bug
Hi,
An update to the documentation is needed: getPost() now does not query GET then POST if it didn't find the value in GET. Rather, it checks only in POST. The documentation above says otherwise, probably reflecting past API and I guess it better be updated.
Thanks for this extension!
input + redactor
I am using redactor for field content of my model. Below is the actionCreate method,
public function actionCreate() { $model = new Post; // Uncomment the following line if AJAX validation is needed // $this->performAjaxValidation($model); if (isset($_POST['Post'])) { $model->attributes = $_POST['Post']; // Get the original `content` and putify it $oriPost = Yii::app()->input->getOriginalPost('Post'); $model->content = Yii::app()->input->purify($oriPost['content']); $model->content = Yii::app()->input->xssClean($model->content); if ($model->save()) { $this->redirect(array('view', 'id' => $model->id)); } } $this->render('create', array( 'model' => $model, )); }
I purify and xssClean in order to get a save content. However, when I set the style (set size, float, margin, etc) of an image, I got a problem. After click create, style attribute of the image will not be saved. It seems that purify and/or the xssClean method has deleted it.
Any help to use which method? Thank you in advance.
Cheers,
Daniel
Little change
Me too, I need allowed tags sometimes. So, I've added
public $allowedTags = '';
property, then I've changed stripTags() like this:
public function stripTags($str, $encode=false, $allowed = '') { if(is_array($str)) { foreach($str AS $k=>$v) $str[$k]=$this->stripTags($v, $encode, $this->allowedTags); return $str; } $str=trim(strip_tags($str,$this->allowedTags)); if($encode) $str=$this->encode($str); return $str; }
Finally, I can use this syntax:
Yii::app()->input->allowedTags = '<tag1><tag2>'; Yii::app()->input->stripTags($htmlToPurify);
Yii 2.0
Hi, any plans to port this over to Yii 2.0? Or at least some guide on how to get this extension to work on Yii 2.0? Great extension by the way.
@ss229
@ss229
I don't use Yii2 now, i have never tried it so i don't know what it would imply to translate this extension into a Yii 2.0 one.
If you are into Yii 2.0 then you should try to change it yourself.
Thanks.
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.