Skip to content
Опубликовано: 2016-02-10
Теги: perl

Получение 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