• ベストアンサー

UTF8 エンコード/デコード

http://okwave.jp/qa/q6746313.html で質問した者です。 どうもお答え頂いたエンコードと、ブラウザ様が勝手に行うエンコードのルールが違うようです。 Perlは全てutf8、出力するHTMLもutf8、ブラウザ様が勝手にエンコードしたデータはなんですかあれ? いろいろ試しましたが、なにをどうやっても文字化けします。

質問者が選んだベストアンサー

  • ベストアンサー
  • ralf124c
  • ベストアンサー率52% (232/446)
回答No.2

昔作った検証用サンプルも入れときます 参考になれば幸いです [ファイル名:index.cgi:UTF-8]↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ #!/usr/bin/perl my $sDT = '漢字です'; my $sDT_URL = './test.cgi?T1='.URL_Encode($sDT); print <<HTML_BODY; Content-type: text/html\n\n <html> <head> <meta http-equiv="Content-Language" content="ja"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>TEST UTF-8</title> </head> <body> <p><a href="$sDT_URL">CLICK</a></p> </body> </html> HTML_BODY exit; ## URLエンコード sub URL_Encode{ my ($p01,@waste)=@_; $p01 =~ s/([^\w])/'%'.unpack('H2',$1)/eg; $p01 =~ tr/ /+/; return $p01; } ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ [ファイル名:test.cgi:UTF-8]↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ #!/usr/bin/perl my %hIN = readMethod(); my $ss = $hIN{T1}; print "Content-type: text/html\n\n"; print <<HTML_BODY; <html> <head> <meta http-equiv="Content-Language" content="ja"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>TEST UTF-8</title> </head> <body> 送信内容:$ss </body> </html> HTML_BODY exit; ## ******************************************************** ## メソッド読み込み ## ******************************************************** sub readMethod{ my %rm_in; my $paramPost; if($ENV{REQUEST_METHOD} eq 'GET'){ my @tmpPrmt = split(/&/,$ENV{'QUERY_STRING'}); foreach(@tmpPrmt){ my ($p1,$v1) = split(/=/,$_); $v1 =~ tr/+/ /; $v1 =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/ego; if(exists($rm_in{$p1})){ $rm_in{$p1} .= "\t".$v1; }else{ $rm_in{$p1}=$v1; } } }elsif($ENV{REQUEST_METHOD} eq 'POST'){ read(STDIN, $paramPost, $ENV{'CONTENT_LENGTH'}); my @tmpData=split(/&/,$paramPost); foreach(@tmpData){ my ($p1,$p2)=split(/=/,$_); $p1 =~ tr/+/ /; $p1 =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/ego; $p2 =~ tr/+/ /; $p2 =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/ego; if(exists($rm_in{$p1})){ $rm_in{$p1} .= "\t".$p2; }else{ $rm_in{$p1}=$p2; } } }else{ print "die for error..."; } return %rm_in; } ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

jelfe
質問者

お礼

丁寧にありがとうございます。 perlのutf8解釈に問題があったみたいで、 入出力の際は全てutfフラグをつけたり外したりすることで解決しました。

その他の回答 (1)

  • ralf124c
  • ベストアンサー率52% (232/446)
回答No.1

シチュエーションがよくわからないので的外れの回答かもしれませんが・・・ まず、CGIでURLエンコードが必要な状況というのはGETメソッドでのリンクを作りたい場合以外考えにくいのですが 通常、URLエンコードに文字コード云々は関係ないと思います ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ ## URLエンコード sub URL_Encode{ my ($p01,@waste)=@_; $p01 =~ s/([^\w])/'%'.unpack('H2',$1)/eg; $p01 =~ tr/ /+/; return $p01; } ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 以上のサブルーチンで ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ my $sDT = '漢字です'; my $sDT_URL = './test.cgi?HOGEHOGE='.URL_Encode($sDT); ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ こんな感じで呼び出すだけです。 URLエンコードは7ビット以上のデータを便宜上7ビットコードの文字列で表現するだけのものなので文字コードの受け渡し前後で化けるならば、プログラム内部でのデータの扱いに問題があるからです。 よくある失敗パターンとして 1.プログラムがEUCやS-JISで書かれていて、変数内のデータでUTF-8を扱っていたりする場合(UTF-8で保存したあと修正などのためS-JISで開いてそのままセーブしてしまうパターン) 2.BOM付きコードを扱っている場合 3.モジュールを含むPerlのバージョンが古すぎて書かれているプログラムの文字コードが判別あるいは正常処理ができない 4.ファイルをサーバに転送する際に文字コードを変換している 5.HTMLでの表示時に「charset」や「Content-Language」をちゃんと指定していない 6.HTMLとCSSとJavaScriptで文字コードが統一されていない、又はそれを認識していても相互変換ができていない などでしょうか レンタルサーバなどでPerl5.8以前のものがいまだ使われていることもあるので要注意です。 CGIが動くならFUTOMIのサーバアナライザなどで環境を把握しておく方が良いでしょう。 ちなみにURLデコードは以下の通り ## URLデコード sub URL_Decode{ my ($p01,@waste)=@_; $p01 =~ tr/+/ /; $p01 =~ s/%([a-fA-F0-9]{2})/chr(hex($1))/ge; return $p01; } 蛇足ですが、GETメソッドでデータの受け渡しには文字数制限や、アドレス欄に見えることで安全面に問題があるので、できるだけPOSTメソッドを使いましょう。

関連するQ&A