Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

variableFilter and bbcode parsing
Goto page 1, 2  Next
 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Smarty 3
View previous topic :: View next topic  
Author Message
stayclose
Smarty Rookie


Joined: 16 Feb 2010
Posts: 9

PostPosted: Wed Jul 21, 2010 1:23 pm    Post subject: variableFilter and bbcode parsing Reply with quote

Hello Monte,

I am switching one of our sites over to Smarty3 RC3 and as such I've ran into some small problems. I am using the variable filter htmlspecialchars which works great except when you want to parse bbcode.

As is the case now, modifiers are applied first and after that the variable filter is applied. So, my bbcode modifier generates HMTL from [b] etc tags. Which are then escaped by the variable filter.

There are some solutions (in my opinion):

1) use nofilter and apply your own modifier to escape first, then apply smiley and bbcode modifiers. In my opinion this is not the best solution. Especially in this case where you already allow users to influence the output forgetting to apply to escape modifier can have some serious impact. Also it pretty much negates the usefulnes of autoescaping.

2) apply the variable filter before the modifiers. I think this is one of the safest options because you know the data your are working with is safe for displaying.

3) bypass the variable filter all together and auto escape when assigning. This is what I use with Smarty 2:

function assign($tpl_var_unsafe, $value_unsafe = null, $output_filter = TRUE)
{

$tpl_var = $tpl_var_unsafe;
$value = $value_unsafe;

if ($output_filter === TRUE) {

if (is_array($tpl_var_unsafe)) {
$tpl_var = $this->_output_filter($tpl_var_unsafe);
} else {
$value = $this->_output_filter($value_unsafe);
}

}


function _output_filter($in) {

if (is_array($in)) {

$out = array();

foreach ($in as $key => $value) {
if ($value != "") {
$out[$key] = $this->_output_filter($value);
}
}

} else {

$out = htmlspecialchars(iconv("UTF-8", "UTF-8//IGNORE", $in), ENT_QUOTES, "UTF-8", FALSE);

}

return $out;

}

NOTE: this also isn't the best solution since i'm missing the other methods by only doing this for assign()!

What would be the best solution in your opinion? Perhaps I am overlooking something in the docs and there's an even better solution. I also couldn't find anything related on the forum.

Thanks,
Back to top
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Wed Jul 21, 2010 6:10 pm    Post subject: Reply with quote

Well I never thought about this possible problem.

To your ideas:

1.) Currently this is the best workaround.

2.) This is the betst solution. However it requires some major changes in the parser for the modifier handling. I will try to implement this ASAP, but could take a few days until it's done.

3.) Even if this worked for you in Smarty2 but personally don't like this solution. In my opinion the filter should work on the output string and not on variables as they are assigned. You may want to use the variables for other purpose as output. When you run the filter also on these variables you may not gat the expected results.
Back to top
View user's profile Send private message
stayclose
Smarty Rookie


Joined: 16 Feb 2010
Posts: 9

PostPosted: Thu Jul 22, 2010 9:36 am    Post subject: Reply with quote

Well, I agree with you on point 2. The filter should only be used on variables that are actually displayed.

Until the changes are visible in SVN I have implemented a simple method in class Smarty_Variable to get me going for now:

$this->value = $this->_variableFilter($value);

private function _variableFilter ($in)
{

if (is_array($in)) {

$out = array();

foreach ($in as $key => $value) {
if ($value != "") {
$out[$key] = $this->_variableFilter($value);
} else {
//print "[empty] key: $key, value: $value\n";
$out[$key] = $value;
}
}

} else {

if (is_string($in)) {
//print "[string] value: $in\n";
$out = htmlspecialchars(iconv("UTF-8", "UTF-8//IGNORE", $in), ENT_QUOTES, "UTF-8", FALSE);
} else {
//print "[non-string] value: $in\n";
$out = $in;
}

}

return $out;

}

The only thing to remember I see with option 2 is that when you want (for instance, ofcourse it depends on what your variable filter does!) HTML outputted you will have to add a modifier to negate the variable filter to that specific variable in your template.
Back to top
View user's profile Send private message
stayclose
Smarty Rookie


Joined: 16 Feb 2010
Posts: 9

PostPosted: Thu Jul 22, 2010 11:16 am    Post subject: Reply with quote

After some testing I noticed a case where I would need a whole array not to be ran through a filter.

Ofcourse I could have added a modifier for each variable (there are a lot) but instead I temporarily implemented the following:

In smarty_internal_data.php:

public function assign($tpl_var, $value = null, $nocache = false, $scope = SMARTY_LOCAL_SCOPE, $variableFilter = true)
{


public function __construct ($value = null, $nocache = false, $scope = SMARTY_LOCAL_SCOPE, $variableFilter = true)
{

if ($variableFilter === true) {
$this->value = $this->_variableFilter($value);
} else {
$this->value = $value;
}


Where private function _variableFilter is the one from an earlier post.

Variable assignment should be like this:

$smarty->assign("myvar", $myvar, false, SMARTY_LOCAL_SCOPE, false);

Note that this is only useful in my specific case.
Back to top
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Fri Jul 23, 2010 1:12 pm    Post subject: Reply with quote

The execution order has now been changed. The variable filter does now run on output before the modifier.

Note that the execution of the variable filter is automatically context sensitive. It does run only when output is gererated.

Example with variable filter htmlspecialchars
Code:
{if $foo == '>'}{$foo}{/if}


Assume that foo has '>' assigned. The filter does not run on $foo inside the if tag. So the compare will work. But it does run on {$foo} so the generated output is '?gt;'

The same does apply to default modifers. In contrast Smarty2 did run default modifers always which did create in many cases problems.


The change is in the SVN now.
Back to top
View user's profile Send private message
stayclose
Smarty Rookie


Joined: 16 Feb 2010
Posts: 9

PostPosted: Fri Jul 23, 2010 3:44 pm    Post subject: Reply with quote

Hello Uwe,

After some initial testing everything seems to be working as I expected. I have applied the latest SVN code and thus removed my initial workaround. I think this is the most elegant way to go, in combination with 'nofilter' it is also very flexible. In my case it gives me the freedom needed and also gives me some extra speed by only running the variable filter on variables that are actually outputted.

Thanks

U.Tews wrote:
The execution order has now been changed. The variable filter does now run on output before the modifier.

Note that the execution of the variable filter is automatically context sensitive. It does run only when output is gererated.

Example with variable filter htmlspecialchars
Code:
{if $foo == '>'}{$foo}{/if}


Assume that foo has '>' assigned. The filter does not run on $foo inside the if tag. So the compare will work. But it does run on {$foo} so the generated output is '?gt;'

The same does apply to default modifers. In contrast Smarty2 did run default modifers always which did create in many cases problems.


The change is in the SVN now.
Back to top
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Sat Jul 24, 2010 11:51 pm    Post subject: Reply with quote

I had introduced another bug which is fixed in the SVN now.
Back to top
View user's profile Send private message
thunberg
Smarty Rookie


Joined: 08 Mar 2011
Posts: 6

PostPosted: Tue Mar 08, 2011 9:37 pm    Post subject: Reply with quote

I could be mistaken, but I believe version 3.0.7 once again incorrectly applies variable filters (or the mapped default_modifiers) after in-template modifiers as opposed to before.

The example I'm currently referring to applies an htmlentities-like variable filter and when outputting in a template using "|nl2br" the <br> tags are escaped.

Any suggestions?
Back to top
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Wed Mar 09, 2011 1:35 pm    Post subject: Reply with quote

The change got somehow lost.

This is now fixed in the SVN trunk version.
Back to top
View user's profile Send private message
thunberg
Smarty Rookie


Joined: 08 Mar 2011
Posts: 6

PostPosted: Wed Mar 09, 2011 4:14 pm    Post subject: Reply with quote

Works perfectly now, thank you for fixing it.
Back to top
View user's profile Send private message
stayclose
Smarty Rookie


Joined: 16 Feb 2010
Posts: 9

PostPosted: Tue Mar 22, 2011 8:44 am    Post subject: Reply with quote

I was having the exact same thing, I applied 3.0.7 but I only noticed it when I went on recompiling some templates.

I'm happy it is fixed in SVN Smile

Thanks Uwe
Back to top
View user's profile Send private message
thunberg
Smarty Rookie


Joined: 08 Mar 2011
Posts: 6

PostPosted: Mon Aug 20, 2012 10:49 pm    Post subject: Reply with quote

I think this has once again reverted. I recently upgraded from Smarty 3 SVN revision 3286 to 3.1, and my default modifiers are being run after the in-template modifiers. Here's an example of my setup (note that I have a page class that extends Smarty):

$this->default_modifiers = array('escape:"htmlall":"UTF-8"');

in the template:

{$event.details|truncate:190|nl2br}

Prior versions worked as expected, current version outputs a bunch of visibly escaped <br />.

Thank you in advance for the help.
Back to top
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Wed Aug 22, 2012 7:44 pm    Post subject: Reply with quote

When we introduced the $smarty->escape_html option flag we decided on the execution order documented here http://www.smarty.net/docs/en/variable.escape.html.tpl

Either way we go is wrong.
{$foo|strlen} is an argument pro “escapeHTML goes last”,
{$foo|nl2br} is an argument pro individual goes last”.

We think that modifier adding html tags are used less frequently that something like {$foo|escape|nl2br nofilter} is in order for such cases.
Back to top
View user's profile Send private message
thunberg
Smarty Rookie


Joined: 08 Mar 2011
Posts: 6

PostPosted: Thu Aug 23, 2012 4:55 am    Post subject: Reply with quote

I appreciate both the reply and your continued work on Smarty, but unfortunately that does not help in my situation since the "escape_html" option uses "htmlspecialchars" and not the more complete "htmlentities".

Additionally, in your documentation it states that:

"Modifiers and Filters are run in the following order: modifier, default_modifier, $escape_html, registered variable filters, autoloaded variable filters, template instance's variable filters. Everything after default_modifier can be disabled with the nofilter flag."

Unless I'm ready that incorrectly, it would imply that "nofilter", unlike in the past, has no impact on whether or not default modifiers are applied. In practice though, in 3.1, "nofilter" does in fact prevent default modifiers from being applied (as I expected based on previous version behavior).

So I can plan for the above, is this a documentation or implementation error?
Back to top
View user's profile Send private message
thunberg
Smarty Rookie


Joined: 08 Mar 2011
Posts: 6

PostPosted: Thu Aug 23, 2012 5:15 am    Post subject: Reply with quote

Additionally, since you've specifically added a separate method to escape HTML via "escape_html", wouldn't that nullify the argument against having "default_modifiers" run first?
Back to top
View user's profile Send private message
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Smarty 3 All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP