Проблема с использованием Юникода в URL с cgi.PATH_INFO в ColdFusion
Мой сайт ColdFusion (MX7 на IIS 6) имеет функцию поиска, которая добавляет поисковый запрос в URL, например http://www.example.com/search.cfm/searchterm
,
Проблема, с которой я сталкиваюсь, заключается в том, что это многоязычный сайт, поэтому поисковый термин может быть на другом языке, например القاهرة
приводя к поисковому URL, такому как http://www.example.com/search.cfm/القاهرة
Проблема в том, когда я прихожу, чтобы получить поисковый запрос из URL. я использую cgi.PATH_INFO
извлекать путь страницы поиска и поисковый термин и извлекать поисковый термин из этого, например /search.cfm/searchterm
однако, когда символы юникода используются в поиске, они преобразуются в вопросительные знаки, например /search.cfm/??????
,
Это реальные вопросительные знаки, а не то, что браузер не может форматировать символы Юникода, или они искажаются при выводе.
Я не могу найти информацию о том, поддерживает ли ColdFusion Юникод в URL, или как я могу решить эту проблему и каким-то образом получить полный URL - у кого-нибудь есть какие-нибудь идеи?
Ура,
Том
Изменить: Дальнейшие исследования привели меня к выводу, что проблема может быть связана с IIS, а не ColdFusion, но мой первоначальный запрос остается в силе.
Дальнейшее редактирование
Результат GetPageContext().GetRequest().GetRequestUrl().ToString()
является http://www.example.com/search.cfm/searchterm/?????
так что, похоже, проблема идет довольно глубоко.
3 ответа
Да, это не совсем вина ColdFusion. Это общая проблема.
Это в основном ошибка оригинальной спецификации CGI, которая указывает, что PATH_INFO
должен быть%-кодирован, таким образом теряя оригинал %xx
последовательности байтов, которые позволили бы вам определить, какие реальные символы подразумеваются.
И это частично вина IIS, потому что он всегда пытается прочитать представленные %xx
байты в части пути как Unicode в кодировке UTF-8 (если путь не является допустимой последовательностью байтов UTF-8, в этом случае он принимает значение для кодовой страницы Windows по умолчанию, но не дает возможности узнать, что это произошло), Сделав это, он помещает его в переменные окружения в виде строки Unicode (поскольку envvars - это Unicode под Windows).
Однако большинство основанных на байтах инструментов, использующих C stdio (и я предполагаю, что это применимо к ColdFusion, как это делается в Perl, Python 2, PHP и т. Д.), Затем пытаются прочитать переменные среды как байты, и среда выполнения MS C кодирует содержимое Unicode снова, используя кодовую страницу Windows по умолчанию. Таким образом, любые символы, которые не помещаются в кодовую страницу по умолчанию, будут потеряны навсегда. Это будет включать в себя ваши арабские символы при запуске на западной установке Windows.
Умный скрипт, имеющий прямой доступ к Win32 GetEnvironmentVariableW
API может вызвать это, чтобы получить переменную среды native-Unicode, которую они могли бы затем кодировать в UTF-8 или что-то еще, что они хотели, предполагая, что ввод был также UTF-8 (что вы обычно хотите сегодня). Однако я не думаю, что CodeFusion предоставляет вам такой доступ, и в любом случае он работает только с IIS6 и выше; IIS5.x будет отбрасывать любые символы, отличные от кодовой страницы по умолчанию, прежде чем они достигнут переменных окружения.
В противном случае вам лучше всего переписать URL. Если слой выше CF может преобразовать это search.cfm/القاهرة
в search.cfm/?q=القاهرة
тогда вы не столкнетесь с той же проблемой, что и QUERY_STRING
переменная, в отличие от PATH_INFO
, не указывается для%-декодирования, поэтому %xx
байты остаются там, где их может видеть инструмент на уровне CF.
Вот что вы могли бы сделать:
<cfset url.searchTerm = URLEncodedFormat("القاهر", "utf-8") >
<cfset myVar = URLDecode(url.searchTerm , "utf-8") >
Конечно, я бы порекомендовал вам работать с чем-то вроде этого в этом случае:
yourtemplate.cfm? SEARCHTERM =% C3% 98% C2% A7% C3% 99% E2% 80% 9E
И затем вы делаете перезапись URL в IIS (если это еще не сделано в framework/ остальной части приложения) http://learn.iis.net/page.aspx/461/creating-rewrite-rules-for-the-url-rewrite-module/ в соответствии с вашим шаблоном.
Вы можете установить кодировку символов URL-адреса и области видимости FORM с помощью функции setEncoding():
Вы должны сделать это прежде, чем получите доступ к любой из переменных в этой области.
Но кодировка этих областей по умолчанию уже UTF-8, так что это может не помочь. Кроме того, это, вероятно, не повлияет на объем CGI.
Сервер IIS записывает правильные символы в журнал запросов?