如何强制 FastCGI 将表单数据编码为 UTF-8,就像 CGI.pm 有选项一样?

发布于 2024-10-17 09:23:33 字数 3055 浏览 1 评论 0原文

尝试在 FastCGI 下运行旧的 CGI 脚本。不带额外参数的打印会给出正确的输出: print $q->div( $q->param("text") )

但是当使用 CGI 方法的额外参数哈希打印时 print $q->div( {-id=>"id"}, $q->param("text") ),它会破坏 UTF-8 格式的数据 ('õäöüžš' ->; '

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????一切都在普通 CGI 下完美运行(使用“-utf8”-flag)。

FastCGI 转换的示例脚本,称为 test.fcgi?text=õäöüžš 应该给出四个相等的块:

#!/usr/bin/perl -w --

use strict;
use CGI::Fast qw(:all);
use locale;
use utf8;

BEGIN {
        binmode(STDIN);                       # Form data
        binmode(STDOUT, ':encoding(UTF-8)');  # HTML
        binmode(STDERR, ':encoding(UTF-8)');  # Error messages
}

my ($q) = ();
my $test = "õäöüžš";

while ($q = new CGI::Fast) {

        print $q->header(-type=>"text/html", -charset=>"utf-8"), 
                $q->start_html(-encoding=>"utf-8");

        print "1: ",
                $q->div(  $q->param('text') ),
                "<br />",
                "2: ",
                $q->div( {-id=>"id"},  $q->param('text') ),
                "<br />",
                "3: ",
                $q->div(  $test ),
                "<br />",
                "4: ",
                $q->div( {-id=>"id"},  $test ),
        $q->end_html();

}

第一个块很好,第二个块损坏,第三个和第四个也很好:

普通的 CGI 示例,因为它给出了所有4正确的方法:

#!/usr/bin/perl -w --

use strict;
use CGI qw(:all -utf8);
use locale;
use utf8;

BEGIN {
        binmode(STDIN);                       # Form data
        binmode(STDOUT, ':encoding(UTF-8)');  # HTML
        binmode(STDERR, ':encoding(UTF-8)');  # Error messages
}

my ($q) = ();
my $test = "õäöüžš";
$q = new CGI;

        print $q->header(-type=>"text/html", -charset=>"utf-8"), 
                $q->start_html(-encoding=>"utf-8");

        print "1: ",
                $q->div(  $q->param('text') ),
                "<br />",
                "2: ",
                $q->div( {-id=>"id"},  $q->param('text') ),
                "<br />",
                "3: ",
                $q->div(  $test ),
                "<br />",
                "4: ",
                $q->div( {-id=>"id"},  $test ),
        $q->end_html();

在我看来,FastCGI表单数据没有utf8标志,我不明白,如何正确强制它?在 CGI.pm 下我声明为:

use CGI qw(:all -utf8);

但是 FastCGI 怎么样?

Trying to run old CGI-scripts under FastCGI. Printing without extra parameters gives proper output: print $q->div( $q->param("text") )

But when printing out with extra parameters hash for CGI-methods print $q->div( {-id=>"id"}, $q->param("text") ), it ruins UTF-8 formed data ('õäöüžš' -> 'õäöüžš')

It happens only with CGI parameters, in script defined variables work fine (examples 3 and 4). Everything works perfecty under ordinary CGI (with "-utf8"-flag ).

FastCGI-turned example script, called as test.fcgi?text=õäöüžš should give four equal blocks:

#!/usr/bin/perl -w --

use strict;
use CGI::Fast qw(:all);
use locale;
use utf8;

BEGIN {
        binmode(STDIN);                       # Form data
        binmode(STDOUT, ':encoding(UTF-8)');  # HTML
        binmode(STDERR, ':encoding(UTF-8)');  # Error messages
}

my ($q) = ();
my $test = "õäöüžš";

while ($q = new CGI::Fast) {

        print $q->header(-type=>"text/html", -charset=>"utf-8"), 
                $q->start_html(-encoding=>"utf-8");

        print "1: ",
                $q->div(  $q->param('text') ),
                "<br />",
                "2: ",
                $q->div( {-id=>"id"},  $q->param('text') ),
                "<br />",
                "3: ",
                $q->div(  $test ),
                "<br />",
                "4: ",
                $q->div( {-id=>"id"},  $test ),
        $q->end_html();

}

First block is fine, second broken, 3rd and 4th also fine:

Ordinary CGI-example as that gives all 4 right way:

#!/usr/bin/perl -w --

use strict;
use CGI qw(:all -utf8);
use locale;
use utf8;

BEGIN {
        binmode(STDIN);                       # Form data
        binmode(STDOUT, ':encoding(UTF-8)');  # HTML
        binmode(STDERR, ':encoding(UTF-8)');  # Error messages
}

my ($q) = ();
my $test = "õäöüžš";
$q = new CGI;

        print $q->header(-type=>"text/html", -charset=>"utf-8"), 
                $q->start_html(-encoding=>"utf-8");

        print "1: ",
                $q->div(  $q->param('text') ),
                "<br />",
                "2: ",
                $q->div( {-id=>"id"},  $q->param('text') ),
                "<br />",
                "3: ",
                $q->div(  $test ),
                "<br />",
                "4: ",
                $q->div( {-id=>"id"},  $test ),
        $q->end_html();

It seems to me, that with FastCGI form-data has no utf8-flag on and i don't understand, how to properly force it? Under CGI.pm i declare as:

use CGI qw(:all -utf8);

But how with FastCGI?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

↙温凉少女 2024-10-24 09:23:34

在 Git 2.27(2020 年第 2 季度)中,Gitweb 应该可以解决该问题。

请参阅 提交 2ecfcde(2020 年 3 月 29 日),作者:朱利安·穆蒂尼奥 (ju1m)
(由 Junio C Hamano -- gitster -- 合并于 提交 7a8bb6d,2020 年 4 月 22 日)

gitweb:修复 UTF-8 编码使用 CGI::Fast

签字人:朱利安·穆蒂尼奥

FCGI 流是使用旧的流 API 实现的:TIEHANDLE,因此使用 binmode() 应用 PerlIO 层对它们没有影响。

此补丁中的解决方案是重新定义FCGI::Stream::PRINT函数以使用UTF-8作为输出编码git_blob_plain( )git_snapshot() 仍必须以原始二进制模式输出。

此问题和解决方案早在 2012 年就已报告过:

With Git 2.27 (Q2 2020), Gitweb should fix the issue.

See commit 2ecfcde (29 Mar 2020) by Julien Moutinho (ju1m).
(Merged by Junio C Hamano -- gitster -- in commit 7a8bb6d, 22 Apr 2020)

gitweb: fix UTF-8 encoding when using CGI::Fast

Signed-off-by: Julien Moutinho

FCGI streams are implemented using the older stream API: TIEHANDLE, therefore applying PerlIO layers using binmode() has no effect to them.

The solution in this patch is to redefine the FCGI::Stream::PRINT function to use UTF-8 as output encoding, except within git_blob_plain() and git_snapshot() which must still output in raw binary mode.

This problem and solution were previously reported back in 2012:

与酒说心事 2024-10-24 09:23:34

我会这样做:

use strict;
use CGI;
CGI->compile();
use CGI::Fast;
use utf8;
while (new CGI::Fast) {
    $CGI::PARAM_UTF8=1;# may be this????
    my $q =CGI->new;
    #rest of the code should work
}

I would do:

use strict;
use CGI;
CGI->compile();
use CGI::Fast;
use utf8;
while (new CGI::Fast) {
    $CGI::PARAM_UTF8=1;# may be this????
    my $q =CGI->new;
    #rest of the code should work
}
征﹌骨岁月お 2024-10-24 09:23:33

1) CGI::FastCGI.pm,因此您可以指定相同的导入参数。

use CGI::Fast (-utf8);

2) FCGI 流是使用旧的流 API 实现的,TIEHANDLE。使用 binmode() 应用 PerlIO 层没有任何效果。正确的解决方案是在输出数据之前对其进行编码,但如果这不是一个选项,我可以提供此热补丁:

#!/usr/bin/perl
use strict;
use warnings;
use utf8;

use CGI::Fast (-utf8);
use FCGI      ();
use Encode    ();

my $enc = Encode::find_encoding('UTF-8');
my $org = \&FCGI::Stream::PRINT;
no warnings 'redefine';
local *FCGI::Stream::PRINT = sub {
    my @OUTPUT = @_;
    for (my $i = 1; $i < @_; $i++) {
        $OUTPUT[$i] = $enc->encode($_[$i], Encode::FB_CROAK|Encode::LEAVE_SRC);
    }
    @_ = @OUTPUT;
    goto $org;
};

my $literal = "õäöüžš";

while (my $q = CGI::Fast->new) {
    print $q->header(-type => "text/html", -charset => "UTF-8"),
          $q->start_html(-encoding => "UTF-8"),
          $q->p("Text 1:" . $literal),
          $q->p("Text 2:" . $q->param('text')),
          $q->end_html;
}

1) CGI::Fast is a subclass of CGI.pm, so you can specify the same import arguments.

use CGI::Fast (-utf8);

2) FCGI streams are implemented using the older stream API, TIEHANDLE. Applying PerlIO layers using binmode() has no effect. The proper solution would be to encode your data before outputting it, but if thats not an option I can offer this hotpatch:

#!/usr/bin/perl
use strict;
use warnings;
use utf8;

use CGI::Fast (-utf8);
use FCGI      ();
use Encode    ();

my $enc = Encode::find_encoding('UTF-8');
my $org = \&FCGI::Stream::PRINT;
no warnings 'redefine';
local *FCGI::Stream::PRINT = sub {
    my @OUTPUT = @_;
    for (my $i = 1; $i < @_; $i++) {
        $OUTPUT[$i] = $enc->encode($_[$i], Encode::FB_CROAK|Encode::LEAVE_SRC);
    }
    @_ = @OUTPUT;
    goto $org;
};

my $literal = "õäöüžš";

while (my $q = CGI::Fast->new) {
    print $q->header(-type => "text/html", -charset => "UTF-8"),
          $q->start_html(-encoding => "UTF-8"),
          $q->p("Text 1:" . $literal),
          $q->p("Text 2:" . $q->param('text')),
          $q->end_html;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文