Как я могу преобразовать вход CGI в UTF-8 без модуля кодирования Perl? - PullRequest
0 голосов
/ 19 сентября 2010

На этом форуме я узнал, что не хорошая идея использовать следующее для преобразования входных данных 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.

Ответы [ 2 ]

6 голосов
/ 19 сентября 2010

Не предварительно оптимизируйте.Сначала сделайте это обычным способом, а затем профилируйте и сравните тест, чтобы увидеть, где вам нужно оптимизировать.Люди, как правило, тратят все свое время где-то еще, поэтому начинать с завязанными глазами и надевать на себя наручники не дает никакой пользы.

Не бойтесь модулей.Задача mod_perl - загружать все как можно меньше раз, чтобы время запуска и время загрузки модуля были незначительными.

1 голос
/ 21 сентября 2010

Не используйте escape() для создания ваших опубликованных данных. Это не совместимо с URL-кодированием, это мутантная странность JavaScript, которая обычно никогда не должна использоваться. Одним из недостатков является то, что он будет кодировать не-ASCII-символы в нестандартные последовательности %uNNNN на основе кодовых единиц UTF-16 вместо стандартного UTF-8 в кодировке URL. Ваш текущий код не сможет справиться с этим.

Обычно вместо этого следует использовать encodeURIComponent().

Если вам необходимо самостоятельно декодировать введенный URL-адрес, а не использовать библиотеку форм (а это означает, что вы не сможете обрабатывать multipart/form-data), вам потребуется преобразовать символы + в пробелы перед заменой % слэш. Эта замена стандартна в отправке форм (но не в других местах в данных в кодировке URL).

Чтобы убедиться, что ввод действителен в формате UTF-8, если вы действительно не хотите использовать библиотеку, попробуйте это регулярное выражение . Он также исключает некоторые управляющие символы (вы можете изменить его, чтобы исключить другие).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...