Почему при отключенных «магических кавычках» PHP / Wordpress продолжает автоматически экранировать мои данные POST?

30

Это простой вопрос с странно неуловимым ответом.

get_magic_quotes_gpc() сообщает 0. Повторяю, магические кавычки отключены. Магические кавычки, по-видимому, были отключены в php.ini (не во время выполнения).

Тем не менее, все POST-данные, включая одинарные кавычки ('), экранируются при доступе к PHP. Что может быть причиной этого?

Спасибо.


Изменить: Для любопытных это скриншот нашей phpinfo: http://img843.imageshack.us/img843/6959/screenshot20120120at552.png


Изменить: при подготовке тестового примера я обнаружил общее происхождение проблемы. Мы загружаем Wordpress, так как наше приложение интегрируется с установкой WP Multisite. Когда я отключу загрузку Wordpress, автоматическое экранирование отключено. Кто-нибудь знает, где может быть найден код автозапуска Wordpress?

  • 3
    Пожалуйста, покажите нам краткий тестовый скрипт, который производит это поведение для вас. Возможно проблема только в методе тестирования.
  • 0
    Вы можете проверить заголовки, которые отправляет ваш браузер.
Показать ещё 2 комментария
Теги:
escaping

6 ответов

35
Лучший ответ

Я думаю, что нашел. Проблема (ошибка): 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 отличный ответ.

  • 12
    Спасибо, что поделились информацией о таком насмешке
  • 2
    через 2 года у нас все еще есть этот баг. Обратите внимание, что вы не можете использовать это несколько раз, поэтому, если вы используете его, другой плагин использует его, результат будет непредсказуемым.
Показать ещё 4 комментария
12

Развернувшись на @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.
}

Интересно, что этот вызов выполняется после того, как плагины были загружены до загрузки темы. Sooo, наверху вашего плагина

// 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 et al вместо $_POST (помните, что это глобальный не суперглобал), где вам нужно. Также помните, что, пока ваш плагин загрузил перед темой, если тема вызывается в одну из функций плагина, которая использует $_POST, она должна читать из $_REAL_POST, чтобы получить неэкранированные значения.

  • 0
    Интересное решение! У вас уже есть это конкретное решение, работающее в плагине?
  • 0
    @rinogo Да, я подключил его прошлой ночью, он работает как шарм!
Показать ещё 9 комментариев
0

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() при использовании этих переменных.

  • 0
    Только в WordPress вы сначала экранируете данные, а затем выкручиваете их в следующей строке.
  • 0
    @ Твой здравый смысл, ирония, верно? Wordpress всегда делал подобные вещи, и через несколько лет вы получаете новую версию с возможностью отключить реальную функциональность, определив константу в wp-config или что-то в этом роде ...
0

Мне просто пришлось иметь дело с этой проблемой и найти то, что, по моему мнению, довольно приятное решение. Это гарантирует, что 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);
}

И теперь все идеально!

  • 0
    Но, чтобы быть ясным, это также постоянно изменяет суперглобальные перемены, верно?
  • 0
    (Например, все другие плагины / темы / ядро также будут снабжены значениями, не заключенными в магические кавычки? Возможно, лучше вместо этого использовать переменные в рамках плагина. Независимо от того, мне нравится ваше решение!)
0

Лучший ответ, приведенный здесь, - скопировать для собственного использования, например:

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

?>
-2

Или просто делай, как я. Прокомментируйте всю реализацию в методе load.php wp_magic_quotes().

Я не использую магические цитаты. Это вызывало у меня гораздо больше головных болей, чем того стоило. Лично я предпочитаю поддерживать свою собственную дисциплину в области санитарии. Я просто не хочу начинать формировать плохие привычки программирования.

Но я понимаю, что принуждение WordPress включать такую ​​ "особенность". Возможно, сообщество разработчиков лучше всего будет использовать глобальный вариант, чтобы отключить его.

  • 0
    Если это решение работает для вас, то отлично! Однако следует обратить внимание на две потенциальные проблемные области: 1) Модификация ядра подвержена ошибкам и даже опасна (с точки зрения безопасности), особенно в отношении чего-то вроде побега. 2) Многие плагины предназначены для удобной работы с wp_magic_quotes (). Изменение этой реализации может изменить их поведение. Подробнее о том, как сохранить / убить wp_magic_quotes (): core.trac.wordpress.org/ticket/18322
  • 0
    Смотрите мой комментарий к @adamj под моим решением, это не очень хорошая идея, так как вы нарушите код Wordpress, который ожидает, что эти значения будут экранированы.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню