Удаление недействительных / неполных многобайтовых символов - PullRequest
8 голосов
/ 09 марта 2012

У меня проблемы с использованием следующего кода при вводе пользователем:

htmlentities($string, ENT_COMPAT, 'UTF-8');

При обнаружении недопустимого многобайтового символа PHP выдает уведомление:

Предупреждение PHP: htmlentities (): недопустимая многобайтовая последовательность в аргументе в /path/to/file.php в строке 123

Моей первой мыслью было подавление ошибки, но это медленная и плохая практика: http://derickrethans.nl/five-reasons-why-the-shutop-operator-should-be-avoided.html

Моей второй мыслью было использование флага ENT_IGNORE, но даже руководство по PHP предлагает не использовать это:

Бесшумно отбрасывать недопустимые последовательности единиц кода вместо возврата пустой строки. Использование этого флага не рекомендуется, поскольку » может иметь последствия для безопасности .

Немного дальнейшей причины привело меня к следующему коду:

    // detect encoding
$encoding =  mb_detect_encoding($query);
if($encoding != 'UTF-8') {
    $query = mb_convert_encoding($query, 'UTF-8', $encoding);
} else {
    // strip out invalid utf8 sequences
    $query = iconv('UTF-8', 'UTF-8//IGNORE', $query);
}

К сожалению, iconv также выдает E_NOTICE, когда он удаляет / игнорирует недопустимые символы:

Если вы добавляете строку // TRANSLIT к out_charset, транслитерация активируется. Это означает, что когда символ не может быть представлен в целевой кодировке, он может быть аппроксимирован одним или несколькими одинаково выглядящими символами. Если вы добавите строку // IGNORE, символы, которые не могут быть представлены в целевой кодировке, будут молча отброшены. В противном случае str вырезается из первого недопустимого символа и генерируется E_NOTICE.

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

Итак, это подводит меня к моему последнему вопросу: Как я могу удалить недействительные многобайтовые символы, эффективно, безопасно, без уведомлений / предупреждений / ошибок?

Ответы [ 2 ]

4 голосов
/ 14 марта 2013

iconv('UTF-8', "ISO-8859-1//IGNORE", $string);

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

2 голосов
/ 11 марта 2012

Как я могу удалить недействительные многобайтовые символы эффективно, безопасно, без уведомлений / предупреждений / ошибок?

Ну, как вы уже обрисовали в своем вопросе самостоятельно ( или, по крайней мере, связанный ), удаление недопустимой последовательности байтов не является вариантом.

Вместо этого его, вероятно, следует заменить символом замены U + FFFD.Начиная с PHP 5.4.0 вы можете использовать флаг ENT_SUBSTITUTE для htmlentities.Это, вероятно, наиболее безопасно, если вы не хотите отклонять строку.

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

...