Противоядие от 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);
}
?>