|
Pers.narod.ru. PHP. Статьи. Ещё раз про кавычки, удаление пробелов и константы PHP_INI_* |
Типовая задача исключения из ввода пользователя лишних пробелов и/или тегов решается практически в каждом профессиональном скрипте на PHP.
Удалить теги легко стандартной функцией strip_tags, а вот
чтобы удалить все лишние пробелы (в том числе, между словами), нам недостаточно стандартной
trim, как минимум, нужно использовать регулярное выражение:
function trimall($string) {
return trim(preg_replace("/\s+/"," ",$string));
}
или альтернативное выражение, например, такое:
function trimall($string) {
return trim(preg_replace("/ +/"," ",$string));
}
Нерешённой останется только проблема с кавычками. Увы, при настройках PHP
по умолчанию (в том числе, и в текущей версии 5.3.1), кавычки из строк, переданных методом POST или GET после ввода пользователя, при выводе их на экран
могут "экранироваться", то есть, символ " в коде превратится в \":
<?php
$text='';
if (isset ($_POST['text'])) {
$text=strip_tags(trimall($_POST['text']));
echo $text;
}
?>
<form method="post">
<input type="text" name="text" value="<?php echo $text; ?>">
<input type="submit" value="OK">
</form>
Ввод "слово1" даст на выходе \"слово1\". За настройки кавычек в PHP 4-5 версий отвечают
аж 3 переменных, в будущей 6 версии их обещают убрать.
magic_quotes_gpc - если директива включена, все символы ', ", \ и NUL (байт с нулевым кодом)
будут автоматически экранироваться бэкслешем \. С версии 5.3.0 опция объявлена устаревшей, будет
исключена в PHP 6.0.0. Не меняется программно в версиях старше 4.2.3. По умолчанию включена,
именно эта настройка "виновата" в том, что у нас произошло со словом.
magic_quotes_runtime - если включена, то большинство функций, которые возвращают
данные из базы или текстовых файлов, будут возвращать заэкранированные теми же бэкслешами
двойные и одинарные кавычки. Но это ещё не всё! Если дополнительно включена директива
magic_quotes_sybase, то экранируются только одинарные кавычки,
причем не обратным слэшем, а такой же одинарной кавычкой! К счастью, этой директивой можно
управлять программно, по умолчанию она выключена, в версии 5.3.0 объявлена устаревшей,
а в 6.0.0 будет упразднена.
magic_quotes_sybase - как уже сказано, если эта опция включена, то меняется
правило экранирования одинарной кавычки, она записывается с дополнительной
одинарной кавычкой вместо обратной косой черты, если magic_quotes_gpc или
magic_quotes_runtime разрешены. Директивой можно
управлять программно, по умолчанию выключена. Нигде не написано, что она объявлена устаревшей,
но в PHP 6.0.0 директива также должна быть упразднена.
Как от всего этого не сойти с ума и обеспечить корректную обработку кавычек?
Я не раз уже приводил код функции magic, которая разбирается с этой проблемой,
в последнее время она стала вот такой:
function magic ($path) {
@ini_set('magic_quotes_runtime', '0');
@ini_set('magic_quotes_sybase', '0');
//magic_quotes_gpc не меняется программно - см. доки
if (@get_magic_quotes_gpc()=='1') $path=stripslashes($path);
return $path;
}
То есть, 2 директивы, которые можно поставить программно, так и ставятся (с удалением контроля
ошибок оператором "@" - для будущих версий), третья директива проверяется
и при необходимости обрабатываются "лишние" бэкслеши. Последнее выполняется стандартной
функцией stripslashes, хотя можно было бы и "ручными" заменами, как я делал раньше:
if (@get_magic_quotes_gpc()=='1') {
$path= str_replace ('\\"','"',$path);
$path= str_replace ("\\'","'",$path);
$path= str_replace ("\\\\","\\",$path);
}
Функцию get_magic_quotes_gpc также можно бы было не вызывать, ограничившись стандартной
ini_get:
if (@ini_get('magic_quotes_gpc')=='1') $path=stripslashes($path);
P.S. При таком подходе функция stripslashes удалит сочетание символов \"
даже там, где оно нужно, например, в этом предложении. Как быть? Я просто в таких случаях заменяю символ
"\" его HTML-кодом \
Иногда приходится решать обратную задачу - экранировать "опасные" символы обратными слэшами. Добавить бэкслеши при выключенной настройке magic_quotes_gpc можно
стандартной функцией addslashes. А вот если magic_quotes_gpc включена, делать
addslashes не нужно - получится двойное экранирование... ведь тогда функция addslashes и
так автоматически применяется ко всем данным GET, POST, и COOKIE.
Теперь полный код примера, удаляющего из ввода теги, все лишние пробелы между лексемами, не зависящего от настроек кавычек и возвращающего кавычки в форму, стал таким:
<?php
function trimall($string) {
return trim(preg_replace("/\s+/"," ",$string));
}
function magic ($path) {
@ini_set('magic_quotes_runtime', '0');
@ini_set('magic_quotes_sybase', '0');
if (@ini_get('magic_quotes_gpc')=='1') $path=stripslashes($path);
return $path;
}
$text='';
if (isset ($_POST['text'])) {
$text=strip_tags(trimall(magic($_POST['text'])));
echo $text;
}
?>
<form method="post">
<input type="text" name="text" value="<?php echo htmlspecialchars($text); ?>">
<input type="submit" value="OK">
</form>
(в примере не хватает открывающих и закрывающих тегов HTML). Как видите, перед тем как выдать
в теге <form> текст в качестве значения поля ввода <input> (по стандарту HTML здесь нужен синтаксис value="значение в двойных кавычках"),
мы заменили "критичные" для PHP символы <, >, ", ' и & на соответствующие "HTML-сущности".
<, > и т.д. Сделала это стандартная функция htmlspecialchars. Вообще говоря, так нужно делать всегда, независимо от настроек кавычек.
Заодно отметим ещё один важный приём, о котором начинающие тоже часто забывают. Перед использованием любой строки в коде формируемого скриптом SQL-запроса не забудьте после соединения с базой
применить к этой строке функцию mysql_real_escape_string - в статье
стандартной справки по этой функции
всё очень хорошо расписано, зачем и почему :)
Наконец, узнать о том, какие директивы файла php.ini какими способами можно менять, легко
из так называемых "констант PHP_INI_*", в справке рядом с каждой директивой в столбце
Changeable написано одно из 4 значений:
PHP_INI_USER - директива может быть установлена в пользовательских скриптах методом ini_set или в реестре Windows;
PHP_INI_PERDIR - директива может быть установлена в файле php.ini, .htaccess или httpd.conf;
PHP_INI_SYSTEM - директива может быть установлена в файле php.ini или httpd.conf;
PHP_INI_ALL - директива может быть установлена где угодно.
Наконец, очень хороший и простой способ решить описанные в статье проблемы с кавычками - добавить в папку скрипта файл с именем .htaccess и содержимым вида
php_flag magic_quotes_gpc off php_flag magic_quotes_runtime off php_flag magic_quotes_sybase off
Это отключит все 3 директивы и избавит нас от необходимости заботиться о всех этих бэкслешах.
Ну а на локалхосте Windows, где файл .htaccess ничего не значит, всегда можно настроить свой файл php.ini.
|
|