RE: [patch] add $smarty->escape_output feature
"Martijn van Zal" <[email protected]> Thu, 4 May 2006 18:40:41 +0200
| Newsgroups | gmane.comp.php.smarty.devel |
|---|---|
| Message-ID | <[email protected]> |
I think this is a great addition to Smarty, and I'm sure going to use it. It changes the way you think about escaping, normally you have so escape all variables which somehow could contain html, if you forget to do it, you won't notice until someone (deliberately) abuses it. Using this function you don't have to worry about html which could be in your variables, it just displays it the way you want it all the time. If you forget to use the noencode modifier you find out early in the process, and it's easy to fix. It should be more difficult to insert HTML code in a template. I think Monthe misunderstanded your first mail and overreacted a little, your last explanation is perfectly clear. Kindest regards, Martijn van Zal Technical Director Email. [email protected] Cell. +31 (0)6 42721045 Brothers in art Stationsstraat 20b 1211 EN Hilversum Tel. +31 (0)35 6220093 Fax. +31 (0)35 6210996 www.brothersinart.net -----Original Message----- From: Andreas Korthaus [mailto:[email protected]] Sent: donderdag 4 mei 2006 18:19 To: [email protected]; Monte Ohrt Subject: Re: [SMARTY-DEV] [patch] add $smarty->escape_output feature Hi! Monte Ohrt wrote: > I don't think you should require this in the template: > > {if $foo|noescape eq "<bar>"} I don't require that! When I apply my patch and try the following code: xss.php: <?php $smarty = new Smarty(); $smarty->escape_output='html'; $smarty->assign('xss', '<xss>'); $smarty->display('xss.tpl'); ?> xss.tpl: {$xss} {$xss|noescape} {if $xss eq "<xss>"}ESCAPE{/if} {if $xss eq "<xss>"}NOESCAPE{/if} I get the following output: <xss> <xss> NOESCAPE That's because I don't apply a (default_)modifier on a variable, but I change what the compiler does when writing "echo $variable" to the compiled template. The "heart" of my change is the following in function _compile_tag() from Smarty_Compiler.class.php (line 435). Before my change: if (preg_match( '~^' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$~', $tag_command)) { $_return = $this->_parse_var_props($tag_command . $tag_modifier); return "<?php echo $_return; ?>" . $this->_additional_newline; } After my change: if (preg_match( '~^' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$~', $tag_command)) { $_return = $this->_parse_var_props($tag_command . $tag_modifier); // THAT'S WHAT'S NEW: $_return_escaped = $this->_escape_var($_return, $tag_modifier); return "<?php echo $_return_escaped; " . $this->_additional_newline; } So only if the regular expression above is true, the "current tag" gets escaped. As far as I understand, block functions like {if} are parsed completely somewhere else, with all included vars. And I don't need to catch them, because value of variables INSIDE {if} will never be written to STDOUT when the PHP interpreter executes the compiled template. If you do {if $var eq "<xss>"}{$var}{/if} you don't have to worry about what you find in {if}. Only {$var} can reach the users browser, and that's what is catched by my patch. {if} only creates PHP-Code, which will be away after interpreting the PHP-script. BUT: I'm not sure if there are more wholes in the smarty core compiler, where variables like $var still can reach the browser using something similar like {if}. It must be a function, which get's a variable as input, and which becomes part of the output. That's what modifiers do, so I added my escaping _after_ applying all modifiers. Perhaps you can think about something else here? Or perhaps you can think about a case, where escaping output from modifers could be a bad idea? It's important to realize, that $smarty->escape_output only makes sense, if assigning HTML-Code from PHP to the template is considered to be bad practice. Passing HTML _SHOULD_ be more difficult and uncomfortable. If you excessively want to pass HTML to your templates, $smarty->escape_output is not the right feature for you. If you want to make these people happy too, you will end up with something like the current $default_modifiers, which are not useful for anybody. Of course there can allways be exceptions, that's what the "noescape" modifier is for. If a user doesn't agree with that, he should not use $smarty->escape_output at all. That's the only way to come to a clean/complete solution. People also don't tend to use $default_template_handler_func if they are happy with the default ;-) > The engine should determine that $foo is not output (not echo()), so > it shouldn't get escaped in the first place. That's exactly what's happening with the patch ;-) > foo is {$foo} > > That should get escaped. The compiled template would be something > like: echo htmlspecialchars($this->_tpl_vars['foo'],ENT_QUOTES); exactly! That's what my patch does. boots thinks[1] about not using escape "modes" like "html|htmlall|url|user_defined", but a callback-function. I'm not sure how to add parameters to the callback function (like ENT_QUOTES and UTF-8 for htmlspecialchars). If you have to add a user-space wrapper function to pass the parameters, escaping becomes slower than my solution, which hardcodes htmlspecialchars()... in the compiled templates. What do you think about that? [1]: http://www.phpinsider.com/smarty-forum/viewtopic.php?p=30374#30374 Best regards Andreas -- Smarty Development Mailing List (http://smarty.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php -- Smarty Development Mailing List (http://smarty.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php