Лучшие практики разработки программного обеспечения, поддерживающего универсальное принятие

Программное обеспечение, полностью поддерживающее универсальное принятие, должно:

В побласти интерфейсов и получения данных


  • Отображать имена в кодировке Unicode всегда, когда это возможно. Пользователям следует разрешать, но не требовать от них, вводить доменные имена как A-метки вместо U-меток. Однако для отображения по умолчанию следует использовать U-метки, а A-метки показывать пользователю только тогда, когда это приносит ему пользу.
  • Не генерировать EAI-адреса с A-метками, но обрабатывать их при получении из стороннего программного обеспечения.
  • Любой компонент пользовательского интерфейса, требующий от пользователя ввести доменное имя или адрес электронной почты, должен принимать длинные имена. Доменные имена в кодировке ASCII могут содержать до 63 символов в каждой метке и иметь общий размер до 253 байтов. Метки UTF-8 могут быть намного длиннее меток ASCII, а их общая длина может составлять до 670 байтов. Помните, что в кодировке UTF-8 большинство символов Unicode занимает больше одного байта. См. RFC 1035.

В области проверки данных


  • Проверять только по мере необходимости. Проверять данные нужно только в том случае, если это необходимо для работы приложения или сервиса. Это самый надежный способ обеспечить принятие системами всех допустимых доменных имен.
  • Учитывать, что любые синтаксически правильные входные данные могут представлять доменные имена или адреса электронной почты, которые в настоящее время используются в интернете. Они могут быть действительными или недействительными, в зависимости от приложения.
  • Возможные механизмы проверки корректности доменных имен:
    • Убедитесь, что та часть доменного имени, которая представляет TLD, есть в официальной таблице. IANA публикует список доменов верхнего уровня здесь и здесь
    • Запросите данные по доменному имени напрямую в DNS, используя:
      • GETDNS API (http://getdnsapi.net/) — платформонезависимый способ отправки DNS-запросов.
      • Встроенный в вашу ОС механизм DNS-запросов.
    • Для обнаружения опечаток требуйте повторного ввода адреса электронной почты.
    • Проверьте символы в метках, убедившись, что каждая метка соответствует правилам интернационализации доменных имен в приложениях (IDNA 2008), см. RFC 5892
    • При проверке самих меток ограничьтесь небольшим количеством правил для метки целиком, которые определены в RFC, см. RFC 5894
    • Убедитесь, что продукт или функция правильно обрабатывает числа.
      • Например: Символы арабских цифр следует обрабатывать как числа в полях числового ввода, а также как цифры ASCII.
      • Обратите внимание, что арабские цифры допустимы в U-метках, но не считаются эквивалентными цифрам ASCII в этом контексте.

В области хранения данных


  • Приложения и сервисы должны поддерживать последнюю версию стандартов Unicode.
  • По мере возможности информацию следует хранить в формате UTF-8. Кроме того, некоторым системам может потребоваться поддержка старого формата UTF-16, но в большинстве случаев формат UTF-8 предпочтительнее. UTF-7 устарел, а UTF-32 слишком громоздкий для хранения файлов. При необходимости строки следует нормализовать (иногда нормализация может привести к потере информации).
  • Примите во внимание все комплексные сценарии перед преобразованием A-меток в U-метки и наоборот во время хранения. В новых приложениях целесообразнее хранить в файле или базе данных только U-метки, поскольку это упрощает поиск, сортировку и отображение. Однако преобразование может повлиять на взаимодействие с более старыми приложениями и сервисами, не поддерживающими Unicode.
  • Пометьте адреса электронной почты и доменные имена как таковые в хранилище, чтобы упростить доступ. Хранение адресов электронной почты и доменных имен в полях «Автор» документа или «Контактная информация» в журнале событий приводило к утрате исходного адреса.
  • Независимо от способа хранения адресов и доменных имен, вы должны иметь возможность сопоставлять строки в нескольких форматах. Например, при поиске example.みんな следует также найти example.xn-- q9jyb4c.

В области обработки данных


  • Убедитесь, что для всех ответов веб-сервера и почты MIME указан тип контента UTF-8.
  • Укажите UTF-8 в заголовке HTTP веб-сервера. Важно обеспечить, чтобы кодировка указывалась в каждом ответе.
  • Учитывайте ситуацию перед преобразованием A-меток в U-метки и наоборот во время обработки. Целесообразно хранить в файле или базе данных только U-метки, поскольку это упрощает поиск и сортировку. Однако преобразование может повлиять на взаимодействие с более старыми приложениями и сервисами, не поддерживающими Unicode.
  • Убедитесь, что продукт или функция обрабатывает операции сортировки, поиска и сравнения в соответствии с языковыми спецификациями, а также обеспечивает возможность многоязычного поиска и сортировки.
  • Не используйте urlencode для меток в доменных именах:
    • example.みんな — правильно
    • example.%E3%81%BF%E3%82%93%E3%81%AA — неправильно
  • Поскольку стандарт Unicode постоянно расширяется, следует проверить символы, которые не были определены в момент создания приложения или сервиса, и убедиться в отсутствии ошибочных или противоречивых выходных данных. Результатом отсутствия шрифтов в базовой операционной системе могут стать неотображаемые символы (часто для их представления используется небольшой прямоугольник), но такая ситуация не должна приводить к сообщению о сбое или ошибке.
  • Используйте API, c поддержкой Unicode.
  • Используйте последнюю редакцию документов по протоколам и таблицам интернационализированных доменных имен в приложениях (IDNA 2008) для IDN-доменов: RFC 5891 и RFC 5892.
  • По возможности выполняйте обработку текста в формате UTF-8.
  • Координируйте обновления приложений и сервисов, от которых они зависят. Если сервер использует Unicode, а клиентская часть нет, или наоборот, придется выполнять преобразование при каждой операции передачи данных, что способствует возникновению ошибок и может замедлить работу.
  • При преобразовании символов текстовые строки могут существенно удлиняться или сокращаться. Каждый символ UTF-8 может быть от 1 до 4 байтов длиной, и в некоторых случаях один символ в другой кодировке может соответствовать нескольким символам UTF-8 или наоборот.

В области отображения данных


  • Отображайте все символы Unicode, которые поддерживаются базовой операционной системой. Все современные операционные системы поддерживают Unicode, но их механизмы визуализации не всегда подходят для всех сценариев и языков. Обеспечивайте визуализацию символов в приложениях только в том случае, если правильная визуализация невозможна в целевой операционной системе.
  • При разработке приложения или сервиса обращайте внимание на поддерживаемые языки и обеспечивайте охват этих языков операционными системами и приложениями.
  • Преобразуйте A-метки в U-метки перед отображением. Например, конечный пользователь должен увидеть строку «example.みん な», а не строку «example.xn--q9jyb4c». (Это преобразование — пример обработки, обеспечивающей UA-готовность).
  • По умолчанию отображайте доменные имена как U-метки. Показывайте пользователю A-метки только тогда, когда это приносит выгоду.
  • Помните, что могут быть доменные имена, где используется несколько алфавитов.
    • Некоторые символы Unicode могут выглядеть одинаковыми для человеческого глаза, но разными для компьютеров. Например, латинская O, кириллическая О и греческая омикрон О.
    • Строки с несколькими наборами символов часто встречаются в тесто связанных алфавитах (напр., японские наборы символов кандзи, катакана, хирагана и ромадзи.) Смешивание алфавитов также может использоваться для злонамеренных целей, таких как фишинг. Для проверки того, что алфавиты в последовательности Unicode соответствуют передовой практике, применяется технический стандарт Unicode № 39 «Механизмы безопасности Unicode».
    • Если пользовательский интерфейс обращает внимание пользователя на такие строки, избегайте предвзятого отношения к пользователям нелатинских алфавитов.

    Дополнительные сведения об аспектах обеспечения безопасности при использовании Unicode можно получить здесь.
  • Помните о наличии символов, запрещенных для использования в доменных именах, см. RFC 5892

В области работы с Unicode


  • Используйте API с поддержкой Unicode.
  • Используйте стандартные, хорошо отлаженные API для выполнения следующих задач:
    • Преобразование формата строк.
    • Определение алфавита строки.
    • Определение того, содержит ли строка символы нескольких алфавитов.
    • Нормализация/декомпозиция Unicode.
  • Не используйте UTF-7 и ограничивайте использование UTF-32.
    • UTF-7 устарел.
    • UTF-32 использует четыре байта для каждого кода символа. Поскольку каждый символ занимает одинаковое количество места и может быть напрямую проиндексирована в массивах, его удобно использовать в программировании, но он может оказаться слишком громоздким для хранения в файлах и базах данных.
  • Не используйте UTF-16, кроме случаев, когда это настоятельно необходимо (как в некоторых API Windows и приложениях Javascript). В UTF-16 16 битов могут представлять только символы от 0x0 до 0xFFFF. Значения выше этого диапазона (от 0x10000 до 0x10FFFF) используют пары псевдосимволов, известных как суррогаты. Если не выполнить тщательное тестирование обработки суррогатных пар, могут возникнуть сложные ошибки и потенциальные дыры в безопасности.
  • Используйте UTF-8 в файлах cookie, чтобы приложения могли правильно их считывать.
  • Используйте документы протоколов и таблиц IDNA 2008: RFC 5891 и RFC 5892.
  • Не используйте IDNA 2003, который был заменен на IDNA 2008.
  • Поддерживайте таблицы IDNA и Unicode соответствующих версий. Например, если приложение не применяет классификационные правила в документе таблиц для интерпретации кодов символов, как они введены (RFC 5892), должны быть получены таблицы IDNA, которые соответствуют поддерживаемой в системе версии Unicode. Эти таблицы не обязательно должны представлять последнюю версию Unicode, но они должны быть согласованными.
  • Проверяйте метки, используя правила IDNA 2008 для полной метки. Иногда целесообразна дополнительная проверка; например, если приложению известно, какие алфавиты разрешены в используемых им доменных именах.

Дополнительные рекомендации


  • Используйте авторитетные ресурсы для проверки доменных имен. Не делайте устаревших бессистемных предположений, таких как «длина всех TLD не должна превышать 6 символов».
  • Убедитесь, что продукт или функция правильно обрабатывает числа. Например, числовые символы ASCII и азиатские иероглифы, представляющие числа, в определенных ситуациях должны обрабатываться как числа.
  • Учитывайте, что почтовые адреса, которые могут быть адресами EAI, могут быть в самых неожиданных местах:
    • Метаданные исполнитель/автор/фотограф/авторские права.
    • Метаданные шрифтов.
    • Контактные данные DNS.
    • Информация о версии.
    • Вспомогательная информация.
    • Контактные данные OEM.
    • Регистрация, обратная связь и другие формы.
  • Ограничьте список символов, которые разрешено использовать при создании новых доменных имен и адресов электронной почты: Все продукты, обрабатывающие адреса электронной почты, должны принимать интернационализированные адреса электронной почты, в локальной части которых допускается использование большинства символов UTF-8. Однако приложение или сервис не должны разрешать использование всех символов при создании пользователем нового IDN- домена или адреса EAI. Изначальный запрет на создание определенных IDN-доменов или адресов электронной почты может снизить вероятность возникновения проблем с безопасностью и доступностью. (Однако рекомендуется, чтобы программное обеспечение принимало такие строки в случае их получения.)
  • Помните, что универсальное принятие не всегда можно измерить с помощью одних только сценариев автоматизированного тестирования. Например, не всегда можно протестировать, как приложение или протокол обрабатывает сетевой ресурс, и иногда лучше всего проверить соблюдение требований путем анализа функциональной спецификации и проекта.
  • Ошибочно считать, что, поскольку компонент не вызывает напрямую API- интерфейсы разрешения имен или не использует напрямую адреса электронной почты, это не влияет на него. Следует понимать, как компонент получает доменные имена — это не всегда происходит через взаимодействие с пользователем. Ниже приведены некоторые примеры того, как компонент может получить доменное имя:
    • Групповая политика.
    • Запрос LDAP.
    • Файлы конфигурации.
    • Реестр Windows.
    • Передача или получение из другого компонента или функции.
  • Анализируйте код, чтобы избежать проблем с переполнением буфера
    • В Unicode строки могут удлиняться или сокращаться при выравнивании регистра или нормализации.
    • При преобразовании символов текстовые строки могут существенно удлиняться или сокращаться.