magic_quotes_gpc - how to handle in PHP 5.3 and 6.0

I saw that in the PHP documentation, magic_quotes_gpc is depreciated in PHP 5.3, and removed in 6.0

How is the best way to handle detection for magic_quotes_gpc in 5.2.x and remove the extra slashes from input, and work for 5.3.x and 6.x?

<?php

	$var_name = "";
	$var_box = "";
	
	if(isset($_POST['submit_text'])){
		//$var_name = trim($_POST['name']);
		//$var_box = trim($_POST['box']);
		$var_box = ini_get( 'magic_quotes_gpc' ) ? stripslashes( trim($_POST['box']) ) : trim($_POST['box']);
		$var_name = ini_get( 'magic_quotes_gpc' ) ? stripslashes( trim($_POST['name']) ) : trim($_POST['name']);
	}
?>
<html><body>

<form action="<?php echo basename($_SERVER['PHP_SELF']); ?>" method="post">

<textarea name="name" cols="10" rows="8"><?php echo htmlspecialchars($var_name); ?></textarea>

<input name="box" type="text" value="<?php echo htmlspecialchars($var_box); ?>" />

<button name="submit_text" type="submit">Submit</button>

</form>

</body></html>

It can help to use a separate class with which to retrieve and process the global variables.

For example:


class Helper
{
    private $_post;
    ...
    public function __construct()
    {
        $this->_post = $_POST;
        ...
    }
    private function getStrippedValue($var, $default)
    {
        if (get_magic_quotes_gpc() === 1) {
            $var = stripslashes($var);
        }
        if (strlen($var) < 1) {
            $var = $default;
        }
        return $var;
    }
    public function post($key, $default = '')
    {
        $value = $default;
        if (isset($this->_post[$key])) {
            $value = $this->_post[$key];
        }
        return $this->getStrippedValue($value, $default);
    }
    ...
}
?>

The … characters above indicate where additional code can be placed, to handle other globals such as $_GET

How you might use the above class is:


require_once 'Helper.php';
$helper = new Helper();
...
$personId = $helper->post('personid');

It’s 2010. How about just turning it off completely in php.ini and forgetting it exists?

Perhaps because you don’t have access to the ini, and htaccess is disabled :frowning:
If so, best to use this code to disable http://www.php.net/manual/en/security.magicquotes.disabling.php

Two reasons.

  1. you may be dealing with a legacy codebase that wouldn’t survive just turning it off. By using a class to retrieve and sanitize the values you can ensure that all globals are being safely managed, and then make the change.

  2. It makes testing a lot easier. Instead of the code directly accessing global variables, you can provide a mockup of the Helper class and automatcally return your own test values.
    See: http://www.simpletest.org/en/mock_objects_documentation.html
    See: http://www.phpunit.de/manual/3.0/en/mock-objects.html

I’m gonna disagree with you Paul :frowning:
The question is how to disable magic quotes. This is a server directive, if it can’t be disabled there, then the next best thing is to disable it in a boot script - at the entry point, not all over your classes/functions. That is, it needs to be disabled, not disabled sometimes, disabled full stop.

How would you suggest that the OP manages global variables in his existing code so that they will continue to work properly as he migrates from 5.2, to 5.3, and to 6.0. I believe that is what the OP is asking about.

The topic of how to handle $_GET, $_POST and others when 6.0 rolls around has been floating about for a while.

For example, recently at stackoverflow.com this code was suggested, to pre-process the globals.


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

On my personal server, sure, I can turn magic quotes off. On other servers…no, I wouldn’t have access to it.

Without turning the code into spaghetti, I was looking for a one-shot solution to effectively neutralize magic quotes for the entire script if it was turned on.

I did find this code splice…but it doesn’t actually remove the slashes when included before any $_POST work. I’m guessing the concept works, but the actual example code doesn’t:

	//if magic quotes is on, remove the slashes it adds to input
	if (get_magic_quotes_gpc()) {
	    foreach (array('_GET', '_POST', '_COOKIE', '_REQUEST') as $src) {
	        foreach ($$src as $key => $val) {
	            $$src[$key] = stripslashes($val);
	        }
	    }
	}

post 4
is there a fault with the code on the php manual page specifically written to disable magic quotes?

@paul, one of us is confused, what migration?

ok, so it looks like I was starting to wander in the general direction.

I tried that example code, but I got an error:

syntax error, unexpected ‘&’ on foreach (array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST) as &$array) {

Something’s wrong with one of the references?

I changed the $array variable, fixed the stripslashes() function names, but it doesn’t actually strip the slashes.

My reading of the original post is that he wants a way to “handle detection for magic_quotes_gpc in 5.2.x and remove the extra slashes from input” in a way that will also “work for 5.3.x and 6.x”

He’s after a coding technique that will work across 5.2, 5.3 and into 6.0

If you still think otherwise Hash, further confirmation from Force Flow is always an option.

how to disable magic_quotes gpc in 5.x -> 6

  1. edit the php.ini file

; Magic quotes
;

; Magic quotes for incoming GET/POST/Cookie data.
magic_quotes_gpc = Off

; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.
magic_quotes_runtime = Off

; Use Sybase-style magic quotes (escape ' with '' instead of \\').
magic_quotes_sybase = Off

can’t do that?
2. htaccess


php_flag magic_quotes_gpc Off

can’t do that?
3. Use this code at the start of your script


if (get_magic_quotes_gpc()) {
    $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);
}

how to handle detection in any php version


if(ini_get('magic_quotes_gpc') {
    // will be empty string if this directive does not exist
    // or true/false if it does
    // either way false if it is disabled

how to get rid of it in any php version? use the code posted on the php manual page

Thank you Hash. Your post here is going to be my reference on this issue from here-on in.

I copy pasted the manual page I linked in post 4 … :rolleyes:

That’s it exactly :slight_smile:

Hash, I missed the page you linked to: http://www.php.net/manual/en/security.magicquotes.disabling.php

Yes, the code provided there does work…I just tried it.

One thing I noticed through looking at these code examples…some of the examples remove the slashes from the keys…if that’s what you’re supposed to do, would this also work?

if(ini_get('magic_quotes_gpc') ){
    function stripslashes_gpc(&$value){ $value = stripslashes($value);}
    array_walk_recursive($_GET, 'stripslashes_gpc');
    array_walk_recursive($_POST, 'stripslashes_gpc');
    array_walk_recursive($_COOKIE, 'stripslashes_gpc');
    array_walk_recursive($_REQUEST, 'stripslashes_gpc');
}

It seems to me that this method might be a little more efficient than the other block of code. Or is there a reason not to do it this way? (remember, I don’t care about PHP4, so a PHP5-only technique will fit the bill too)

it won’t strip slashes from the keys

The above server-side code works on 5.2, but as the Deprecated features in PHP 5.3.x page says, the use of magic_quotes_gpc, magic_quotes_runtime or magic_quotes_sybase in 5.3 will throw a deprecated error on startup.

it seems that each version has different acceptable ways of disabling magic quotes.

5.2 - ini directives, .htaccess and code
6.0 - .htaccess? or historical code, otherwise no issue

Is 5.3 where you would use just .htaccess followed up if not possible by code?

I would think using ini_get(‘magic_quotes_gpc’) would be a more failsafe way, like hash says, instead of using the depreciated/removed functions