Можно ли с уверенностью предположить, что декодированные URI с процентной кодировкой превращаются в UTF-8?


В RFC 3986 говорится, что новая схема URI должна быть сначала закодирована в UTF-8, прежде чем быть закодирована в процентах. Однако это не относится к предыдущим версиям URI.

Можно ли с уверенностью предположить, что все многобайтовые URI, закодированные в процентах, превращаются в кодированную строку UTF-8 после прохождения через urldecode()?

Например, если содержимое $_SERVER['REQUEST_URI'] кодируется в процентах как таковое:

/b%C3%BCch/w%C3%B6rterb%C3%BCch

После того, как я передам эту строку в urldecode(), у меня должна быть многобайтовая строка. Но как я узнаю в какая кодировка у этой строки? В приведенном выше примере это UTF-8, но безопасно ли всегда предполагать это?

Если это небезопасно предполагать, есть ли способ (кроме mb_detect_encoding) определить кодировку строки? Я проверил заголовки запросов, похоже, в них нет ничего полезного.

 15
Author: rickchristie, 2011-10-10

3 answers

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

Перейдите к концу, чтобы перейти непосредственно к заключению.

Из Документов ПРИСТАНИ по международным символам и кодировке символов, из раздела "Международные символы в URL-адресах", я нашел эти параграфы:

Из-за отсутствия стандарта, разные браузеры использовали разные подходы к используемой кодировке символов. Некоторые используют кодировку страницы, а некоторые используют UTF-8. Некоторые проекты были подготовлены различными органами по стандартизации, предполагающими, что UTF-8 станет стандартной кодировкой. Более старые версии jetty (например, серии 4.0.x) использовали UTF-8 по умолчанию в ожидании принятия стандарта. Поскольку стандарта не было, jetty-4.1.x вернулся к кодировке ISO по умолчанию-8859-1.

HTML организации W3C стандарт теперь рекомендует использовать UTF-8: http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars и, соответственно, серия jetty-6 использует по умолчанию UTF-8.

В связанной спецификации HTML 4.0 действительно есть рекомендация для клиентов кодировать символы, отличные от ASCII, в UTF-8, прежде чем кодировать их в процентах, поэтому мы знаем, что это была рекомендация от W3C начиная с HTML 4.0.

Пример, используемый на странице, таков:

<A href="http://foo.org/Håkon">...</A>

В то время как это позже говорится, что та же кодировка должна быть применена к части фрагмента, но не говорится, что если она также применима к строке запроса.

Ввод URL-адресов в браузеры

Firefox

Как уже упоминал Пекка, на основе этой ссылки Firefox отправляет URI в кодировке ISO-8859-1 еще в 2007 году. Читая ссылку, это, похоже, поведение по умолчанию для Firefox кодировка по умолчанию в Mac - это UTF-8.

Я протестировал Firefox 3.6.13 в Windows XP и Firefox 6 в обоих Windows 7 и Mac OS X. Версия для Mac отправляет все в UTF-8, так что беспокоиться не о чем.

Firefox 3.6.13 и 6 в Windows по умолчанию кодирует строки запроса в ISO-8859-1 , но при вводе символов, которых не существует в ISO-8859-1 в строку запроса (α, например), Firefox 3 переключает кодировку всей строки запроса на UTF-8. Я почти уверен, что это то же самое поведение в более поздних версиях тоже.

В Firefox 3.6.13 и 6 в Windows, которые я тестировал, часть пути URI всегда кодируется как UTF-8.

Если вы введете этот URL-адрес в Firefox 3.6/6 в Windows:

http://localhost/test/ü/ä/index.php?chär=ü

Строка запроса кодируется как ISO-8859-1, но часть "путь" кодируется как UTF-8:

http://localhost//test/%C3%BC/%C3%A4/index.php?ch%E4r=%FC

Также следует отметить, согласно этому сообщению в блоге , Firefox 3.0 преобразует символ катанаки в &#12450; перед его кодированием в процентах . Когда я пытался это сделать в Firefox 3.6.13 в строке запроса и пути символ катанака правильно кодируется в UTF-8.

Опера

Opera 10.10 на Mac кодирует часть строки запроса URI в ISO-8859-1, хотя кодировка по умолчанию для Mac OS X UTF-8. Часть "путь" кодируется в UTF-8, как и в Firefox.

Если вы попытаетесь ввести греческий алфавит α в строку запроса, он будет отправлен в виде вопросительного знака.

Такое же поведение демонстрирует Opera 11.51 в Windows XP.

Сафари

Safari 5.1 на Mac всегда отправляет все в формате UTF-8. Safari 5.1 в Windows демонстрирует такое же поведение.

Хром

Версия 13 в Windows кодирует строку запроса и путь как UTF-8. У меня нет Chrome на Mac, но можно с уверенностью предположить , что Chrome всегда отправляет UTF-8, как Safari.

Обозреватель Интернета

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я использую IECollection для установки нескольких версий IE в одной машина, так что это может быть неестественным поведением IE (кто-нибудь может подтвердить это?).

IE 6, 7 и 8 в Windows XP кодирует часть URI "путь" в UTF-8 правильно. Однако умлауты и греческий алфавит, введенные в строку запроса , не кодируются в процентах. Строка запроса, введенная в адресную строку, кажется, отправлена в ISO-8859-1, греческий алфавит альфа "α" в строке запроса транслитерируется в "а".

Заключение

Это коротко и неполно, и я не могу гарантируйте правильность этого, но, похоже, наиболее распространенными кодировками для URI являются либо ISO-8859-1, либо UTF-8 (я понятия не имею, что восточноазиатцы используют в качестве своей кодировки, и это слишком исчерпывающе для меня, чтобы попытаться выяснить).

Поскольку это уже рекомендация из HTML 4.0, я думаю, можно с уверенностью предположить, что часть URI "путь" всегда кодируется в UTF-8. Firefox 2.0 все еще может быть доступен, поэтому вы также должны проверить, соответствует ли кодировка ISO-8859-1. Если это не UTF-8 или ISO-8859-1, скорее всего, это плохой запрос.

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

Безопасная Многобайтовая маршрутизация

Самый безопасный способ - просто выбрать одну кодировку (UTF-8 - самая безопасная ставка) для всего вашего приложения. Затем вы должны:

  1. Убедитесь, что все ваши строки кодируется в UTF-8, прежде чем использовать его для создания вашего URI. После этого правильно закодируйте свой URI в процентах .
  2. Убедитесь, что все ваши формы в кодировке URL (GET) отправляют свои данные в правильной кодировке. Смотрите этот FAQ от Kore Nordmann для получения дополнительной информации о том, как убедиться, что ваши формы отправляют правильную кодировку.

Также смотрите этот замечательный ответ от бобинса.

После этого у вас не должно возникнуть никаких проблем с анализом URI. Если кодировка не в UTF-8, то это плохой запрос, и вы можете ответить 404 или 400 страницами.

 3
Author: rickchristie, 2017-05-23 12:12:02

Поскольку в любом случае небезопасно предполагать, что ("плохим парням все равно"), вы можете использовать mb_check_encoding для проверки строки UTF-8. UTF имеет структуру, которая с низкой вероятностью соответствует строке в другой кодировке.

 0
Author: Lyth, 2011-10-11 07:43:18

Ты не знаешь. Это зависит от человека/кода, который сгенерировал URI.

 0
Author: Julian Reschke, 2011-10-11 07:49:19