PHP - Shorter Magic Quotes Solution
Asked Answered
S

3

0

I'm writing a app that needs to be portable. I know I should disable magic quotes on the PHP configuration but in this case I don't know if I can do that, so I'm using the following code:

if (get_magic_quotes_gpc() === 1)
{
    $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);

    while (list($key, $val) = each($process))
    {
        foreach ($val as $k => $v)
        {
            unset($process[$key][$k]);

            if (is_array($v))
            {
                $process[$key][stripslashes($k)] = $v;
                $process[] = &$process[$key][stripslashes($k)];
            }

            else
            {
                $process[$key][stripslashes($k)] = stripslashes($v);
            }
        }
    }

    unset($process);
}

To simplify the process of disabling magic quotes I had the following idea:

if (get_magic_quotes_gpc() === 1)
{
    foreach (array('GET', 'POST', 'COOKIE', 'REQUEST') as $array)
    {
        ${'_'.$array} = unserialize(stripslashes(serialize(${'_'.$array})));
    }
}

But I tried and I got an error I'm unable to understand, for instance with ?name=O'Reilly:

serialize($_GET); // a:1:{s:4:"name";s:9:"O\'Reilly";}
stripslashes(serialize($_GET)); // a:1:{s:4:"name";s:9:"O'Reilly";}

But unserialize(stripslashes(serialize($_GET))) gives me this weird error:

Notice: unserialize(): Error at offset 30 of 32 bytes


EDIT: Due to the length attribute in serialize() I changed the code to use JSON functions:

if (get_magic_quotes_gpc() === 1)
{
    foreach (array('GET', 'POST', 'COOKIE', 'REQUEST') as $array)
    {
        ${'_' . $array} = json_decode(stripslashes(json_encode(${'_' . $array})), true);
    }
}

However now the $_GET array is coming up empty, can anyone explain me why?

Sculpturesque answered 16/1, 2010 at 14:55 Comment(4)
As far as I know, they won't actually remove get_magic_quotes_gpc in PHP 6, exactly because it's going to break these kind of scripts for no reason, so people convinced them that it would be a silly thing to do. Instead, it will just be marked as deprecated. Just something to keep in mind if you want to simplify the code a bit.Shemikashemite
@Michael: The manual (pt2.php.net/manual/en/security.magicquotes.php) still says otherwise: This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 6.0.0.Sculpturesque
No, that's the part of the manual talking about magic quotes as a feature - which is indeed going to be removed. The in-progress NEWS file for PHP6 (svn.php.net/viewvc/php/php-src/trunk/…) states "Changed get_magic_quotes_gpc(), get_magic_quotes_runtime to always return false and set_magic_quotes_runtime() to raise an E_CORE_ERROR.", so the functions for checking if they're enabled are still there.Shemikashemite
@Michael: Thanks, it's nice to know that. =)Sculpturesque
S
1

Solved it, I had to use the JSON_HEX_APOS flag in json_encode():

if (get_magic_quotes_gpc() === 1)
{
    $_GET = json_decode(stripslashes(json_encode($_GET, JSON_HEX_APOS)), true);
}

Before (mqgpc.php?name[got'cha]=O'Reilly):

Array
(
    [name] => Array
        (
            [got\'cha] => O\'Reilly
        )
)

After (mqgpc.php?name[got'cha]=O'Reilly):

Array
(
    [name] => Array
        (
            [got'cha] => O'Reilly
        )
)
Sculpturesque answered 16/1, 2010 at 16:17 Comment(0)
S
2

I don't think the second version will work. Serialized strings are stored along with their length, if you are removing characters, you would need to update that length value. I would rather implement it this way to improve readability:

function strip_slashes_recursive(&$value) {
    if (!is_array($value)) {
        $value = strip_slashes($value);
    } else {
        foreach (array_keys($value) as $key) {
            $arrayValue = strip_slashes_recursive($value[$key]);
            unset($value[$key]);
            $value[strip_slashes($key)] = $arrayValue;
        }
    }
}

foreach (array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST) as &$array) {
    strip_slashes_recursive($array);
}
// don't forget to unset references or it can lead to very nasty bugs
unset($array);
Sauer answered 16/1, 2010 at 15:16 Comment(0)
S
1

Solved it, I had to use the JSON_HEX_APOS flag in json_encode():

if (get_magic_quotes_gpc() === 1)
{
    $_GET = json_decode(stripslashes(json_encode($_GET, JSON_HEX_APOS)), true);
}

Before (mqgpc.php?name[got'cha]=O'Reilly):

Array
(
    [name] => Array
        (
            [got\'cha] => O\'Reilly
        )
)

After (mqgpc.php?name[got'cha]=O'Reilly):

Array
(
    [name] => Array
        (
            [got'cha] => O'Reilly
        )
)
Sculpturesque answered 16/1, 2010 at 16:17 Comment(0)
S
0

I usually solve that problem this way:

function smagic($params){
    if(get_magic_quotes_gpc()){
        if(!is_array($params))
            return stripslashes($params);
        else
            return array_combine( array_map('stripslashes',array_keys($params)), array_map('smagic',array_values($params)) );
    }
}

And then, for $_GET:

$_GET = smagic($_GET);
Strike answered 16/1, 2010 at 16:0 Comment(2)
Doesn't handle array keys. =\Sculpturesque
@AlixAxel You were right: Check now that I've corrected the bug ;)Strike

© 2022 - 2024 — McMap. All rights reserved.