如何强制FastCGI像CGI.pm那样将表单数据编码为UTF-8?

问题描述 投票:3回答:3

[尝试在FastCGI下运行旧的CGI脚本。没有额外参数的打印将提供正确的输出:print $q->div( $q->param("text") )

但是,当使用CGI方法print $q->div( {-id=>"id"}, $q->param("text") )的额外参数散列进行打印时,它将破坏UTF-8形成的数据('õäöüžš'->'õäö¼¼¾¾¾'']

仅使用CGI参数会发生,在脚本定义的变量中可以正常工作(示例3和4)。在普通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如何?

perl utf-8 cgi fastcgi
3个回答
5
投票

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;
}

0
投票

使用Git 2.27(2020年第二季度),Gitweb应该解决此问题。

请参阅commit 2ecfcdeJulien Moutinho (ju1m)(2020年3月29日)。((ju1m中的Junio C Hamano -- gitster --合并,2020年4月22日)>

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

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

FCGI流是使用较旧的流API:commit 7a8bb6d实现的,因此使用gitweb来应用gitweb层对其没有影响。

此补丁中的解决方案是重新定义TIEHANDLE函数以使用UTF-8作为输出编码

,但PerlIObinmode()仍必须以原始二进制模式输出。

以前曾在2012年报告过此问题和解决方案:

  • Git邮件列表:FCGI::Stream::PRINT
  • git_blob_plain()

-2
投票

我愿意:

© www.soinside.com 2019 - 2024. All rights reserved.