urldecode и кодировки
Сегодня неожиданно много времени провёл за изучением одного из репортов в трекере 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);
}
}
Комментарии:
Нету комментариев для вывода...