Получение codepoint символа
В процессе работы с LDAP столкнулся с неверной интерпретацией некоторых символов. Особую проблему доставляла запятая и знак равенства. Для них быстро были найдены коды ,
— \2C
и =
—\3D
. Тут, казалось бы, можно забыть о проблеме, но на деле оказалось не совсем так.
Этот скрипт используется в том числе для проверки валидности введенных пользователем пары логин-пароль. Со сменой политики паролей вдруг выяснилось, что проверка валидности не проходит, если в пароле используются специальные символы.
Так как в LDAP для non-ASCII и специальных символов используется подстановка codepoit’а, то для решения проблемы был придуман такой способ:
my $ldappass = join '', map {$_ =~ /\w/ ? $_ : sprintf "\\%02X", unpack("U*", $_) } split //, $password;
Здесь идет дополнительная проверка, что символ из разряда буква-цифра. Без нее блок map
‘а будет выглядеть проще и соответственно будут преобразовываться все символы:
... map { sprintf "\\%02X", unpack("U*", $_) } ...
А для обратного преобразования из codepoint в символы можно использовать такой способ (работает в случае если все символы представлены своими codepoint):
say map chr (hex, split /\\/, $ldappass)
А вот цельный пример преобразования туда-обратно одной строкой:
echo -n '!~Фамилия,@ Имя Отчество`[]'|perl -E 'use utf8::all; say map {sprintf "\\%04X", unpack("U*", $_)} split //, <>'|perl -E 'use utf8::all;say map chr hex, split /\\/, <>'
Итог выполнения этой строки:
\0021\007E\0424\0430\043C\0438\043B\0438\044F\002C\0040\0020\0418\043C\044F\0020\041E\0442\0447\0435\0441\0442\0432\043E\0060\005B\005D