2014-07-12 5 views
0

Perl/HTML 파일을 UTF-8 형식으로 변경하려고했습니다. 불행히도 양식에 문제가 있습니다. 문제를 보여주는 간단한 테스트 스크립트를 만들었습니다. 모든 작업은 자체적으로 다시로드되므로 입력 한 텍스트가 다시 표시됩니다. 그것은 ASCII 문자로 잘 작동합니다. 독일어로 "Umlaute"(ÄÖÜ)를 입력하자마자 캐릭터가 왜곡됩니다. 러시아 문자 (ЭЯЮ)도 처리 할 수 ​​없습니다. 다음은 스크립트입니다.Perl 및 HTML : UTF8이 양식에서 작동하지 않습니다.

#!/usr/bin/perl 

use utf8; 
use Encode; 
use open ':std', ':encoding(UTF-8)'; 

# Safe query-string in hash: 
$querystring = $ENV{ 'QUERY_STRING' }; 
read(STDIN, $poststring, $ENV{CONTENT_LENGTH}); 
if (($querystring ne "") && ($poststring ne "")) { $querystring .= "&$poststring"; } 
    else { $querystring .= $poststring; } 

$querystring =~ s/&/=/gi; 
%query = split(/=/, $querystring); 
foreach $key (keys(%query)) { 
    $query{$key} =~ tr/+/ /; 
    $query{$key} =~ s/%([\da-f][\da-f])/chr(hex($1))/egi; 
    $uquer{$key} = decode_utf8($query{$key}); 
} 

print "Content-Type: text/html; charset=\"UTF-8\"\n\n"; 
print <<END; 
    <HTML> 
     <HEAD> 
      <META HTTP-EQUIV="Content-Type" content="text/html; charset=utf-8"> 
     </HEAD> 
     <BODY> 
      <FORM NAME="frmeing" METHOD="POST" ACTION="test0.cgi"> 
       <INPUT NAME="df_kurs" TYPE="TEXT" VALUE="$uquer{'df_kurs'}"> 
       <INPUT TYPE="SUBMIT"> 
      </FORM> 
     </BODY> 
    </HTML> 
END 

이 스크립트도 테스트 할 수 있습니다. 이 주소의 온라인 주소는 다음과 같습니다. http://project-website.org/test/test0.cgi 누가 문제가 될 수 있는지 알고 있습니까? 당신의 도움에 미리 감사드립니다!

답변

5

decode_utf8 버전의 버그로 인해 발생했습니다.

$ perl -Mutf8 -MEncode -E' 
    $u = $d = encode_utf8("é"); 
    utf8::upgrade($u); # Changes how the string is stored internally 
    say $u eq $d ?1:0; 
    say decode_utf8($d) eq decode_utf8($u) ?1:0; 
' 
1 
0 

당신이 볼 수 있듯이, $u$d은 동일하지만, decode_utf8의 버전은 다르게 디코딩한다. 특히 $u을 변경하지 않고 반환합니다.

이 문제는 최신 버전의 Encode에서 수정되었습니다. (2.53, 제 생각입니다.)

문제를 해결하는 쉬운 방법은 자신의 버그를 수정하는 것입니다. use open을 사용하면 url 인코딩을 이스케이프 처리하지 않고 UTF-8에서 디코딩하기 전에 STDIN을 UTF-8에서 디코딩하도록 프로그램에 지시합니다.

수정 :

#!/usr/bin/perl 

use utf8;      # Source code is encoded using UTF-8. 
use open ':encoding(UTF-8)'; # Set default encoding for file handles. 
BEGIN { binmode(STDOUT, ':encoding(UTF-8)'); } # HTML 
BEGIN { binmode(STDERR, ':encoding(UTF-8)'); } # Error log 

use Encode; 

# Safe query-string in hash: 
$querystring = $ENV{ 'QUERY_STRING' }; 
read(STDIN, my $poststring, $ENV{CONTENT_LENGTH}); 
if (($querystring ne "") && ($poststring ne "")) { $querystring .= "&$poststring"; } 
    else { $querystring .= $poststring; } 

$querystring =~ s/&/=/gi; 
%query = split(/=/, $querystring); 
foreach $key (keys(%query)) { 
    $query{$key} =~ tr/+/ /; 
    $query{$key} =~ s/%([\da-f][\da-f])/chr(hex($1))/egi; 
    $uquer{$key} = decode_utf8($query{$key}); 
} 

print "Content-Type: text/html; charset=\"UTF-8\"\n\n"; 
print <<END; 
    <HTML> 
     <HEAD> 
      <META HTTP-EQUIV="Content-Type" content="text/html; charset=utf-8"> 
     </HEAD> 
     <BODY> 
      <FORM NAME="frmeing" METHOD="POST"> 
       <INPUT NAME="df_kurs" TYPE="TEXT" VALUE="$uquer{'df_kurs'}"> 
       <INPUT TYPE="SUBMIT"> 
      </FORM> 
     </BODY> 
    </HTML> 
END 

하지만 당신은 정말 CGI.pm.를 사용해야합니다

#!/usr/bin/perl 

use strict; # Always! 
use warnings; # Always! 

use utf8;      # Source code is encoded using UTF-8. 
use open ':encoding(UTF-8)'; # Set default encoding for file handles. 
BEGIN { binmode(STDOUT, ':encoding(UTF-8)'); } # HTML 
BEGIN { binmode(STDERR, ':encoding(UTF-8)'); } # Error log 

use CGI qw(-utf8); 
use Encode; 

my $cgi = CGI->new(); 
my %uquer = $cgi->Vars(); 

print $cgi->header('text/html; charset=UTF-8'); 
print <<END; 
    <HTML> 
     <HEAD> 
      <META HTTP-EQUIV="Content-Type" content="text/html; charset=utf-8"> 
     </HEAD> 
     <BODY> 
      <FORM NAME="frmeing" METHOD="POST"> 
       <INPUT NAME="df_kurs" TYPE="TEXT" VALUE="$uquer{'df_kurs'}"> 
       <INPUT TYPE="SUBMIT"> 
      </FORM> 
     </BODY> 
    </HTML> 
END 
관련 문제