Welcome Guest, Not a member yet? Register   Sign In
set_value html_escape twice
#1

Hello,

Since Codeigniter 3, set_value, by its new default third parameter value, escapes values before returning them.

This is a problem when you make form HTML inputs using the form_helper like this :
PHP Code:
echo form_input("explanation"set_value("explanation"$ruleObject['explanation'])); 

set_value uses html_escape and form_input uses html_escape too : A big issue for example with quote characters.

My workaround was to set html_escape default value to FALSE in the form_helper.

Any other idea ?
Reply
#2

actually, the set_value() always escaped the output. The new third parameter was created to allow you NOT to escape the value (if you set it to FALSE). But you are right about form_input() escaping values. Could you show me how you did the workaround?
Reply
#3

(08-05-2015, 06:18 AM)Avenirer Wrote: actually, the set_value() always escaped the output. The new third parameter was created to allow you NOT to escape the value (if you set it to FALSE). But you are right about form_input() escaping values. Could you show me how you did the workaround?

I think you're wrong about the previous escaping of set_value().  This was the previous version (I downloaded it Nov 2011) :
PHP Code:
    function set_value($field ''$default '')
    {
        if (
FALSE === ($OBJ =& _get_validation_object()))
        {
            if ( ! isset(
$_POST[$field]))
            {
                return 
$default;
            }

            return 
form_prep($_POST[$field], $field);
        }

        return 
form_prep($OBJ->set_value($field$default), $field);
    } 


This is the CI3 version :
PHP Code:
    function set_value($field$default ''$html_escape TRUE)
    {
        
$CI =& get_instance();

        
$value = (isset($CI->form_validation) && is_object($CI->form_validation) && $CI->form_validation->has_rule($field))
            ? 
$CI->form_validation->set_value($field$default)
            : 
$CI->input->post($fieldFALSE);

        isset(
$value) OR $value $default;
        return (
$html_escape) ? html_escape($value) : $value;
    } 

This is my workaround in the MY_form_helper.php :
PHP Code:
    function set_value($field$default ''$html_escape FALSE)
    {
        
$CI =& get_instance();

        
$value = (isset($CI->form_validation) && is_object($CI->form_validation) && $CI->form_validation->has_rule($field))
            ? 
$CI->form_validation->set_value($field$default)
            : 
$CI->input->post($fieldFALSE);

        isset(
$value) OR $value $default;
        return (
$html_escape) ? html_escape($value) : $value;
    } 
Reply
#4

In the older versions form_prep() was actually htmlspecialchars(). So... it was always escaped Smile
Reply
#5

So in your workaround, you simply changed the default value of the third parameter to FALSE? Why not simply do this?


PHP Code:
function set_value($field$default ''$html_escape FALSE)
{
  
parent::set_value()

Reply
#6

(08-05-2015, 12:29 PM)Avenirer Wrote: So in your workaround, you simply changed the default value of the third parameter to FALSE? Why not simply do this?



PHP Code:
function set_value($field$default ''$html_escape FALSE)
{
 
 parent::set_value()


Aside from obviously ignoring parameters and the actual return value, because it's a global function - it can't have a parent.
Reply
#7

(This post was last modified: 08-06-2015, 02:01 AM by FnX.)

(08-05-2015, 12:53 PM)Narf Wrote:  it can't have a parent.

Exactly, this is not an object Smile


I think I found the actual issue. It is the html_escape function definition in Common.php. I changed the new doubleEncode default parameter to false and everything looks fine now.

This is in Codeigniter2 :
PHP Code:
    function html_escape($var)
    {
        if (
is_array($var))
        {
            return 
array_map('html_escape'$var);
        }
        else
        {
            return 
htmlspecialchars($varENT_QUOTESconfig_item('charset'));
        }
    } 

This is in code igniter 3 :

PHP Code:
    /**
     * Returns HTML escaped variable.
     *
     * @param    mixed    $var        The input string or array of strings to be escaped.
     * @param    bool    $double_encode    $double_encode set to FALSE prevents escaping twice.
     * @return    mixed            The escaped string or array of strings as a result.
     */
    
function html_escape($var$double_encode TRUE)
    {
        if (empty(
$var))
        {
            return 
$var;
        }
        
        if (
is_array($var))
        {
            return 
array_map('html_escape'$vararray_fill(0count($var), $double_encode));
        }

        return 
htmlspecialchars($varENT_QUOTESconfig_item('charset'), $double_encode);
    } 

The new third parameter id set to true. I set it to false as a default value and this solves most of my problems (I found another problem in the form_dropdown function of form_helper.php which was not escaping the option $key/$val and now is (so there is my htmlspecialchars. now in conflict with the new one. avoiding double escape helps)

BTW this is strange because htmlspecialchars says its default is to escape everything ...
Reply
#8

This is a parameter so that you can alter its value dynamically. You are NOT supposed to modify the framework's files.
Reply
#9

As Narf said, you're not supposed to modify the framework's files. The parameter was added specifically so you could do this:

PHP Code:
echo form_input("explanation"set_value("explanation"$ruleObject['explanation'], false)); 

The documentation for set_value() even states this:
Quote:The third (optional) parameter allows you to turn off HTML escaping of the value, in case you need to use this function in combination with i.e. form_input() and avoid double-escaping.
Reply
#10

I just found what was going wrong using the debug mode !
The form_prep method has a fallback case when the field has already been prepped.
This case was preventing my values to be double encoded !
Now there is no more strange case like that (because it's not safe at all).

PHP Code:
// we've already prepped a field with this name
// @todo need to figure out a way to namespace this so
// that we know the *exact* field and not just one with
// the same name
if (isset($prepped_fields[$field_name]))
{
return 
$str;



So as you say either I change the framework's files which is bad. Either I change my 146 usage of set_value() ... I prefer not to panic people changing all the versioned files ... 
Reply




Theme © iAndrew 2016 - Forum software by © MyBB