【发布时间】:2023-03-23 09:40:01
【问题描述】:
通过这个论坛,我了解到使用以下方法将 CGI 输入(来自 escape()d Ajax 调用或普通 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 转换?
更新:
我更喜欢保持非模块化,因为唯一的黑盒就是 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 ($_)"); }
}
}
以类似的方式,如果可以提取或复制 Encode 的 UTF-8 解码函数,那就太好了。
【问题讨论】:
-
编码是 Perl 自带的,难道“做对了”不应该胜过其他任何事情吗?模块就是代码。
-
我在Effective Perl Programming 中介绍了大部分这些内容,我想我之前已经向您提到过。编码是执行此操作的本机方式。 Perl 将大块的功能分成模块,这样你就不必使用你不想要的东西。
-
模块不是黑匣子。你可以看看他们的来源。大多数人并不喜欢 CGI。他们向不知道自己在做什么的人推荐它,因为它至少是一个起点。例如,您的 CGI 解析器被严重破坏,原因与其他不知道自己在做什么的人破坏事物的原因相同。例如,& 并不总是参数分隔符,参数可以有多个值。你两个都不处理。查看 CGI.pm 以了解它的作用以及您必须处理的内容。
-
您说:更安全的方法 [...] 是执行以下操作 [...]。 But this is not what I said. 我特别推荐
URI::Escape::XS模块而不是unpack。 XS 模块的运行速度与内置模块的速度相同,因此您对性能的关注没有任何影响。正如 brian 所说,profile 首先,您会惊讶于您的程序实际花费的时间。