Re: [patch] add $smarty->escape_output feature
Monte Ohrt <[email protected]> Wed, 03 May 2006 21:04:09 -0500
| Newsgroups | gmane.comp.php.smarty.devel |
|---|---|
| Message-ID | <[email protected]> |
Off the top of my head, you have to be careful to not escape the values
when they are not direct output.
example:
$smarty->assign('foo','<bar>');
{$foo} <-- variable output, so escape so it comes out <bar>
{if $foo eq "<bar>"} <-- do not escape $foo here, it is in an IF condition
Andreas Korthaus wrote:
> Hi!
>
> I've had a discussion with boots in the smarty forum about a new,
> optional(!) smarty feature for general output escaping, which should
> not break BC. The idea is to provide means for projects, which like to
> use something like a contract, which ensures, that every output from
> user-input in smarty template gets escaped if a special, new Smarty
> member variable ($smarty->escape_output) is set (the used
> escape-function is modifiable). Other template engines provide
> something like that (e.g. flexy, savant), in Smarty this is not
> possible today (forget about default_modifiers).
>
> You can find the discussion here:
>
> http://www.phpinsider.com/smarty-forum/viewtopic.php?t=7806
>
> Attatched you can find a patch against CVS-HEAD, which implements the
> basic functionality. It's not ready yet, because I did not catch every
> point where input get's displayed without escaping.
>
> From what I understand the smarty code, I think I have catched
> everything beside some of the plugins. But I'm not sure here, so I'd
> be very happy if someone with better knowledge of the smarty compiler
> could check if it's OK.
>
> And I'd like to know what your general opinion about such a feature is.
>
>
> Best regards
> Andreas
> ------------------------------------------------------------------------
>
> 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('~(^|\|)(no)?escape($|\|)~', $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;
> + }
> + }
> +
> }
>
> /**
>
--
Smarty Development Mailing List (http://smarty.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php