Smarty Forum Index Smarty
The discussions here are for Smarty, a template engine for the PHP programming language.
Dedicated server web hosting provided by Guru-host.eu.
[patch] Add a "$smarty->escape_output&qu
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    Smarty Forum Index -> General
View previous topic :: View next topic  
Author Message
andreas
Smarty Pro


Joined: 22 Apr 2003
Posts: 106

PostPosted: Fri Apr 28, 2006 12:30 pm    Post subject: [patch] Add a "$smarty->escape_output&qu Reply with quote

Hi!

Some time ago I started [url=http://www.phpinsider.com/smarty-forum/viewtopic.php?t=4992]a discussion on using htmlspecialchars()
on every assigned variable. "default_modifiers" turned out to be not very useful at all ("I see default_modifiers as a dead-horse. Let them rest in peace"), I posted some ideas how to improve the code, but the Smarty Devs said that global/default output escaping is not the right solution for the problem.

(since I cannot see a difference between the text and link format, here the url of the thread from last year: http://www.phpinsider.com/smarty-forum/viewtopic.php?t=4992)

I still disagree. Of course you can construct special situations where this is not useful, but Smarty has a lot of features which are not useful in every situation I think Wink
In my opinion, something like that (if well implemented) would be very useful for the majority of users - and can prevent a lot of XSS security problems.

The current situation is:

option 1 - do something like that in PHP-Code:
[php]$smarty->assign('string', htmlspecialchars($string, ENT_QUOTES, 'UTF-8'));
foreach ($array as $k=>$v) {
$array[$k] = tmlspecialchars($v, ENT_QUOTES, 'UTF-8');
}
$smarty->assign('array', $array);
...[/php]

or option 2 - do something like that in your template:
Code:
{$string|escape:"html":"UTF-8"}
{foreach from=$array item=test}
  {$test|escape:"html":"UTF-8"}
{/foreach}
...


What do you think, how many people do this?

What I suggest here, is a new Smarty feature, to make Smarty escape every variable, which is written into the compiled template.

Perhaps add a new member variable to the smarty class like "$smarty->escape_output = TRUE/FALSE", and now - everywhere in Smarty_Compiler.class.php, where "echo" is written to the compiled template, surround the following code with "htmlspecialchars()"!

Not sure abaut all details yet, perhaps make it possible to use other functions instead of htmlspecialchars(), and other charsets. This could be configured by 1 or 2 new Smarty member variables IMO (e.g. "$smarty->output_charset").

The same code from examples above looks like that now:

[php]$smarty->escape_output = 'html';
$smarty->output_charset = 'UTF-8';

$smarty->assign('string', $string);
$smarty->assign('array', $array);
...[/php]

Code:
{$string}
{foreach from=$array item=test}
  {$test}
{/foreach}
...


That's how I would love to write PHP-Code and Templates!

I have looked at the code, I can find 11 places where "echo" is printed to the templates. I think not all of them must be changed as described above, because some Smarty plugins return HTML code, but these use smarty_function_escape_special_chars(), and as I looked at the default_modifier code some time ago, it's not so difficult to hook into the processing, and escape everything which will be output and which is not hardcoded somewhere in a Smarty plugin/function (like "<select>").

I'm working a lot with Smarty, and large templates, and I'd love to see such a feature added to Smarty, because it would safe me a lot of time, and I'm quite sure, it would protect a lot of unprotected Smarty-based applications against XSS.

In my applications I can't find a better place to add such code than Smarty, and it has to be added to Smarty, it does not make so much sense to extend Smarty and reimplement all those core methodes.

If you really consider implementing something like that in future versions of Smarty, I'd like to come up with a patch, but I don't put so much time in it, if there is no chance to add it anyway - and that's what my feeling was after the last discussion about output encoding.

You said in the last discussion, that only the template-designer knows when to encode. I don't agreee with that! IMO the Template Designer should not be bothered with quoting or encoding, he simply writes HTML/CSS code and adds variables to it. Such a Smarty feature does not rely on the Template Designer to make no mistake, it's a "secure by default" model. It's like a contact you can rely on, so template designers have to open wholes if necessary, they don't have to close all of them.

And that's what makes the most sense IMO. And if it does not make sense to a particular user, he should simply not enable "$smarty->output_escape"!


Best regards
Andreas[/url]


Last edited by andreas on Tue Jul 20, 2010 11:58 pm; edited 2 times in total
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5608
Location: Toronto, Canada

PostPosted: Fri Apr 28, 2006 10:00 pm    Post subject: Reply with quote

Hi andreas.

Looking at that thread (again! Smile), it seems that there was agreement that the behaviour you suggest is an improvement, but the stopping issue is BC. I am still sympathetic to this idea. Yet I think it would be useful if it was not completely automatic. By that, I mean that it should be possible to configure what (if any) escaping function is auto-applied to scalars. It might also be useful to allow individual overrides where required in the template itself (though it seems that would be tricky to implement). Maybe instead of $smarty->escape_output = t/f have $smarty->output_escape_func = 'htmlspecialchars'; and have the default be false (or maybe null). The addition of the an output_charset seems like a good idea, but again, it should, by default be null.

Of course I can't speak to how Monte or Messju (or for that matter, others in the community!) would react, but FWIW, if you have a patch that does this cleanly and does not affect BC, I would support it.

Best Regards.
Back to top
View user's profile Send private message
andreas
Smarty Pro


Joined: 22 Apr 2003
Posts: 106

PostPosted: Fri Apr 28, 2006 10:33 pm    Post subject: Reply with quote

Aside from that - how can a Template Designer know, which variables he can trust and which not? Since the common goal is to seperate the Design/HTML-Code from Business Logic, a Template Designer should only know the variables, not where the values in it come from, and what has happened to them in PHP-Code before (values hard-coded in PHP-Code? values from database? user-input? already escaped in PHP?).

If you follow these common design priniples, template-variables containing HTML-Code should be avoided, because it blurs the seperation of Logic and Design.
However, if you have another opinion, if you want to pass HTML regardless of those arguments, you still have a lot of choices:

1. simply don't use $smarty->escape_output if you don't need it
2. use own smarty plugins (output of those don't gets escaped)
3. Perhaps a modifier can be added to prevent escaping, if the modifier is used (e.g. {$var|no_escape})

Another important point is, if you compare my old code above, with the new one, the escaping is really inconvenient, and if something like that is inconvenient, people tend to neglect it.


Last edited by andreas on Tue Jul 20, 2010 11:58 pm; edited 1 time in total
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5608
Location: Toronto, Canada

PostPosted: Fri Apr 28, 2006 11:15 pm    Post subject: Reply with quote

Hi andreas.

I agree with your reasoning (particularly about passing HTML in as variables -- that is a bad practice). I think you may not appreciate the fact that HTML is not the only thing that Smarty is used to template.

Regarding your comments:

- we should filter input (ie: data validation) but not alter it; this includes input into the templates. Otherwise, as you astutely point-out, one can not know what has happened to the data before it arrived. This was a major problem with magic_quotes et al and lead to unnecessary confusion. The key point is that data taken as an input should not already be transformed into a target format. IMO, a template designer should be able to "trust" all inputs.

- because templates form the output portion (ie: data consumed and transformed into a target format), it is completely reasonable that a template designer be knowledgeable of escaping said output. That doesn't imply that the process can not be automated to an extent (ie: give them tools) but I don't think that we should take the view that template designers (as well as programmers implementing Smarty in their view layer) have NO responsibility in this regard. IMO, a template designer should ensure "trust" for all outputs. That said, it may be possible to do this by agreeing with the application designer that certain Smarty features (such as those being discussed) will be turned on and have specific values. This is part of the application/template contract that I am so fond of mentioning Wink

Anyhow, I don't think that auto-escaping on the assumption of HTML should be the default for Smarty 2.x. I suspect these issues will be revisited in Smarty 3.x (whenever that happens Smile) but in that case, I'd rather have different modes so that all escaping can be abstracted based on doctypes. That's a more involved (and I suppose rather debatable) idea and I don't see much room for it in the 2.x architecture. Thoughts?


Last edited by boots on Fri Apr 28, 2006 11:19 pm; edited 1 time in total
Back to top
View user's profile Send private message
andreas
Smarty Pro


Joined: 22 Apr 2003
Posts: 106

PostPosted: Fri Apr 28, 2006 11:18 pm    Post subject: Reply with quote

Hi boots!

boots wrote:
Looking at that thread (again! Smile),

Wink

boots wrote:
it seems that there was agreement that the behaviour you suggest is an improvement, but the stopping issue is BC. I am still sympathetic to this idea.

I'm glad to hear this! What I suggest here, is not the same as suggested in the old thread. I perfectly understand the BC concerns, but I think the way default_modifiers are implemented, make it comepletly useless Wink So I'm all for letting it die -> deprecate it!

I think, a well implemented output escaping feature would be a very valuable addition to smarty. So I'd like to think about it "from scratch", not on top of "default_modifier relics". I'm not as familiar with the Smarty code as you are probably, I've only written some small patches for it, I cannot be 100 % sure how to implement a feaure like that. I'm thinking in 2 directions:

1. use existing hooks which are called as late as possible, perhaps something similar to the way I proposed in the old thread. You have to make sure, that you can catch every bit of output. Not only variables, but also methode calls and output of modifiers/plugins...

2. Try to address the issue the other way around: Find every piece of code where any output is created (e.g. "echo..." is written to the compiled template). If you have spot all pieces of code, you can put an escape function around the variables, methode-calls... which should not output HTML. For plugins/modifiers you must use the existing function/hook to escape only the output, which is not hardcoded somewhere in Smarty (like <option>, <select>...).

At the moment, the second way looks easier to me, but as said, I'm not an export of Smarty internals Wink

I'm very interested in your thoughts about it!

boots wrote:
Yet I think it would be useful if it was not completely automatic. By that, I mean that it should be possible to configure what (if any) escaping function is auto-applied to scalars.


Of course such a feature should not be enabled by default, I'd suggest to implement a new smarty member variable like

[php]$smarty->escape_output = 'html';[/php]

I think the parameters for "escape" modifier should be used as values here. e.g. "html" would be -> htmlspecialchars($string, ENT_QUOTES).

And I think the character set should be influenceable too:

[php]$smarty->escape_output = 'html';
$smarty->output_charset = 'UTF-8';[/php]

-> htmlspecialchars($string, ENT_QUOTES, 'UTF-8');

boots wrote:
It might also be useful to allow individual overrides where required in the template itself (though it seems that would be tricky to implement). Maybe instead of $smarty->escape_output = t/f have $smarty->output_escape_func = 'htmlspecialchars'; and have the default be false (or maybe null). The addition of the an output_charset seems like a good idea, but again, it should, by default be null.


That's exactly what I think. I don't want to force anybody to use such a feature or a special charset. I don't want that everybody now starts to change his/her templates/PHP code... I'd only like to add a handy feature to smarty, because I think smarty is the perfect place to implemement that! While I argue for an output-scaping feature, I can perfectly understand other opinions, so please don't get me wrong! I only look at it as a new, useful feature, not as "the new way to write smarty templates" Wink

boots wrote:
Of course I can't speak to how Monte or Messju (or for that matter, others in the community!) would react, but FWIW, if you have a patch that does this cleanly and does not affect BC, I would support it.


I'd be happy to hear what Monte or Messju thinks about it. I'll have a closer look at the source this weekend. I'd be also happy about any brief statement on how anybody else would implement it!


best regards
Andreas


Last edited by andreas on Wed May 05, 2010 10:31 pm; edited 2 times in total
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5608
Location: Toronto, Canada

PostPosted: Fri Apr 28, 2006 11:27 pm    Post subject: Reply with quote

IIR, some of the bundled plugins use echo -- but they shouldn't. All plugins should return the result. Maybe normalizing that in the codebase can be the first step to see this through. Unfrtunately, that doesn't address the issue for non-bundled (ie: 3rd party) plugins...
Back to top
View user's profile Send private message
andreas
Smarty Pro


Joined: 22 Apr 2003
Posts: 106

PostPosted: Sat Apr 29, 2006 11:08 am    Post subject: Reply with quote

boots wrote:
I agree with your reasoning (particularly about passing HTML in as variables -- that is a bad practice). I think you may not appreciate the fact that HTML is not the only thing that Smarty is used to template.


Why?

1. I don't want to enable output escaping by default

2. I also want to make it possible to use different escaping functions, or user-defined ones.

If you do something with markup, like xml/html, such an output escaping is needed every time (and that's what most people use smarty for). If you do other things, e.g. generating mails (that's something I do using smarty too), you simply don't enable such a feature. And for HTML mails you need output escaping again (also works with $smarty->fetch()).

boots wrote:
- we should filter input (ie: data validation) but not alter it; this includes input into the templates. Otherwise, as you astutely point-out, one can not know what has happened to the data before it arrived. This was a major problem with magic_quotes et al and lead to unnecessary confusion.


But if you are talking about magic_quotes, a comparable bad solution for output escaping would be something like that:

Go to php-src, search where variables, methode-output... is written to STDOUT, and put urlencode(); around it. And enable that by default and not changable from user-space. That's really far away from what I'm talking about. Some differences:

1. output escaping is not enabled by default
2. output escaping can be enabled/disabled in user-space
3. output escaping can use different escape-functions (also user-defined)
4. output escaping is only implemented in a template engine, which usually creates markup code which allways needs escaped variables
5. if you use the template engine for different purposes you simply don't enable output ecaping

6. magic-quotes was meant for a small set of "PHP-storage engines"
7. magic-quotes influences all input, regardless of the "destination" of the data
8. magic-quotes does not really work for the databases it was invented for
9. magic-quotes it was enabled by default
10. magic-quotes it was not modifiable in user-space
11. magic-quotes it cannot be configured for different escapings
...

The rule is: "filter input -> escape output", not "escape input".

boots wrote:
The key point is that data taken as an input should not already be transformed into a target format. IMO, a template designer should be able to "trust" all inputs.


But please tell me how should this be done? I often thought about using htmlspecialchars() on every value, before writing it to the database, but I don't think something like that is the best way because you get other problems. E.g. if you want to generate Excel or PDF documents from the same data. So if you load data into objects of the business logic / model, you still can't escape them, because you should not know what happens to the data after that. At this stage, you still have special html characters in your data. And now you either have to write special PHP-code, to escape all data passed to the template, or you have to use {$var|escape} in your templates (which becomes more ugly if you want to use UTF-8, what I do).

So in my eyes the template engine is the perfect place to do the escaping automatically. If you catch every "echo" block, so everything which will be printed get's escaped, I cannot see any problems with it. You only can get problems, if you WANT to output HTML code, which is not hardcoded in your templates. If you really want to do this, you can perhaps use a modifier ("no_escape"), or what I'd recommend, write a smarty plugin, which can return HTML (here only data inside the plugin gets escaped, not the HTML-code you intend to create).

And if somebody thinks that this is annoying, as said before - it should only be an optional feature, you allways have to enable it, if you want to use output escaping. But I really prefer the "secure by default" approach.


boots wrote:
- because templates form the output portion (ie: data consumed and transformed into a target format), it is completely reasonable that a template designer be knowledgeable of escaping said output. That doesn't imply that the process can not be automated to an extent (ie: give them tools) but I don't think that we should take the view that template designers (as well as programmers implementing Smarty in their view layer) have NO responsibility in this regard. IMO, a template designer should ensure "trust" for all outputs.


I can actually NOT agree with that (while I still understand that point of view Wink). It is so easy to come to a "secure by default" approach (when we are talking about XSS...). The only problem is, that code which should not be escaped, gets escaped.

In my opinion, people should avoid code like that, as explained above. If they can't avoid it, they should be forced to use the inconvenient route of using modifiers or plugins. IMO this will also help to get better code!

That said, I'm still talking about an optional feature here. If I want to "force" someone, I'm only talking about the case where he has output escaping feature enabled, which is not the default.

But people allways make mistakes, so why bother them with escaping? I think it's not so difficult to find a really nice solution.

boots wrote:
That said, it may be possible to do this by agreeing with the application designer that certain Smarty features (such as those being discussed) will be turned on and have specific values. This is part of the application/template contract that I am so fond of mentioning Wink


Yes, that's what I'm thinking about it.

boots wrote:
Anyhow, I don't think that auto-escaping on the assumption of HTML should be the default for Smarty 2.x.


No, no, no - I'm talking about an optional feature, not a default. And I don't assume HTML, the escape function used should be modifiable.

boots wrote:
I suspect these issues will be revisited in Smarty 3.x (whenever that happens Smile) but in that case, I'd rather have different modes so that all escaping can be abstracted based on doctypes. That's a more involved (and I suppose rather debatable) idea and I don't see much room for it in the 2.x architecture. Thoughts?


You don't see much room for the feature itself, or only if it's enabled by default? I tend to not recommend to enable such a feature by default. But I'm not sure. I'm only talking about HTML, because it's the most common use of smarty. Perhaps there is room in smarty 2.7 for:

$smarty->encode_output = NULL|'html'|'htmlall'|'urlencode'...
$smarty->output_charset = NULL|'UTF-8'|'latin1'...

where both values default to NULL, so nothing gets escaped automatically. If you enable it, you can be sure, that every variable, function return value... will be escaped by smarty, with the escape function and charset you have configured, which is the contract between template designer and PHP programmer.

Perhaps it's possible to add another modifier like {$var|no_escape}, to make it possible to still use unescaped output for special cases.


best regads
Andreas


Last edited by andreas on Tue Jul 20, 2010 11:58 pm; edited 2 times in total
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5608
Location: Toronto, Canada

PostPosted: Sun Apr 30, 2006 7:48 am    Post subject: Reply with quote

Hi Andreas!

I think we cross-posted and that that is where the confusion came from. Your first post and mine in this thread seem to be where we both are on the same page. Forget the noise and consider the patch Smile Sorry for any confusion there....

Best regards.

ps. an output_escape_func and output_unescape_func might be required to allow for an unescaping at template time -- if you catch my meaning.
Back to top
View user's profile Send private message
andreas
Smarty Pro


Joined: 22 Apr 2003
Posts: 106

PostPosted: Wed May 03, 2006 10:10 am    Post subject: Reply with quote

Ok, here is a first patch against CVS-HEAD:

I added a $escape_output and $output_charset to the Smarty class, which are passed to SmartyCompiler too. Both default to NULL.

In SmartyCompiler I added a "_escape_var()" methode, which puts an escape-function around the variable name. It's called from _compile_tag() line 449.

This does not break BC, you have to change the new member variable to get any effect.

But I'm not sure if I already catched all points where output is printed. As written in this thread, I found 11 places, where the SmartyCompiler uses "echo", but most of them write things like tags, which are not modifiable by any input. But I'm not yet an expert of smarty source, so there are probably some more places to catch. What I catch now, are variables and methode calls.

If you look at the plugins, my function is called after modifiers are applied, so the output generated by modifiers will be escaped too.

Other plugins like html_options call the smarty_function_escape_special_chars() function to escape user-input. So with an old/unpatched version of smarty, you allways get the values in plugins using smarty_function_escape_special_chars(), ecaped by:

[php] $string = htmlspecialchars($string);[/php]

This does not escape '. That's what the plugin situation is like today.

But why is this a function and not a Smarty methode? this would make it easier to change this function. Now it's hardcoded everywhere and it's difficult to change htmlspecialchars() to htmlentities() or add ENT_QUOTES... Plugins allways get the Smarty object, so this could be easily handled, if they would use a Smarty methode instead of a function, which does not know the Smarty object. The easiest way to change this without breaking BC, is passing a parameter, which says what escaping to use - or pass the Smarty object.
In my opinion the better way would be to go across all plugins, and change them to use a smarty methode instead of smarty_function_escape_special_chars().

Example code to make use of the patch:

[php]$smarty = new Smarty;
$smarty->escape_output='html';
$smarty->assign('xss', '<XSS>"\'');
$smarty->display('xss.tpl');[/php]

Code:
{$xss}


Here is the first patch (probably not complete, but works for me):

Code:
Index: libs/Smarty.class.php
===================================================================
RCS file: /repository/smarty/libs/Smarty.class.php,v
retrieving revision 1.524
diff -u -r1.524 Smarty.class.php
--- libs/Smarty.class.php   18 Jan 2006 19:02:52 -0000   1.524
+++ libs/Smarty.class.php   3 May 2006 09:41:09 -0000
@@ -398,6 +398,29 @@
      */
     var $config_class          =   'Config_File';
 
+    /**
+     * This tells Smarty whether or not to auto-escape output (variables)
+     *
+     * Available values:
+     *    - null: no escaping (default)
+     *  - 'html': htmlspecialchars()
+     *  - 'htmlall': htmlentities()
+     *  - 'url': urlencode()
+     *
+     * @var null|string escape sequence name
+     */
+    var $escape_output = null;
+
+    /**
+     * This tells Smarty what character-set to use for output encoding
+     *
+     * The character set is passed to escaping-functions, if there is a
+     * parameter for that. Default is null.
+     *
+     * @var null|string character-set
+     */
+    var $output_charset = null;
+
 /**#@+
  * END Smarty Configuration Section
  * There should be no need to touch anything below this line.
@@ -1481,6 +1504,8 @@
         $smarty_compiler->compile_id        = $this->_compile_id;
         $smarty_compiler->_config            = $this->_config;
         $smarty_compiler->request_use_auto_globals  = $this->request_use_auto_globals;
+        $smarty_compiler->escape_output     = $this->escape_output;
+        $smarty_compiler->output_encoding   = $this->output_encoding;
 
         if (isset($cache_include_path) && isset($this->_cache_serials[$cache_include_path])) {
             $smarty_compiler->_cache_serial = $this->_cache_serials[$cache_include_path];
Index: libs/Smarty_Compiler.class.php
===================================================================
RCS file: /repository/smarty/libs/Smarty_Compiler.class.php,v
retrieving revision 1.379
diff -u -r1.379 Smarty_Compiler.class.php
--- libs/Smarty_Compiler.class.php   22 Apr 2006 08:16:57 -0000   1.379
+++ libs/Smarty_Compiler.class.php   3 May 2006 09:45:09 -0000
@@ -435,15 +435,20 @@
                     ~xs', $template_tag, $match)) {
             $this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__);
         }
-       
+
         $tag_command = $match[1];
         $tag_modifier = isset($match[2]) ? $match[2] : null;
         $tag_args = isset($match[3]) ? $match[3] : null;
 
         if (preg_match('~^' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$~', $tag_command)) {
-            /* tag name is a variable or object */
+
+           /* tag name is a variable or object */
             $_return = $this->_parse_var_props($tag_command . $tag_modifier);
-            return "<?php echo $_return; ?>" . $this->_additional_newline;
+
+            /* variable gets escaped, when $Smarty->escape_output is enabled */
+            $_return_escaped = $this->_escape_var($_return, $tag_modifier);
+
+            return "<?php echo $_return_escaped; ?>" . $this->_additional_newline;
         }
 
         /* If the tag name is a registered object, we process it. */
@@ -2286,6 +2291,40 @@
                              E_USER_ERROR, __FILE__, __LINE__);
     }
 
+    /**
+     * add output-escaping around variable
+     * (called after modifiers)
+     *
+     * @param string $var_name
+     * @param string $modifier_string
+     */
+    function _escape_var($var_name, $modifier_string)
+    {
+      /* only escape if $Smarty->escape_output is set and "noescape" modifier is not used */
+        if (!is_null($this->escape_output) && !preg_match('~(^|\|)noescape($|\|)~', $modifier_string)) {
+       
+         if (is_null($this->output_charset)) {
+            $_charset = '';
+         }
+         else {
+            $_charset = ',' . $this->output_charset;
+         }
+            switch ($this->escape_output) {
+                case 'html':
+                    return "htmlspecialchars({$var_name}, ENT_QUOTES{$_charset});";
+                case 'htmlall':
+                    return "htmlentities({$var_name}, ENT_QUOTES{$_charset});";
+                case 'url':
+                    return "urlencode({$var_name});";
+                default:
+                   $this->_trigger_fatal_error("Smarty output escaping error: escapement type '$this->escape_output' is not implemented");
+           }
+        }
+        else {
+           return $var_name;
+        }
+    }
+
 }
 
 /**


any comments appreciated - would be helpful if you can construct examples, where this escaping does not work. (But remember that it should be an optional feature!)

PS: I could not find any plugin using "echo" or "print"!


Last edited by andreas on Tue Jul 20, 2010 11:58 pm; edited 1 time in total
Back to top
View user's profile Send private message
andreas
Smarty Pro


Joined: 22 Apr 2003
Posts: 106

PostPosted: Wed May 03, 2006 11:49 am    Post subject: Reply with quote

I looked at many plugins now, the "modifiers" don't seem to be an issue, because the results will be escaped, and I don't see a problem with it (perhaps "escape" modifier should be filtered in my patch too).

Than you have the "build-in" functions - I also don't see any need for a change here, and no BC problems...

Only the "custom functions" are a little bit more problematic.

Most html_* functions use the smarty_function_escape_special_chars() function, which seems like a good start. In my previous post I have already written something about that.

But there are some plugins, where input is returned without ecaping:

- cycle
- html_table
- mailto
- popup
- popup_init
- textformat

First I'm wondering, why html_table does not use smarty_function_escape_special_chars(), like other html_* functions do. So content in <option> gets escaped today, content in tables does not.

mailto, of course you can pass XSS code to an email field, so I'd like to use escaping here too. (again, remember it's only an option Wink)

and for cycle, I'm not sure, but I'd suggest to use escaping here too. Usually you do things like
Code:
{cycle values="#eeeeee,#d0d0d0"}

in your code, but perhaps some people use variables from input for the color values (or they use it for something totaly different), so I'd suggest to add escaping here. It does not buy you anything, if you add escaping only at some common places. If you want to use a "global output escaping contract", output should get escaped where ever it is possible to bypass my _escape_var() function.

Same for the other 3 functions mentioned above. I think that are the plugins which have to me modified, I'd prefer a smarty methode, which can read the $smarty->escape_output setting, to get the same escaping everywhere in your software.


Can someone tell me, why some functions already use output escaping (they enforce htmlspecialchars()), and ther (also html related funcrions) don't? Does not look standardized... which makes it even more difficult to do the escaping outside of smarty.


PS: if you can think of other problematic plugins, please let me know!


Last edited by andreas on Wed May 05, 2010 10:31 pm; edited 1 time in total
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5608
Location: Toronto, Canada

PostPosted: Wed May 03, 2006 5:01 pm    Post subject: Reply with quote

messju, monte? This would be a good time for folks to give some input Smile
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5608
Location: Toronto, Canada

PostPosted: Wed May 03, 2006 6:19 pm    Post subject: Reply with quote

I still prefer $output_escape_func rather than $escape_output both for naming consistency and for the fact that I'd rather have this passed off to a callback rather than use a "mode". This seems more inline with Smarty's typical design considerations, IMHO.
Back to top
View user's profile Send private message
andreas
Smarty Pro


Joined: 22 Apr 2003
Posts: 106

PostPosted: Thu May 04, 2006 12:22 pm    Post subject: Reply with quote

boots wrote:
I still prefer $output_escape_func rather than $escape_output both for naming consistency and for the fact that I'd rather have this passed off to a callback rather than use a "mode". This seems more inline with Smarty's typical design considerations, IMHO.


But how do you pass additional parameters then?

Most people need something like:
[php]htmlspecialchars($string, ENT_QUOTES, 'UTF-8');[/php]

The syntax I used is borrowed from "escape" modifier, so it's already known:
http://cvs.php.net/viewcvs.cgi/smarty/libs/plugins/modifier.escape.php?view=markup

But OK, that's template-syntax, not PHP.

You don't save any performance with a callback, because I write the final function call directly into the compiled template.

What about adding "user" mode, where programmers can provide an own callback-function using "$output_escape_func"? Wink

Or perhaps use $escape_output to only switch it on/off (TRUE|FALSE), and use htmlspechialchars as default for $output_escape_func?

I like $escape_output, but I'm not in the position to dictate the API Wink Most important for me is that such a feature get's added, if possible with a nice/simple API, the details are not so important for me.

If you only have $output_escape_func which takes a string with the function name, you have to create an own user-space wrapper function if you want to pass additional parameters to functions like htmlspecialchars (or anything else). Don't like that too much, and it will be a little bit slower at runtime. Perhaps add an array like $output_escape_func_params?

PS: I've also written to the smarty NG: http://news.php.net/php.smarty.dev/ (and monte responsed there already)

Last edited by andreas on Tue Jul 20, 2010 11:58 pm; edited 1 time in total
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5608
Location: Toronto, Canada

PostPosted: Thu May 04, 2006 3:58 pm    Post subject: Reply with quote

andreas wrote:

But how do you pass additional parameters then?

Most people need something like:
[php:1:c9a64dd9f2]htmlspecialchars($string, ENT_QUOTES, 'UTF-8');[/php:1:c9a64dd9f2]

The syntax I used is borrowed from "escape" modifier, so it's already known: http://cvs.php.net/viewcvs.cgi/smarty/libs/plugins/modifier.escape.php?view=markup

...

If you only have $output_escape_func which takes a string with the function name, you have to create an own user-space wrapper function if you want to pass additional parameters to functions like htmlspecialchars (or anything else). Don't like that too much, and it will be a little bit slower at runtime. Perhaps add an array like $output_escape_func_params?


Good points but the callback can be made to accept $smarty as an argument (like plugins) as you suggest (but dislike). That way it can lookup other public members if it is interested in them. In which case, it should probably be named $output_handler_func Smile Never, the less, that does lead to some overhead which is unfortunate. My main motivation is that if we add escape handling, it should be pluggable enough to allow for various styles and not be so tied to htmlspecialchars directly. The fact that you are using the same system as devised in the escape modifier is a good-thing, so I can't really argue that one too much.

Basically, I'm not married to this idea; however, I do think that at minimum, the naming should be $output_escape rather than $escape_output (to match associated $output_* vars) if we go with the system you are proposing.

At least this is moving forward a bit more than it did last time, huh? Smile

Best.
Back to top
View user's profile Send private message
andreas
Smarty Pro


Joined: 22 Apr 2003
Posts: 106

PostPosted: Thu May 04, 2006 4:39 pm    Post subject: Reply with quote

boots wrote:
Good points but the callback can be made to accept $smarty as an argument (like plugins) as you suggest (but dislike). That way it can lookup other public members if it is interested in them. In which case, it should probably be named $output_handler_func Smile

No, I don't think that's needed. An example:

[php]$smarty->output_escape_func = 'my_htmlspechialchars_wrapper';
function my_htmlspechialchars_wrapper($string) {
return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
}
[/php]

Or what do I miss? But as said, I don't like that very much, and it replaces the php-core function calls in the compiled templates against a user-space function wrapping the core function.

I think something like that is not a very nice API.

An alternative would be:
[php]$smarty->output_escape_func = 'my_htmlspechialchars_wrapper';
$smarty->output_escape_func_params = array(ENT_QUOTES, 'UTF-8');[/php]

Or use a methode with 2 params? Hm...

I still like the "modes" most, as long it's possible to add user-defined functions. But in my opinion that's an exception, and don't like to define APIs for every exception. I like to add a simple API for the most common cases, and make it possible use user-defined functions as an additional feature. But that's only my personal point of view, it's also important that smarty API remains consistent...

boots wrote:
Never, the less, that does lead to some overhead which is unfortunate. My main motivation is that if we add escape handling, it should be pluggable enough to allow for various styles and not be so tied to htmlspecialchars directly. The fact that you are using the same system as devised in the escape modifier is a good-thing, so I can't really argue that one too much.


It's a decision which you have to make. As long as I can use htmlspecialchars with parameters, everything is fine Wink But as said, I prefer a simple API for common cases, and I prefer the code which is faster at runtime. If I finally should implement escaping "modes", I will provide a way to make it possible to use user-defined callback function. But I'd like to do that as an additional feature...

boots wrote:
Basically, I'm not married to this idea; however, I do think that at minimum, the naming should be $output_escape rather than $escape_output (to match associated $output_* vars) if we go with the system you are proposing.


I think this should be possible Wink

boots wrote:
At least this is moving forward a bit more than it did last time, huh? Smile

definitly, I'm quite surprised Smile


Last edited by andreas on Tue Jul 20, 2010 11:58 pm; edited 1 time in total
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Smarty Forum Index -> General All times are GMT
Goto page 1, 2, 3  Next
Page 1 of 3

 
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