2019年1月21日月曜日

Perl uri_unescape で文字化け

実は文字化けにはその後も苦しんでおりまして。
原因となる現象をようやく突き止めましたのでサンプルプログラムを公開しますね。

use Carp::Heavy;
use strict;
use URI::Escape;
use Encode;
use encoding 'utf-8';

my $a1 = '%E8%A9%A6%E9%A8%93';
my $b0 = '試験';
my $b1 = uri_escape_utf8($b0); #内容は '%E8%A9%A6%E9%A8%93'
print("$a1\n");
print("$b1\n");
print("1\n") if($a1 eq $b1);    #当然のごとく1が出力される

my $a2 = uri_unescape($a1);
my $b2 = uri_unescape($b1);
print("1\n") if($a2 eq $b2);    #なぜか 1 が表示されない
print("$b2\n"); #こちらは '試験'
print("$a2\n"); #文字化け
exit;


use encoding 'utf-8' を取ったり use utf8; にしたりすると他所に
大影響が出てしまうため変更できません。

これ。本当にハマりましたよ。
いったい何がどうなっているのかさっぱりわかりませんでした。

※実際には CGI 上のパラメータが文字化けしてました。

上記の謎の動作ですが
$a1= encode_utf8($a1);
を呼び出すことで期待通りの動きをすることがわかりました。

さて、本番環境に対応しようと・・・
my $cgi = new CGI();
my $a2 = $chi->param('a2');
文字化けです。
CGI の sub new で取得するuri_encode されたパラメータに対して事前に
encode_utf8を実行しなければならないのに、POSTリクエストだから標準
入力を変更する術が見つかりません。

じゃあ、ってことで呼び出し側を GET にしましたら、なんの変更も加えず
文字化けしなくなりましたよ。
Perlモジュールのバージョンの影響かと思い、さんざん調査すること3日
こういうのって、あっけなく解決するもんなんですねぇ
あー眠たい。