2010-05-14 7 views
3

Давайте предположу, что пользователь введите адрес какого-либо ресурса, и мы должны перевести его на:IDN осведомленных инструментов для кодирования/декодирование удобочитаемого IRI в/из действительного URI

<a href="valid URI here">human readable form</a> 

спецификацию HTML4 относятся к RFC 3986, который позволяет только Алфавитно-цифровые символы ASCII и тире в главной части и все символы, отличные от ASCII, в других частях должны быть закодированы в процентах. Это то, что я хочу добавить в атрибут href, чтобы обеспечить правильную работу ссылок во всех браузерах. IDN должен быть закодирован с помощью Punycode.

Проект HTML5 относится к RFC 3987, который также допускает кодированные в процентах символы юникода в главной части и большое подмножество юникода как в хосте, так и в других частях без их кодирования. Пользователь может вводить адрес в любой из этих форм. Чтобы обеспечить читаемую человеком форму, мне нужно декодировать все печатные символы. Обратите внимание, что некоторые части адреса могут не соответствовать действительным последовательностям UTF-8, обычно, когда целевой сайт использует некоторую другую кодировку символов.

Пример того, что я хотел бы получить:

<a href="http://xn--80aswg.xn--p1ai/%D0%BF%D1%83%D1%82%D1%8C?%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81"> 
http://сайт.рф/путь?запрос</a> 

Есть ли какие-либо средства для решения этих задач? Меня особенно интересуют библиотеки для Python и JavaScript.

Обновление: Я знаю, что есть способ сделать проценты и Punycode (без нормальной нормализации, но я могу жить с ним) кодирование/декодирование в Python и JavaScript. Вся задача требует гораздо больше работы, и есть некоторые подводные камни (некоторые символы всегда должны быть закодированы или никогда не закодированы в зависимости от контекста). Интересно, есть ли готовые к использованию библиотеки для проблемы целых, так как это кажется довольно распространенным явлением, и современные браузеры уже делают такие преобразования (попробуйте ввести http://%D1%81%D0%B0%D0%B9%D1%82.%D1%80%D1%84/ в Google Chrome и замените его на http://сайт.рф/, но используйте Host: xn--80aswg.xn--p1ai в HTTP запрос).

Update2: Vinay Sajip указал, что Werkzeug имеет функции iri_to_uri и uri_to_iri, которые обрабатывают большинство случаев правильно. Я обнаружил только 2 случая, когда он не прошел до сих пор: процентный кодированный хост (довольно легко исправить) и недействительные последовательности utf-8 (немного сложно сделать красиво, но не должно быть проблемой).

Я все еще ищу библиотеку в JavaScript. Это не сложно написать, но я бы предпочел не изобретать колесо.

+0

Я добавил ссылку в свой ответ на реализацию Javascript, которая, возможно, может быть адаптирована к вашим потребностям. Это общественное достояние, но я хочу сказать, что это модульные тесты. –

+0

Duplicate: http://stackoverflow.com/questions/183485/can-anyone-recommend-a-good-free-javascript-for-punycode-to-unicode-conversion –

+0

Спасибо за ссылку. Речь идет не только о реализации кодировки в стиле Punycode (это легко), но и о гораздо большей проблеме. –

ответ

2

Если я вас правильно понял, то вы можете использовать батареи, включенные в Python:

# -*- coding: utf-8 -*- 

import urllib 
import urlparse 

URL1 = u'http://сайт.рф/путь?запрос' 
URL2 = 'http://%D1%81%D0%B0%D0%B9%D1%82.%D1%80%D1%84/' 

def to_idn(url): 
    parts = list(urlparse.urlparse(url)) 
    parts[1] = parts[1].encode('idna') 
    parts[2:] = [urllib.quote(s.encode('utf-8')) for s in parts[2:]] 
    return urlparse.urlunparse(parts) 

def from_idn(url): 
    return urllib.unquote(url) 

print to_idn(URL1) 
print from_idn(URL2) 
print to_idn(from_idn(URL2).decode('utf-8')) 

который печатает

http://xn--80aswg.xn--p1ai/%D0%BF%D1%83%D1%82%D1%8C?%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81 
http://сайт.рф/ 
http://xn--80aswg.xn--p1ai/ 

, который выглядит так, как вы хотите. Я не уверен, какие особые случаи вы имеете в виду - возможно, вы могли бы привести некоторые примеры подводных камней, о которых вы говорите?

Update: Я только что вспомнил, Werkzeug имеет iri_to_uri и uri_to_iri функции в версии 0.6 и более поздних версий (ссылки на соответствующую часть документации).

Дальнейшее уточнение: Извините, я не заметил, что вы ищете реализацию JavaScript, а также Python. Существующая реализация Javascript для публичного доступа для punycode - here.Однако я не могу ручаться за это. И, конечно же, вы можете использовать встроенные JavaScript API encodeURI/decodeURI.

+0

Ваши функции работают только для этого примера. Функции Werkzeug работают в большинстве случаев и могут быть легко исправлены для остальных, спасибо! –

+0

В вашей строке кодирования есть - * 'вместо - * -. Чтобы избежать этого беспорядка, вы можете просто написать # код: utf-8 – temoto