Как заставить FastCGI кодировать данные формы как UTF-8, так как CGI.pm имеет опцию? - PullRequest
2 голосов
/ 15 февраля 2011

Попытка запустить старые CGI-скрипты под FastCGI. Печать без дополнительных параметров дает правильный вывод: print $q->div( $q->param("text") )

Но при печати с хэшем дополнительных параметров для CGI-методов print $q->div( {-id=>"id"}, $q->param("text") ) он разрушает сформированные данные UTF-8 ('õäöüžš' -> 'õäöüžš')

Это происходит только с параметрами CGI, в скриптах определенные переменные работают нормально (примеры 3 и 4). Все отлично работает под обычным CGI (с флагом -utf8).

Пример сценария, превращенного в 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();

}

Первый блок в порядке, второй сломан, 3 и 4 также в порядке:

Обычный 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 form-data нет флага utf8, и я не понимаю, как его правильно форсировать? Под CGI.pm я объявляю как:

use CGI qw(:all -utf8);

а как с FastCGI?

Ответы [ 2 ]

5 голосов
/ 17 августа 2011

1) CGI :: Fast является подклассом CGI.pm , поэтому вы можете указать те же аргументы импорта.

use CGI::Fast (-utf8);

2) FCGI Потоки реализованы с использованием более старого API потока, TIEHANDLE . Применение слоев PerlIO с использованием binmode () не имеет никакого эффекта. Правильным решением будет закодировать ваши данные перед их выводом, но если это не вариант, я могу предложить следующее «горячее исправление»:

#!/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 голосов
/ 15 февраля 2011

Я бы сделал:

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