Please note, that when magic_quotes_gpc is set not only $_POST, $_GET, $_REQUEST, $_COOKIE arrays values are slashed. Actually every string value in $GLOBALS array is slashed, ie. $GLOBALS['_SERVER']['PATH_INFO'] (or $_SERVER['PATH_INFO']).

I made test and your function worked right. These were the <input ... /> names I used:name="a"name="b.b b\b"name="c[c.1]"name="c[c 2]"name="c[c\3]"name="c.c c[c.' 4]"name="c ' c[c&quot;4]"name="d&quot;[d&quot;1]"

(I used &quot; because I don't know other way to put " into the name)

and the user-input value:a ' " \ \' \" \\ a

2. > 17) The chars '.', ' ' are always replaced by '_' when used in keys.

This is true only for the top-level keys, such as "b.b b\b", "c.c c" and "c ' c" above. The second-level key "[c.' 4]" was not changed to [c_'_4] but was escaped acording to how magic_quites_XXX are set.

Tested on PHP 4.4.0.

These magic_quotes are really black magic :(

It'll be good to make test against $_SESSION, but I can't do it today.

Escaping of key-strings in GPC-arrays behave different to the escaping of their values.

First I expected that keys in submitted gpc-arrays are never escaped.
Anyway. After I saw escaped keys, I assumed they're escaped according to the settings of magic quotes.
... it's even worse...

It took me over 2 days of testing to figure out the exact behavior and creating two functions (one for each php-version) that strips slashes reliably from any array submitted to a script. Hope this saves someones time and nerves.

The following is true for $_GET- and $_POST-arrays. I hope other arrays affected by magic quotes behave equally.
I did not test the behavior for cases where magic_quotes_sybase is set.

Maybe someone is willing to test those combinations for other php-versions and with magic_quotes_sybase set to 'on' - let me know.
Sorry for this huge amount of text, but it's complete. I was unable to compress the decision table more than this.

Regarding the three main strip methods as found below (two using foreach, 1 using the json method), I've done a little benchmarking using 'true' profiling (using a registered tickhandler where declare(ticks=1)).
I wondered whether or not json would not be terribly slow.
I won't discuss the profiler, but will suffice with the following statement, followed by the used code to benchmark:

The json method was by FAR the quickest (contrary to what I'd thought), so if you need a speedy process, use that!

As can be seen above, using json speeds output by at least a factor of 5 (nearly 6).
Just wanted to share this :D

Do note the strip_json function has two LOC instead of a plain return statement, otherwise it wouldn't get picked up by the tickprofiler (it would return from the code immediately, never reaching the profiler)!

Usage of the return statement in strip_deep2 is not needed, as the argument is passed by reference.
A new test showed that the time penalty for this is about 0.09 seconds.

This actually means that the factor between strip_deep2 vs strip_json is only about 2.
Still, strip_json would be about twice as fast as strip_deep2