HtmlPurifier implementation in Yii

So, i was playing with HTML Purifier a few minutes ago and noticed that the implementation made in Yii is very primitive, or at least from my point of view.

Say i want to allow the target="_blank" attribute in my text editors, with the current implementation this not possible as i don’t have access to the purifier classes.

The html purifier way is like:




$config = HTMLPurifier_Config::createDefault();

$config->set('HTML.DefinitionID', 'enduser-customize.html tutorial');

$config->set('HTML.DefinitionRev', 1);

$config->set('Cache.DefinitionImpl', null); // remove this later!

$def = $config->getHTMLDefinition(true);

$def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');

$purifier=new HtmlPurifier($config);



Remember, i just want to “append” something, i don’t want to rewrite the entire list of allowed attributes.

As far as i can see , it is not possible to do something like this with the current implementation.

Are there any plans of making this work as it should or we must find workarounds to make it work ?

How would you do it with native HTMLPurifier?

The "native" way of calling Html Purifier is like :




$config = HTMLPurifier_Config::createDefault();

$config->set('HTML.DefinitionID', 'enduser-customize.html tutorial');

$config->set('HTML.DefinitionRev', 1);

$config->set('Cache.DefinitionImpl', null); // remove this later!

$def = $config->getHTMLDefinition(true);

$def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');

$purifier=new HtmlPurifier($config);

$purifier->purify($text);



The Yii way is like:




$purifier=new CHtmlPurifier;

$purifier->options=array('options here to build the config from scratch');

$purifier->purify($text);



[This idea just hit me 2 seconds ago]

Not sure, hadn’t had the chance to test, but maybe




$purifier=new CHtmlPurifier; // this would make all html purifier classes available


$config=HTMLPurifier_Config::createDefault();//grab the default configuration.

$def=$config->getHTMLDefinition(true);

$def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');//append to it.


$purifier->options=$config;//and pass it further to the __construct of the main HtmlPurifier class.

$purifier->purify($text);



Hmm, i am sure the above "hack" will do it just fine.

Tried with:




private function getHtmlPurifier()

    {

        if($this->_purifier!==null)

            return $this->_purifier;

        

        $this->_purifier=new CHtmlPurifier;


        $config = HTMLPurifier_Config::createDefault();

        $config->set('HTML.DefinitionID', '12345');

        $config->set('HTML.DefinitionRev', 1);

        $config->set('Cache.DefinitionImpl', null); // remove this later!

        $def = $config->getHTMLDefinition(true);

        $def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');

        $this->_purifier->options=$config;

        

        return $this->_purifier;

    }



But it throws an error :




Cannot set directive after finalization on line 1546 in file /home/xxx/public_html/framework/vendors/htmlpurifier/HTMLPurifier.standalone.php



I don’t get why it throws this error, the $options object reaches HtmlPurifier from inside of the purify() method of the CHtmlPurifier widget, so it should work just fine .

Any ideas ?

As I remember, native throws the same error if you’re setting params in a wrong order or something but I can’t remember what order is correct.

Unfortunately, no luck using this as i wanted.

In the end, i have smth like this :




public function purify($str)

    {

        if(is_array($str))

        {

            foreach($str AS $k=>$v)

                $str[$k]=$this->purify($v);

            return $str;

        }

        return $this->getHtmlPurifier()->purify($str);

    }


private function getHtmlPurifier()

    {

        if($this->_purifier!==null)

            return $this->_purifier;

        $this->_purifier=new CHtmlPurifier;

        if(file_exists($file=Yii::getPathOfAlias('application').DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'htmlpurifier.php'))

            $this->_purifier->options=include($file);

        return $this->_purifier;

    }



So i am using a config file to return an array() of configuration items which does the trick for now (i don’t really care about the target attribute)

Samdark, if you do remember something about this, please let me know.

Know it’s an old thread but I found it in my pursuit of a solution to getting target to work in purified text with links.

And later I found a solution that maybe someone will have use for.




$purifier = new CHtmlPurifier();

$purifier->options = array(

    'Attr.AllowedFrameTargets'=> array('_blank','_self','_parent','_top'), 

    'HTML.Allowed'=> 'p,a[href|target],b,i,br',

);