Имя публикации не должно содержать символы национальных алфавитов 1с

Обновлено: 07.07.2024

В данной статье рассмотрены программные реализации кодировки национальных доменных имен из ASCII- формата в IDN и обратно средствами MS VisualStudio и библиотеки ICU.


История.
Если вы уже слышали аббревиатуру IDN, то следующие четыре абзаца можно смело пропускать.

Исторически для представления доменных имен в Интернете использовались символы ASCII кодировки: “A-z”, “0-9”, “-”. С развитием Интернета символов стало не хватать (точнее коротких и удобных имен) и ICANN заявило о необходимости расширения знаков представления доменных имен за счет использования национальных алфавитов (представлены в Unicode).

Многочисленные обсуждения на немногочисленных форумах, посвященных IDN, сводятся к двум мнениям: «офигеть – дайте две!» и «нас пытаются — мягко говоря — обмануть». Второе основано на специфике реализации данной технологии.

Новые символы – это хорошо закодированные старые :)

По сути, IDN – это удобная и красивая обертка для длинного и неудобного набора символов. На стороне клиента осуществляется кодировка национальных символов в допустимые символы ASCII, которые и являются доменным именем. Если в адресную строку ввести «пример.испытание», то она перекодируется в «xn--e1afmkfd.xn--80akhbyknj4f». Для этого используется кодировка из семейства ASCII – совместимых кодировок (ACE) – Punycode, применяемая в настоящее время в системе многоязычных доменных имен. Алгоритм кодирования Punycode достаточно прост и подробно описан в RFC-3492 (там же он реализован на C).

Какие средства кодировки и перекодировки в нашем распоряжении?

1. Средства Microsoft.

В VisualStudio в пространстве имен System.Globalization реализован класс IdnMapping, среди методов которого можно найти в частности такие — GetAscii и GetUnicode, которые и осуществляют перекодировку в соответствии со стандартами IDNA. Не класс, а мечта – проще некуда:

using namespace System::Globalization;
using System::String;

String^ s1 = "привет.пример";
String^ s;

s = idn.GetAscii(s1, 0, s1->Length);
System::Console::WriteLine(s);

String^ s2 = "xn--b1agh1afp.xn--e1afmkfd";

s = idn.GetUnicode(s2, 0, s2->Length);
System::Console::WriteLine(s);

Для этих же целей у мелкомягких есть две API функции IdnToAscii и IdnToUnicode. К сожалению, Minimum supported client – Windows Vista. Очень жаль. Пример использования функция можно найти на их сайте.

2. Средства ICU (International Components for Unicode). ICU — это С/С++ и Java open source библиотеки, в которых реализованы поддержка и возможности «Unicode and Globalization». В этой библиотеке реализованы следующие функции преобразования доменных имен:

int32_t uidna_toUnicode / uidna_toAscii (const UChar *src, int32_t srcLength, UChar *dest, int32_t destCapacity, int32_t options, UParseError *parseError, UErrorCode *status)
int32_t uidna_IDNToUnicode / uidna_IDNToASCII(const UChar *src, int32_t srcLength, UChar *dest, int32_t destCapacity, int32_t options, UParseError *parseError, UErrorCode *status)
  • UIDNA_DEFAULT – по умолчанию. В случае ошибки возвращает U_UNASSIGNED_ERROR.
  • UIDNA_ALLOW_UNASSIGNED – если данный флаг установлен, то считается, что не назначенные элементы кода в строке ввода представлены в кодировке Unicode.
  • UIDNA_USE_STD3_RULES – синтаксис доменного имени должен удовлетворять стандартам STD3 ASCII. В случае ошибки возвращает U_IDNA_STD3_ASCII_RULES_ERROR.

Возвращаемое значение – длина преобразованной строки. Для избежания переполнения, необходимо сравнить с destCapacity.

wchar_t* s1 = L"пример.прием";
wchar_t pPunycode[MAX_PATH];
UErrorCode status = U_ZERO_ERROR;

int32_t i = uidna_IDNToASCII(s1, -1, pPunycode, MAX_PATH, UIDNA_USE_STD3_RULES, NULL, &status);

if(status == U_IDNA_STD3_ASCII_RULES_ERROR)
wprintf(L"Error");

wchar_t* s2 = L"xn--e1afmkfd.xn--e1afnjf";
wchar_t pUnicode[MAX_PATH];
UErrorCode status = U_ZERO_ERROR;

int32_t i = uidna_IDNToUnicode(s2, -1, pUnicode, MAX_PATH, UIDNA_ALLOW_UNASSIGNED, NULL, &status);

if(status == U_IDNA_STD3_ASCII_RULES_ERROR)
wprintf(L"Error")

Скрипт приведенный ниже демонстрирует следующие особенности работы с символами в 1С:

  • Символ/КодСимвола работают в диапазоне -1..65535, причем Символ(-1) - строка без символов
  • Скрипт ищет все символы "пустые строки". Некоторые из этих строк отображаются как непустые.
  • Скрипт показывает, какие символы являются "буквами" для языка 1С - это полезно для написания обфускаторов и для проверок самописных парсеров языка 1С (собственно для проверки лексического генератора и написан этот скрипт).
  • Скрипт показывает допустимость символов для XML. Это важно, потому что сервер и клиент 1С в управляемых формах общаются через XML, поэтому при попытке передать недопустимый символ возникнет ошибка времени выполнения. Если при загрузке данных из внешних источников это не учитывать, то может возникнуть ситуация, когда 1С будет всегда падать при открытии, например, справочника.
  • Демонстрируется, что строка в 1С не является null-terminated. В скрипте не демонстрируется, но упомянуто, что ТекстовыйДокумент не умеет корректно работать со строками, содержащими Символ(0)

Сам скрипт проверялся в управляемых формах:


&НаКлиенте
Процедура ВыполнитьТест ( Команда )

РезультатТеста = Новый Массив ;
СтруктураДляПроверкиБукв = Новый Структура ;
Начало = - 2 ;
Конец = 65540 ;

Для Сч = Начало По Конец Цикл

Если Сч % 1024 = 0 Тогда
Состояние ( "Символ № " + Строка ( Сч ));
ОбработкаПрерыванияПользователя ();
КонецЕсли;

СимволПоКоду = Символ ( Сч );
СтруктураРезультат = Новый Структура (
"Номер, Символ, ЭтоСимвол, ПустаяСтрока, ЭтоБуква, ДопустимыйСимволыXML, КорректнаяКонкатенация" );
РезультатТеста . Добавить ( СтруктураРезультат );
СтруктураРезультат . Номер = Сч ;
СтруктураРезультат . Символ = СимволПоКоду ;

//Проверка 1 - Это символ?
//Демонстрируется, что Символ/КодСимвола работают в диапазоне -1..65535, причем Символ(-1) - строка без символов
КодПоСимволу = КодСимвола ( СимволПоКоду );
Если КодПоСимволу <> Сч Тогда
СтруктураРезультат . ЭтоСимвол = Ложь;
Продолжить;
Иначе
СтруктураРезультат . ЭтоСимвол = Истина;
КонецЕсли;

//Проверка 2 - Это пустая строка?
//Неочевидный момент - некоторые "пустые строки" вполне имеют графическое непустое отображение
СтруктураРезультат . ПустаяСтрока = ПустаяСтрока ( СимволПоКоду );

//Проверка 3 - Это буква?
//Буквой считаем символ, который может быть именем поля в структуре. Таких букв достаточно много.
ТекущееЗначение = "" ;
Попытка
Если СтруктураДляПроверкиБукв . Свойство ( СимволПоКоду , ТекущееЗначение ) Тогда
//Заодно сохраняем все "одинаковые" буквы, максимальное количество - 4:Θθϑe2;
СтруктураДляПроверкиБукв [ СимволПоКоду ] = ТекущееЗначение + СимволПоКоду ;
Иначе
СтруктураДляПроверкиБукв . Вставить ( СимволПоКоду , СимволПоКоду );
КонецЕсли;
СтруктураРезультат . ЭтоБуква = Истина;
Исключение
СтруктураРезультат . ЭтоБуква = Ложь;
КонецПопытки;

//Проверка 4 - Допустимые символы XML. Строки с недопустимыми символами нельзя передать с сервера или на сервер.
//При получении данных из любых сторонних источников, перез записью их в БД крайне желательно их проверять на то,
//что они смогут потом быть прочитанными.
СтруктураРезультат . ДопустимыйСимволыXML = ( НайтиНедопустимыеСимволыXML ( СимволПоКоду ) = 0 );

//Проверка 5 - корректность конкатенации
//- очевидно, что для символа с кодом -1 конкатенация не работает (это пустая строка длины 0)
//- менее очевидно, что символы кода 0 успешно конкатенируются. Только ТекстовыйДокумент об этом, к сожалению, не знает
ДлиннаяСтрока = СимволПоКоду + СимволПоКоду + СимволПоКоду + СимволПоКоду + СимволПоКоду ;
СтруктураРезультат . КорректнаяКонкатенация = ( СтрДлина ( ДлиннаяСтрока ) = 5 );

//1. в текстовый документ нельзя вывести "нулевой символ"
//2. Выводим "честно" - последовательно по строкам и колонкам, чтобы не привлекать дополнительные механизмы
ТабличныйДокумент = Новый ТабличныйДокумент ;
СчКолонок = 1 ;
Для каждого КлючИЗначениеСтруктураРезультат Из СтруктураРезультат Цикл
ТабличныйДокумент . Область ( 1 , СчКолонок , 1 , СчКолонок ). Текст = КлючИЗначениеСтруктураРезультат . Ключ ;
СчКолонок = СчКолонок + 1 ;
КонецЦикла;
ТабличныйДокумент . Область ( 1 , СчКолонок , 1 , СчКолонок ). Текст = "АналогичныеСимволы" ;
ТабличныйДокумент . Область ( 1 , СчКолонок + 1 , 1 , СчКолонок + 1 ). Текст = "КоличествоАналогов" ;
СчСтрок = 2 ;
Для каждого СтруктураРезультат Из РезультатТеста Цикл

Если СчСтрок % 1024 = 0 Тогда
Состояние ( "Строка № " + Строка ( СчСтрок ));
ОбработкаПрерыванияПользователя ();
КонецЕсли;

СчКолонок = 1 ;
Для каждого КлючИЗначениеСтруктураРезультат Из СтруктураРезультат Цикл
ТабличныйДокумент . Область ( СчСтрок , СчКолонок , СчСтрок , СчКолонок ). Текст = КлючИЗначениеСтруктураРезультат . Значение ;
СчКолонок = СчКолонок + 1 ;
КонецЦикла;
Если СтруктураРезультат . ЭтоБуква = Истина Тогда
ТабличныйДокумент . Область ( СчСтрок , СчКолонок , СчСтрок , СчКолонок ). Текст = СтруктураДляПроверкиБукв [ СтруктураРезультат . Символ ];
ТабличныйДокумент . Область ( СчСтрок , СчКолонок + 1 , СчСтрок , СчКолонок + 1 ). Текст = СтрДлина ( СтруктураДляПроверкиБукв [ СтруктураРезультат . Символ ]);
КонецЕсли;
СчСтрок = СчСтрок + 1 ;

КонецЦикла;
ТабличныйДокумент . Показать ();

Скрипт пробегает по всем символам и просто выводит на экран табличный документ с результатами.

Фишинг существует уже давно. Невозможно подсчитать, какое количество людей предоставило мошенникам на блюдечке пароли от социальных сетей и почтовых сервисов, данные своих кредитных карт и банковских счетов, не удостоверившись в том, что в адресной строке в момент ввода логина и пароля был именно Vkontakte, а не Vkontaktle. Один из способов, с помощью которого можно замаскировать адрес, это использовать символы из других алфавитов.

Интернационализированные доменные имена (IDN) содержат символы национальных алфавитов, отличающиеся от латинских символов. Для того, чтобы структуру системы доменных имён DNS не нужно было менять, для поддержки других языков используется преображение адресов, содержащих символы национальных алфавитов, в слова из символов ASCII. Такой способ был призван стать «мостом» между англоговорящими и неанглоговорящими пользователями.

Для кодирования символов из других алфавитов в символы ASCII используется Unicode. Стандарт Unicode включает в себя знаки почти всех письменных языков мира — более 136 тысяч символов из 139 современных и утративших актуальность языков. Unicode технически — это массив данных, в котором каждому из символов назначен код в формате ASCII, который затем раскодирует формат UTF — Unicode Transformation Format.

F: U+0046
A: U+0041
R: U+0052
S: U+0053
I: U+0049
G: U+0047
H: U+0048
T: U+0054
✪: U+272A

Буквы из разных языков могут выглядеть похоже или абсолютно идентично. Только в английском языке практически неотличимы «l» и «I» — маленькая «L» и большая «i». Русская и английская маленькая «а» — полностью идентичны. Такие символы называют «гомоглифами», а «гомографы» — слова, в которых они используются. Такой способ обмана пользователей использовался уже много лет. Несколько примеров похожего написания адресов:

xn--farsghtsecurity-xng.com --> farsɩghtsecurity.com
— использована строчная греческая «Йота» — "ι" (U+0269)

Компания Farsight Security искала фишинговые сайты, использующие эту уязвимость, в течение трёх месяцев с 17 октября 2017 года по 10 января 2018, и за это время обнаружила более 116 тысяч страниц, копирующих финансовые сайты, страницы модных брендов и биржи криптовалют и, конечно, социальные сети.


Farsight Security предлагает несколько способов защиты от злоумышленников, использующих данный инструмент, главный из которых — бдительность пользователя.

В данной статье будет рассмотрено, как происходит замена и удаление недопустимых символов в системе 1С, если мы находим недопустимые символы в имени файла и когда недопустимые символы содержит XML.

1. Недопустимые символы в имени файла

Когда имя некоторого файла содержит недопустимые символы, возникает потребность замены этих символов. Для произведения замены нужно оговорить, какой синтаксис имеет функция замены при ошибке недопустимых символов в имени файла. Он представлен на скриншоте со строкой кода далее:



Рис.1 Замена недопустимых символов с имени файла

Также у данной функции есть первичные параметры:

· «ИмяФайла» – параметр со строкой, которая содержит наименование файла;

· «НаЧтоМенять» – параметр со строкой, на которую будут заменены недопустимые символы в названии файла.

Результат работы данной функции – это значение, которое будет возвращаться. В нашем случае это строка, которая содержит новое имя файла, после преобразований.

Рассмотрим пример вызова данной функции:



Рис. 2 функция замены при ошибке недопустимых символов

Также очень важным аспектом является доступность данной функции. В системе 1С функцию можно использовать на сервере, на тонком клиенте, на толстом клиенте и на внешнем соединении.

2. Недопустимые символы в XML

Рассмотрим, как происходит удаление если XML содержит недопустимые символы.

Чтобы выполнить данную процедуру, аналогично предыдущему пункту используем специальную функцию, которая продемонстрирована на строке ниже:



Рис. 3 Функция для удаления недопустимых символов XML

Далее следует оговорить, какие параметры поддерживаются в данной функции. Параметр в данном случае только один – это «Текст-Строка». Это строка, внутри которой требуется провести удаление всех недопустимых символов.

Итогом работы этой функции будет значение, которое возвращается в виде строки, полученной в итоге удаления всех недопустимых символов из XML строки.

Рассмотрим на примере общего вида, который представлен ниже, как будет выглядеть вызов функции по удалению, когда текст XML содержит недопустимые символы:



Рис. 4 Вызов функции для удаления недопустимых символов XML

Использование данной функции доступно для сервера, на тонком и толстом клиентах и для внешнего соединения.

Рассмотрим использование функции «НайтиНедопустимыеСимволыXML» на примере. Данная функция не удаляет, а только производит поиск по символам в строке, которые являются недопустимыми в XML строке:



Рис. 5 Удаление недопустимых символов XML

Чтобы сделать поиск по недопустимым символам более быстрым, попытаемся определить позицию недопустимого символа в тексте XML строки. Для этого в середине цикла дадим функции первичные позиции из поиска. Пример данного применения показан на строчке кода ниже:



Рис. 6 Поиск недопустимого символа в тексте

В данной статье были рассмотрены функции, которые помогают определять и удалять, либо заменять, недопустимые символы в имени файла и в XML строке.

Читайте также: