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.