На этом форуме я узнал, что не хорошая идея использовать следующее для преобразования входных данных CGI (из вызова Ajax escape () d или обычной записи HTML-формы) в UTF -8:
read (STDIN, $_, $ENV{CONTENT_LENGTH});
s{%([a-fA-F0-9]{2})}{ pack ('C', hex ($1)) }eg;
utf8::decode $_;
Более безопасный способ (который, например, не пропускает поддельные символы) заключается в следующем:
use Encode qw (decode);
read (STDIN, $_, $ENV{CONTENT_LENGTH});
s{%([a-fA-F0-9]{2})}{ pack ('C', hex ($1)) }eg;
decode ('UTF-8', $_, Encode::FB_CROAK);
Я бы, однако, очень хотел бы избегать использования каких-либо модулей (включая XSLoader, Exporter и все остальное, что они приносят с собой). Эта функция предназначена для большого сайта, управляемого mod_perl, и я думаю, что и производительность, и удобство обслуживания будут лучше без модулей (тем более что текущий код не использует их).
Полагаю, одним из подходов было бы изучить модуль Encode и выделить функции и константы, используемые для вызова «decode ('UTF-8', $ _, Encode :: FB_CROAK)». Я не достаточно знаком с модулями Unicode и Perl, чтобы сделать это. Может быть, кто-то другой способен сделать это или знает аналогичный, безопасный «нативный» способ преобразования UTF-8?
UPDATE:
Я предпочитаю хранить вещи немодулярными, потому что тогда единственным черным ящиком является собственный компилятор Perl (если, конечно, вы не копаетесь в библиотеках модулей).
Иногда вы видите, как большие модули заменяются несколькими конкретными строками кода. Например, вместо модуля CGI.pm (в который люди также влюблены) можно использовать следующее для разбора сообщений AJAX:
my %Input;
if ($ENV{CONTENT_LENGTH}) {
read (STDIN, $_, $ENV{CONTENT_LENGTH});
foreach (split (/&/)) {
tr/+/ /; s/%([a-fA-F0-9]{2})/pack("C", hex($1))/eg;
if (m{^(\w+)=\s*(.*?)\s*$}s) { $Input{$1} = $2; }
else { die ("bad input ($_)"); }
}
}
Аналогичным образом было бы замечательно, если бы можно было извлечь или скопировать функцию декодирования UTF-8 в Encode.