アプリ版:「スタンプのみでお礼する」機能のリリースについて

http://oshiete.goo.ne.jp/qa/6746313.html


で質問した者です。
どうもお答え頂いたエンコードと、ブラウザ様が勝手に行うエンコードのルールが違うようです。

Perlは全てutf8、出力するHTMLもutf8、ブラウザ様が勝手にエンコードしたデータはなんですかあれ?

いろいろ試しましたが、なにをどうやっても文字化けします。

A 回答 (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;
}
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
    • good
    • 0
この回答へのお礼

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

お礼日時:2011/05/25 23:12

シチュエーションがよくわからないので的外れの回答かもしれませんが・・・


まず、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メソッドを使いましょう。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!