Атрибут accept-charset="UTF-8"
является лишь руководством для браузеров, которым не нужно следовать, они не обязаны сообщать, что таким образом, дрянные боты отправки форм являются хорошим примером ...
Обычно я игнорирую плохие символы с помощью iconv()
или с менее надежными функциями utf8_encode()
/ utf8_decode()
, если вы используете iconv
у вас также есть возможность транслитерировать плохие символы.
Вот пример использования iconv()
:
$str_ignore = iconv('UTF-8', 'UTF-8//IGNORE', $str);
$str_translit = iconv('UTF-8', 'UTF-8//TRANSLIT', $str);
Если вы хотите отобразить сообщение об ошибке для своих пользователей, я бы, вероятно, сделал это глобально, а не на основе полученного значения, что-то вроде этого, вероятно, подойдет:
function utf8_clean($str)
{
return iconv('UTF-8', 'UTF-8//IGNORE', $str);
}
$clean_GET = array_map('utf8_clean', $_GET);
if (serialize($_GET) != serialize($clean_GET))
{
$_GET = $clean_GET;
$error_msg = 'Your data is not valid UTF-8 and has been stripped.';
}
// $_GET is clean!
Вы также можете нормализовать новые строки и удалить (не) видимые контрольные символы, например:
function Clean($string, $control = true)
{
$string = iconv('UTF-8', 'UTF-8//IGNORE', $string);
if ($control === true)
{
return preg_replace('~\p{C}+~u', '', $string);
}
return preg_replace(array('~\r\n?~', '~[^\P{C}\t\n]+~u'), array("\n", ''), $string);
}
Код для преобразования из UTF-8 в кодовые точки Unicode:
function Codepoint($char)
{
$result = null;
$codepoint = unpack('N', iconv('UTF-8', 'UCS-4BE', $char));
if (is_array($codepoint) && array_key_exists(1, $codepoint))
{
$result = sprintf('U+%04X', $codepoint[1]);
}
return $result;
}
echo Codepoint('à'); // U+00E0
echo Codepoint('ひ'); // U+3072
Вероятно, быстрее, чем любая другая альтернатива, хотя и не тестировали ее всесторонне.
Пример:
$string = 'hello world�';
// U+FFFEhello worldU+FFFD
echo preg_replace_callback('/[\p{So}\p{Cf}\p{Co}\p{Cs}\p{Cn}]/u', 'Bad_Codepoint', $string);
function Bad_Codepoint($string)
{
$result = array();
foreach ((array) $string as $char)
{
$codepoint = unpack('N', iconv('UTF-8', 'UCS-4BE', $char));
if (is_array($codepoint) && array_key_exists(1, $codepoint))
{
$result[] = sprintf('U+%04X', $codepoint[1]);
}
}
return implode('', $result);
}
Это то, что вы искали?