With "magic quotes" disabled, why does PHP/WordPress continue to auto-escape my POST data?
I think I found it. Problem (bug): http://core.trac.wordpress.org/ticket/18322
Solution: http://codex.wordpress.org/Function_Reference/stripslashes_deep
$_GET = array_map('stripslashes_deep', $_GET); $_POST = array_map('stripslashes_deep', $_POST); $_COOKIE = array_map('stripslashes_deep', $_COOKIE); $_SERVER = array_map('stripslashes_deep', $_SERVER); $_REQUEST = array_map('stripslashes_deep', $_REQUEST);
Note: As suggested by @Alexandar O'Mara, you might want to reconsider overwriting the superglobals like this. If it's appropriate for your situation, for example, you might just "strip locally" using an alternative like $post = array_map('stripslashes_deep', $_POST);
Also see @quickshiftin's excellent answer.
Expanding on @rinogo's answer with a deeper explanation, and offering another workaround.
In wp-settings.php there's an unconditional call to wp_magic_quotes
// Add magic quotes and set up $_REQUEST ( $_GET + $_POST )wp_magic_quotes();
WordPress escapes quotes no matter what
function wp_magic_quotes() { // If already slashed, strip. // Escape with wpdb. // Force REQUEST to be GET + POST.}
What's interesting though is this call is made after plugins have been loaded, before the theme is loaded. Sooo, at the top of your plugin
// A hack to cope with un-configurable call to wp_magic_quotes// E.G. Make the original $_POST available through a global $_REAL_POST$_REAL_GET = $_GET;$_REAL_POST = $_POST;$_REAL_COOKIE = $_COOKIE;$_REAL_REQUEST = $_REQUEST;
Then you can freely use $_REAL_POST
et al. in place of $_POST
(remembering it's a global, not a superglobal) where you need to. Also remember that while your plugin has loaded before the theme, if the theme calls down into one of the plugin functions which uses $_POST
, it should read from $_REAL_POST
to get the unescaped values.
I just had to deal with this issue and found what I think is a pretty nice workaround. It ensures that the GPCs are never slashed. I just put this at the top of my plugin file (it would work at the top of a theme too, I think):
add_action( 'init', 'unslash_gpc' );function unslash_gpc() { $_GET = array_map('stripslashes_deep', $_GET); $_POST = array_map('stripslashes_deep', $_POST); $_COOKIE = array_map('stripslashes_deep', $_COOKIE); $_SERVER = array_map('stripslashes_deep', $_SERVER); $_REQUEST = array_map('stripslashes_deep', $_REQUEST);}
And now everything is perfect!