Re: [patch] add $smarty->escape_output feature

Pedro <[email protected]> Thu, 04 May 2006 23:59:20 +0100
Newsgroups gmane.comp.php.smarty.devel
Message-ID <[email protected]>
Monte Ohrt wrote:
> Off the top of my head, you have to be careful to not escape the values 
> when they are not direct output.

Agreed !
> 
> example:
> 
> $smarty->assign('foo','<bar>');
> 
> {$foo} <-- variable output, so escape so it comes out &lt;bar&gt;
> 
> {if $foo eq "<bar>"} <-- do not escape $foo here, it is in an IF condition
> 
This is a pathetic/extreme example.. If anyone even uses this kind of 
code with smarty they "should be taken out way before dawn and shot with 
a blunt bone arrow"

Whilst I understand the "extreme realms of possibility" are being 
considered, I do not consider it valid !!!

automatically "escaping" output would be invaluable and imho as default 
would be very nice indeed.

And whilst were on a subject ?
Anyone written an output filter than converts
<a href="{$SCRIPT_NAME}?foo=baa&hi=ho&this=that">A & M</a>
to
<a href="{$SCRIPT_NAME}?foo=baa&amp;hi=ho&amp;this=that">A & M</a>


pete :-)



> 
> 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