Почему при отключенных "магических кавычках" PHP/Wordpress продолжает автоматически экранировать мои данные POST?
Это простой вопрос со странно неуловимым ответом.
get_magic_quotes_gpc()
сообщает 0. Повторюсь, магические цитаты отключены. Магические кавычки были отключены в php.ini
(не во время выполнения).
Тем не менее, все данные POST, включая одинарные кавычки ('), экранируются при доступе в PHP. Что может быть причиной этого?
Спасибо.
Изменить: Для любопытных, это скриншот нашего phpinfo: http://img843.imageshack.us/img843/6959/screenshot20120120at552.png
Изменить: во время подготовки контрольного примера, я обнаружил общее происхождение проблемы. Мы загружаем Wordpress, поскольку наше приложение интегрируется с установкой WP Multisite. Когда я отключаю загрузку Wordpress, авто-экранирование отключается. Кто-нибудь знает, где может находиться код автоматического выхода Wordpress?
6 ответов
Я думаю, что нашел это. Проблема (ошибка): http://core.trac.wordpress.org/ticket/18322
Решение: 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);
Примечание. По предложению @Alexandar O'Mara вы можете пересмотреть вопрос о перезаписывании суперглобальных элементов следующим образом. Например, если это подходит для вашей ситуации, вы можете просто "раздеться локально", используя такую альтернативу, как $post = array_map('stripslashes_deep', $_POST);
Также см. Отличный ответ @quickshiftin.
Расширение ответа @rinogo с более глубоким объяснением и предложение другого обходного пути.
В wp-settings.php есть безусловный вызов wp_magic_quotes
// Add magic quotes and set up $_REQUEST ( $_GET + $_POST )
wp_magic_quotes();
Wordpress избегает кавычек независимо от того, что
function wp_magic_quotes() {
// If already slashed, strip.
// Escape with wpdb.
// Force REQUEST to be GET + POST.
}
Что интересно, хотя этот вызов делается после загрузки плагинов, до загрузки темы. Ооо, в верхней части вашего плагина
// 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;
Тогда вы можете свободно использовать $_REAL_POST
и др. вместо $_POST
(помня, что это глобальный, а не суперглобальный), где вам нужно. Также помните, что если ваш плагин загружен до темы, если тема вызывает одну из функций плагина, которая использует $_POST
, это следует читать из $_REAL_POST
чтобы получить неэкранированные значения.
Мне просто пришлось разобраться с этой проблемой, и я нашел довольно хороший обходной путь. Это гарантирует, что GPC никогда не будут сокращены. Я просто поместил это наверху моего файла плагина (я думаю, что это будет работать наверху темы):
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);
}
И теперь все идеально!
Лучший ответ, представленный здесь, это скопировать для собственного использования, например:
$post = array_map('stripslashes_deep', $_POST);
Однако с этим есть теоретическая проблема: поскольку вы работаете с дубликатом, вы не можете сохранять какие-либо изменения в суперглобалах (эй, я не говорю, что это хорошая практика, хорошо?).
Решение: методы доступа
В попытке разрешить этот беспорядок определенным образом и без каких-либо побочных эффектов, я сделал "методы доступа", которые прозрачно применяются stripslashes_deep()
или же addslashes_deep()*
получать / устанавливать запросы к следующим суперглобальным массивам:
* Я должен был бросить addslashes_deep()
вместе из WordPress stripslashes_deep()
,
$_GET
$_POST
$_COOKIE
$_SERVER
$_REQUEST
Вы можете использовать их как:
echo _get('username'); // echo stripslashes_deep($_GET['username']);
_cookie('name', 'value'); // $_COOKIE['name'] = addslashes_deep('value');
Вот код (я называю это gpcsr.php
):
<?php
// cat stripslashes_deep() | sed 's/stripslashes/addslashes/g'
function addslashes_deep( $value ) {
if ( is_array($value) ) {
$value = array_map('addslashes_deep', $value);
} elseif ( is_object($value) ) {
$vars = get_object_vars( $value );
foreach ($vars as $key=>$data) {
$value->{$key} = addslashes_deep( $data );
}
} elseif ( is_string( $value ) ) {
$value = addslashes($value);
}
return $value;
}
function _generic_slashes_wrap(&$arr, $key, $value = null) {
if (func_num_args() === 2) return stripslashes_deep($arr[$key]);
else $arr[$key] = addslashes_deep($value);
}
function _get ($key, $value = null) { if (func_num_args() === 1) return _generic_slashes_wrap($_GET, $key); else _generic_slashes_wrap($_GET, $key, $value); }
function _post ($key, $value = null) { if (func_num_args() === 1) return _generic_slashes_wrap($_POST, $key); else _generic_slashes_wrap($_POST, $key, $value); }
function _cookie ($key, $value = null) { if (func_num_args() === 1) return _generic_slashes_wrap($_COOKIE, $key); else _generic_slashes_wrap($_COOKIE, $key, $value); }
function _server ($key, $value = null) { if (func_num_args() === 1) return _generic_slashes_wrap($_SERVER, $key); else _generic_slashes_wrap($_SERVER, $key, $value); }
function _request ($key, $value = null) { if (func_num_args() === 1) return _generic_slashes_wrap($_REQUEST, $key); else _generic_slashes_wrap($_REQUEST, $key, $value); }
?>
Wordpress предоставляет решение для этого с помощью функции wordpress stripslashes_deep. Таким образом, фрагменты, упомянутые в ответе @ rinogo, станут такими:
$_GET = stripslashes_deep($_GET);
$_POST = stripslashes_deep($_POST);
$_COOKIE = stripslashes_deep($_COOKIE);
$_REQUEST = stripslashes_deep($_REQUEST);
Также примечание, WordPress ничего не говорит о $_SERVER
глобальная переменная, поэтому я бы предположил, что это не влияет.
WordPress добавляет косые черты в $_POST/$_GET/$_REQUEST/$_COOKIE независимо от того, что возвращает get_magic_quotes_gpc(). Поэтому в контексте WordPress при использовании этих переменных всегда следует использовать stripslashes() или stipslashes_deep().
Или просто делай как я. Закомментируйте всю реализацию в методе wp_magic_quotes() load.php.
Я не использую магические цитаты. Это вызвало у меня гораздо больше головных болей, чем оно того стоило. Лично я предпочитаю придерживаться собственной дисциплины санитарии. Я просто не хочу начинать формировать вредные привычки программирования.
Но я понимаю принуждение WordPress включить такую "функцию". Возможно, сообществу разработчиков лучше всего воспользоваться глобальной возможностью его отключения.