Противоядие от magic_quotes_gpc()?

Я видел десятки фрагментов PHP, которые выглядят так:

function DB_Quote($string)
{
    if (get_magic_quotes_gpc() == true)
    {
        $string = stripslashes($string);
    }

    return mysql_real_escape_string($string);
}

Что произойдет, если я позвоню DB_Quote("the (\\) character is cool");? (Спасибо, JSPCAL!)

Разве мы не должны снимать косые черты только тогда, когда get_magic_quotes_gpc() == true и значение возникло из $_GET, $_POST или же $_COOKIE Суперглобальные?

5 ответов

Решение

Да, я тоже видел десятки таких фрагментов PHP. Это немного грустно.

Волшебные кавычки являются проблемой ввода. Это нужно исправить на этапе ввода, повторяя массивы GET/POST/COOKIES и удаляя косую черту, если вам нужно, чтобы ваше приложение запускалось на серверах с использованием грязной архаичной ошибки, которая magic_quotes_gpc, Простая альтернатива состоит в том, чтобы обнаружить опцию "волшебные кавычки" и умереть с ошибкой "ваш сервер сосет", когда она установлена.

mysql_real_escape_string является выходной проблемой. Его необходимо запускать при выходе из сценария, при отправке контента в базу данных, если вы не используете параметризованные запросы (что вам обязательно следует учитывать).

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

Разве мы не должны удалять косые черты только тогда, когда [...] значение происходит из суперглобальных $_GET, $_POST или $_COOKIE?

Да, точно. Вот почему приведенный вами фрагмент действительно вреден. Поскольку отслеживать происхождение строки нецелесообразно (особенно если вы можете комбинировать строки из разных источников, один из которых является косой, а другой нет), вы не можете сделать это в одной функции. Это должны быть две отдельные функции обработки строк, вызываемые в соответствующее время.

Первый шаг - полностью отключить магические кавычки и выдавать большие недостойные предупреждения, если он включен.

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

// in an include used on every page load:
if (get_magic_quotes_gpc()) {
    foreach (array('_GET', '_POST', '_COOKIE', '_REQUEST') as $src) {
        foreach ($$src as $key => $val) {
            $$src[$key] = stripslashes($val);
        }
    }
}

Небольшой удар по производительности, но он даст вам гораздо больше простоты при работе с вашими переменными с тех пор.

Да, как сказал Дэв, вплоть до сценария использовать только полоски при вводе формы...

если вы вызываете стрип-слэш со строкой "O'Reilly", строка не будет изменена. если вы вызываете полосу-косую черту со строкой вроде: "символ обратной косой черты (\) это круто", результат заменит escape-последовательность \) на). Таким образом, использование этой функции на всех значениях БД может слегка испортить ситуацию, но это может быть не замечено.

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

Номер 6 - правильная идея, но она не работает, потому что до PHP 5.4 $$src[$key] использует переменный синтаксис переменной для $ src [$ key], который интерпретируется как $src[0], создавая переменную $_, которая бесполезно. Просто используйте & (оператор ссылки) для $ val и $val = stripslashes($val). Кроме того, в противном случае, начиная с PHP 5.4, вы, вероятно, получите ошибку, потому что PHP не просто приведёт _ к 0

Вы можете попробовать сделать следующее с $_GET, $_POST или $_COOKIE, прежде чем делать с ними что-то еще:

<?php
if (get_magic_quotes_gpc ())
{
    $_POST = array_map ('stripslashes', $_POST);
}
?>

Обратите внимание, это будет работать только в том случае, если ваш входной массив "плоский" (не содержит вложенных массивов). Если вы ожидаете подмассивы во входных данных, то вам нужно написать свой собственный обратный вызов для его обработки. Что-то вроде

<?php
function slashField ($input)
{
    if (is_array ($input))
    {
        foreach ($input as $key => $row)
        {
            $input [$key]   = slashField ($row);
        }
    }
    else
    {
        $input  = stripslashes ($input);
    }
    return ($input);
}

if (get_magic_quotes_gpc ())
{
    $_POST = array_map ('slashfield', $_POST);
}
?>
Другие вопросы по тегам