はくしゅ

2020年7月9日

今回の文字コードの問題でまた少し知識が増えたので
実害はほとんど無いけど以前から度々文字化けしまくっていた
拍手のログ画面をどうにかする事にしました。
拍手自体はまったく問題なく使えるので
利用者には全然実害無いのですが
管理側としては拍手を貰った該当の記事タイトルは文字化けするし
コメントも一部文字化けするので憶測で参照したりしてたので
あんまり困るものでもないけれど、折角文字コード問題やらの解決方法が判ったので
修正して見た次第。
ウチで使っている拍手はレンタルサービスではなく
phpで作られたgj(グッジョブ)というプログラムで
設置と設定だけすればあとは勝手に各記事ごとに拍手ボタンが追加されて
拍手ボタンを押せば記事ごとにログを作成し
どの記事に対してボタンが押されたか、コメントが入ったか
何回押されたかを全部単独で集計してくれるので
限りなくレンタルサービス並の機能を持っているので便利です。
ですが、これ何故か
作成されたログが取得した記事タイトルが時々文字化けします。
ウチの環境が悪いのかgjの問題なのか判りかねてましたが
文字化けと言えば文字コードなので、文字コードも調べたけれど
作者ページではgjはUTF-8で作られてるというだけでそれ以外の情報は無し。
でもログを調べるとShift_JIS。何でログだけsjisなのか。
ただまぁそれでも動いていたので問題は無いのですが・・・。
で、今回blog全部をUTF-8にしたのでphpプログラムは
無条件でUTF-8でエンコされるようになってしまったので
拍手のログを見るページも全部UTF-8になってしまい
ログも全部文字化けしてしまったので不便になってしまいました。
このページだけ従来のShift_JISで表示するようにすればいいのですが
折角なら全部UTF-8になるように改造しようかと。
プログラムソースが(横に)長いので追記に↓


とりあえずphpプログラムを覗いてみる事に。
gjの本体自体はUTF-8で保存してあるので本体は問題ないですが
ログファイルがシフトJISになってるので
書き込み時にシフトJISで書き込まれているワケ。
わたしゃ知識が偏ってるので書き込み時に何でシフトJISになってるのか知りません。
そもそも書き込み時に文字コードを指定できるのかも分かりません。
どっかでシフトJISとして文字列を扱ってるのか分かりませんが
Shift_JISと書いてある部分は全部UTF-8にしたけど変わらず。
でも書き込んだファイルがシフトJISなのは間違いないので
書き込む前にUTF-8に変換すればいいと思って
書き込み手前に文字コード変換を追加してみた。
具体的にはこんな感じ。
改造前:

fwrite($file2, $date . “," . $pagename . “," . htmlspecialchars($pageurl) . “," . htmlspecialchars(urldecode(substr($_GET['gj_message’],0,$STRLEN))) . “," . $ip . “," . $host . “," . $ref . “\r\n");
fclose($file2);

改造後:

$str = $date . “," . $pagename . “," . htmlspecialchars($pageurl) . “," . htmlspecialchars(urldecode(substr($_GET['gj_message’],0,$STRLEN))) . “," . $ip . “," . $host . “," . $ref . “\r\n";
$str = mb_convert_encoding($str,"UTF-8″ , “Shift_JIS");
fwrite($file2, $str);
fclose($file2);

fwriteの手前に、とりあえず変数$strに書き込む内容を入れて
その後で$strの中身の文字コードをmb_convert_encodingでシフトJISからUTF-8に変換。
そして変換してからfwriteで内容をファイルに書き込むように。
こうするだけでログファイルは文字コードUTF-8で作成されるので
phpが強制的にUTF-8で表示しても問題なしに。
同じように新着メッセージを表示するnew.datの書き込み部分も
改造前:

fwrite($fnew, $date . “," . $pagename . “," . htmlspecialchars($pageurl) . “," . htmlspecialchars(urldecode(substr($_GET['gj_message’],0,$STRLEN))) . “," . $ip . “," . $host . “," . $ref . “\n");

改造後:

$str = $date . “," . $pagename . “," . htmlspecialchars($pageurl) . “," . htmlspecialchars(urldecode(substr($_GET['gj_message’],0,$STRLEN))) . “," . $ip . “," . $host . “," . $ref . “\n";
$str = mb_convert_encoding($str,"UTF-8″ , “Shift_JIS");
fwrite($fnew, $str);

やってる事は同じ。
new.datの方はこの後にもfwriteで拍手回数を書き込んでるけど
半角数字のデータなので関係ないです、多分。
今回はUTF-8で書き込むようにしましたが
これがもしEUC-JPで書き込みたい場合は、UTF-8をEUC-JPにするだけでいいと思う。
何なら初期設定の所に$tcodeとか変数追加して

//ログファイルに書き込む文字コードを指定、空白ならシフトJISで書き込み
//"EUC-JP"か"UTF-8″を指定。それ以外は無視されます
$tcode = “UTF-8";

とかにして、さっきの

$str = mb_convert_encoding($str,"UTF-8″ , “Shift_JIS");

if ($tcode === “UTF-8" || $tcode === “EUC-JP") {
$str = mb_convert_encoding($str,$tcode , “Shift_JIS");
}

にすれば、$tcodeにUTF-8等の値があったらその文字コードで変換
値が無い場合や、UTF-8とEUC-JP以外の文字が入っていた場合は
この条件式を通らないので普通にシフトJISのまま書き込みをする
といった感じになるはず。
適当に実装してみたけど、ウチでは問題なく動いてるのでこれでいいや。
xmlも作成してるっぽいので、上記の$tcodeを参照するようにした場合は

if(!fwrite($XML, $xmldata->dump_mem(true, “UTF-8" )))

の"UTF-8″を$tcodeに書き換えたり、

<?xml version=’1.0′ encoding="UTF-8″ ?>

も$tcodeにする必要あるかも。やってないからわからん。
・・・仮にもプログラムを少し齧ってたのになんて適当なんだ・・・。