Как декодировать такую ​​странную строку в UTF-8? (PHP) - PullRequest
4 голосов
/ 18 мая 2010

Итак, у меня есть %u041E%u043B%u0435%u0433%20%u042F%u043A как сохранить его в реальном UTF-8 или (лучше для меня для сущностей HTML)?

Ответы [ 3 ]

10 голосов
/ 18 мая 2010

Это JavaScript escape() формат. Это похоже на URL-кодирование, но не совместимо. Использование его вообще обычно является ошибкой.

Лучше всего изменить сценарий, который его генерирует, вместо этого использовать правильную кодировку URL (encodeURIComponent()). Затем вы можете декодировать его с помощью urldecode или любой другой обычной функции декодирования URL на стороне сервера.

Если вам абсолютно необходимо обмениваться данными в этом нестандартном формате, вам придется написать собственный декодер для него. Вот быстрый взлом, используя HTML-символьно-ссылочный-декодер:

function jsunescape($s) {
    $s= preg_replace('/%u(....)/', '&#x$1;', $s);
    $s= preg_replace('/%(..)/', '&#x$1;', $s);
    return html_entity_decode($s, ENT_COMPAT, 'utf-8');
}

Возвращает необработанную строку байтов UTF-8. Если вы действительно хотите это в ссылках на символы HTML, таких как Ру..., тогда пропустите вызов html_entity_decode. Но обычно нет. Лучше всего сохранять строки в необработанном формате до тех пор, пока их не нужно будет экранировать для окончательного вывода, и лучше всего вообще не заменять символы, не входящие в ASCII, ссылками на символы, если только вам это не нужно.

что если какая-нибудь строка, подобная этой, придет ко мне '% CE% EB% E5% E3 +% DF% EA% F3% F8% EA% E8% ED'

Это кодированный в форме URL, который не совместим напрямую с форматом escape(). Хотя двузначные байтовые экранирования в кодировке URL-адреса отличаются от сумасшедших четырехзначных кодовых единиц кода в формате escape, символ + является неоднозначным. Это может означать плюс (если строка взята из escape) или пробел (если он получен из представления в браузере). Нет никакого способа сказать, что это. Это еще одна причина не использовать escape().

Помимо этого; если бы кодировка этой строки была UTF-8, то да, вышеприведенная функция была бы в порядке, конвертируя как байты в кодировке URL, так и сумасшедшие символы Unicode escape() в необработанные байты UTF-8.

Однако на самом деле это кодовая страница 1251 (Windows Russian). Вы действительно хотите обработать все свои строки в cp1251? Если это так, вам придется немного изменить его, чтобы он кодировал четырехзначные переходы в другую кодировку. Это грязно:

function url_or_maybe_jsescape_decode($s, $charset, $isform) {
    if ($isform)
        $s= str_replace('+', ' ', $s);
    $s= preg_replace('/%u(....)/', '&#x$1;', $s);
    $s= preg_replace('/%(..)/', '&!#x$1;', $s);
    $s= html_entity_decode($s, ENT_COMPAT, $charset);
    $s= str_replace('&!', '&', $s);
    $s= html_entity_decode($s, ENT_COMPAT, 'utf-8');
    return $s;
}

echo url_or_maybe_jsescape_decode('%CE%EB%E5%E3+%DF%EA%F3%F8%EA%E8%ED', 'cp1251', TRUE);

Я бы настоятельно рекомендовал:

  1. исправление файла Flash таким образом, чтобы он использовал правильный encodeURIComponent, а не escape, так что вы можете использовать стандартный URL-декодер вместо этого уродливого хака.

  2. с использованием UTF-8 вместо этого по всему приложению, так что вы можете поддерживать языки, отличные от русского, и вам не нужно беспокоиться об изменении кодировки ввода отправленных форм. *

(Все кодировки, которые не являются UTF-8, отстой, и это НАСТОЯЩИЙ ФАКТ, доказанный НАУКОЙ!)

2 голосов
/ 18 мая 2010

PHP имеет функцию декодирования

$string = html_entity_decode($string,ENT_COMPAT,"UTF-8")
0 голосов
/ 18 мая 2010

Как подсказывают другие, конвертируйте его в Unicode HTML Entities. Это регулярное выражение, которым я пользуюсь,

function escapePercentU($s) {
   $s = preg_replace( "/%u([A-Fa-f0-9]{4})/", "&#x$1;", $s);
   return html_entity_decode($s, ENT_COMPAT, 'utf-8');
}
...