Welcome Guest, Not a member yet? Register   Sign In
form_prep appears to be broken in 1.7.2 html entities are no longer protected. Or was it broken before?
#1

[eluser]brookerrj[/eluser]
In 1.7.1 form_prep() would not try to convert html entities already existing in a string. This was good because when an html string containing html entities was stored in a DB and then retrived for editing in a form they would be protected from conversion and look correct in a form field, E.g. Bob's Name in the database is loaded into a form text field without conversion and is displayed in the form field as Bob's Name.

In 1.7.2 form_prep() existing html entities are not protected and are parsed corrupting the data so that Bob's Name in the database becomes Bob's Name and when loaded into a text field is displayed as Bob's Name.

Unfortunately I am using form helper functions (which all use form_prep() as standard) like form_input() throughout my application .

For quick reference:
1.7.1 code looks like:

Code:
function form_prep($str = '')
    {
        // if the field name is an array we do this recursively
        if (is_array($str))
        {
            foreach ($str as $key => $val)
            {
                $str[$key] = form_prep($val);
            }

            return $str;
        }

        if ($str === '')
        {
            return '';
        }

        $temp = '__TEMP_AMPERSANDS__';

        // Replace entities to temporary markers so that
        // htmlspecialchars won't mess them up
        $str = preg_replace("/&#(\d+);/", "$temp\\1;", $str);
        $str = preg_replace("/&(\w+);/",  "$temp\\1;", $str);

        $str = htmlspecialchars($str);

        // In case htmlspecialchars misses these.
        $str = str_replace(array("'", '"'), array("'", """), $str);

        // Decode the temp markers back to entities
        $str = preg_replace("/$temp(\d+);/","&#\\1;",$str);
        $str = preg_replace("/$temp(\w+);/","&\\1;",$str);

        return $str;
    }

1.7.2 code looks like:

Code:
function form_prep($str = '', $field_name = '')
    {
        static $prepped_fields = array();
        
        // if the field name is an array we do this recursively
        if (is_array($str))
        {
            foreach ($str as $key => $val)
            {
                $str[$key] = form_prep($val);
            }

            return $str;
        }

        if ($str === '')
        {
            return '';
        }

        // 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;
        }
        
        $str = htmlspecialchars($str);

        // In case htmlspecialchars misses these.
        $str = str_replace(array("'", '"'), array("'", """), $str);

        if ($field_name != '')
        {
            $prepped_fields[$field_name] = $str;
        }
        
        return $str;
    }
#2

[eluser]Felix Egli[/eluser]
I have the same problem with form_prep. I think form_prep should do, whats written in the documentation: replace quotes.

If i comment out all the $prepped_fields and htmlspecialchers stuff, form_prep works perfectly for me.

Code:
function form_prep($str = '', $field_name = '')
    {
#        static $prepped_fields = array();
        
        // if the field name is an array we do this recursively
        if (is_array($str))
        {
            foreach ($str as $key => $val)
            {
                $str[$key] = form_prep($val);
            }

            return $str;
        }

        if ($str === '')
        {
            return '';
        }

        // 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;
#        }
#        
#        $str = htmlspecialchars($str);

        // In case htmlspecialchars misses these.
        $str = str_replace(array("'", '"'), array("'", """), $str);

#        if ($field_name != '')
#        {
#            $prepped_fields[$field_name] = $str;
#        }
        
        return $str;
    }
#3

[eluser]darrenm[/eluser]
I've just come across the same problem.

I've got a form that gets it's default values populated from either the database or (if it comes back invalid) the last Post submission.

It's important to run through set_value() (and therfore form_prep()) to remove nasty characters from the user submission, but if there is pre-encoded data in the database (for example &ampWink, then we end up with double-encoding - e.g. &

As a workaround, I've introduced a new function:

Code:
function fix_form_prep($str) {

    $find = array('&','"',''',''','&gt','&lt');
    $replace = array('&','"',''',''','>', '<');

    return str_replace($find,$replace,$str);

}

I then call this after the offending htmlspecialchars in form_prep
Code:
$str = htmlspecialchars($str);
$str = fix_form_prep($str);

This is working, but it lack elegance for me - there must be a better way?

NOTE: the encoding on this forum has scrambled the above function a bit, but you should get the idea.
#4

[eluser]Stu Green[/eluser]
Hi all,

I experienced the same problem. I was prepping form fields before. Now with the new update, all my textareas that contained HTML code were showing as & lt ; etc. I wasn't aware this would happen, and it broke a lot of websites and kept me up last night.

I ended up by just removing the prepping for set_value(), because it now happens automatically if you look at the form helpers (e.g. form_textarea() );

Stu
#5

[eluser]kenjis[/eluser]
CI should use 1.7.1's no double encoding code again.

Code:
$temp = '__TEMP_AMPERSANDS__';

        // Replace entities to temporary markers so that
        // htmlspecialchars won't mess them up
        $str = preg_replace("/&#(\d+);/", "$temp\\1;", $str);
        $str = preg_replace("/&(\w+);/",  "$temp\\1;", $str);

        $str = htmlspecialchars($str);

        // In case htmlspecialchars misses these.
        $str = str_replace(array("'", '"'), array("'", """), $str);

        // Decode the temp markers back to entities
        $str = preg_replace("/$temp(\d+);/","&#\\1;",$str);
        $str = preg_replace("/$temp(\w+);/","&\\1;",$str);

Or

Code:
$temp = '__TEMP_AMPERSANDS__';

        // Replace entities to temporary markers so that
        // htmlspecialchars won't mess them up
        $str = preg_replace("/&#(\d+);/", "$temp\\1;", $str);
        $str = preg_replace("/&(\w+);/",  "$temp\\1;", $str);

        $str = htmlspecialchars($str, ENT_QUOTES, config_item('charset'));

        // Decode the temp markers back to entities
        $str = preg_replace("/$temp(\d+);/","&#\\1;",$str);
        $str = preg_replace("/$temp(\w+);/","&\\1;",$str);
#6

[eluser]kenjis[/eluser]
[quote author="Kenji @ CodeIgniter Users Group in Japan" date="1266063088"]CI should use 1.7.1's no double encoding code again.
[/quote]

This is right when we think comaptibility is more important.

But 1.7.2's code is clean and better when we think that to store an html string containing html entities in a DB is bad practice.

Because html entities are only needed in html output. If you store an html string containing html entities in a DB, you must decode html entities when you mail the data.
If you want to seach the data, you must convert your keyword to html entities.

If you use 1.7.1 code, a string like "& must be written as &_amp;" is not processed correctly. Oh, this forum also, I add "_" after last "&" intentionlally.
#7

[eluser]Felix Egli[/eluser]
Quote:But 1.7.2's code is clean and better when we think that to store an html string containing html entities in a DB is bad practice.

this form_prep in 1.7.2 is not clean at all. its badly broken and must be fixed.

unfortunately it does not look like, this function gets fixed. :-(

i will use kohana for new projects.
#8

[eluser]rip_pit[/eluser]
[quote author="darrenm" date="1265932448"]
As a workaround, I've introduced a new function:

Code:
function fix_form_prep($str) {

    $find = array('&','"',''',''','&gt','&lt');
    $replace = array('&','"',''',''','>', '<');

    return str_replace($find,$replace,$str);

}

I then call this after the offending htmlspecialchars in form_prep
Code:
$str = htmlspecialchars($str);
$str = fix_form_prep($str);

This is working, but it lack elegance for me - there must be a better way?
[/quote]
your fix seems to work fine Smile thanks for the code

Hope we can count on an official fix for this annoying behavir
i searched but i couldn't found no fix nor infos except yours

i'm not blaming the C.I. team coz they already do a huge and good work but I dislike modifying the main core files that might be overwritten at next update
#9

[eluser]janogarcia[/eluser]
No changes on the repository yet http://bitbucket.org/ellislab/codeignite...php#cl-593

I've submitted it to the bug tracker http://codeigniter.com/bug_tracker/bug/11889/
#10

[eluser]rip_pit[/eluser]
[quote author="janogarcia" date="1269093394"]No changes on the repository yet http://bitbucket.org/ellislab/codeignite...php#cl-593

I've submitted it to the bug tracker http://codeigniter.com/bug_tracker/bug/11889/[/quote]

strange that it wasn't listed. thank you for submiting it Wink




Theme © iAndrew 2016 - Forum software by © MyBB