urldecode и кодировки
9 июля 2011
Сегодня неожиданно много времени провёл за изучением одного из репортов в трекере Yii. Первопричина оказалась совсем не той и крылась, как это часто бывает, в несоблюдении стандартов. Вообще тонкости две:
PHP-шный urldecode работает напрямую с октетами (теми, что
%AB
), так что интерпретация строки зависит от кодировки скрипта. В случае Yii этоUTF-8
.Хоть RFC 3986 в районе 16-ой страницы и говорит нам, что «data should first be encoded as octets according to the UTF-8 character encoding», но всё-же достаточно большое количество ПО использует другие кодировки. Чаще всего это
ISO-8859-1
.
То есть после декодирования мы можем получить либо UTF-8, либо что-то ещё. Это ещё скорее всего будет ISO-8859-1
.
Ну и решение — свой urldecode
:
/** * Improved variant of urldecode. * Properly decodes both UTF-8 and ISO-8859-1 encoded URIs. * * @param string $str encoded string * @return string decoded string */ private function urldecode($str) { $str = urldecode($str); // is it UTF-8? // http://w3.org/International/questions/qa-forms-utf-8.html if(preg_match('%^(?: [\x09\x0A\x0D\x20-\x7E] # ASCII | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 )*$%xs', $str)) { return $str; } else { return utf8_encode($str); } }
Комментарии RSS по email OK
2Sam, случаем не это имеется в виду ? http://www.php.net/manual/ru/function.urldecode.php#101401
Да, оно самое. Там даже решение почти 1 в 1.
У этой регулярки есть одна плохая особенность - в некоторых случаях при ее применении php вылетает с segmentation fault. Столкнулся с этим недавно. Использовал для проверки кодировки страниц перед парсингом и на страницах гугла начала вылетать такая ошибка. Пришлось отказаться от проверки регуляркой.