フォームの入力項目で特定の漢字(琥珀、など)を入力してsubmitし、PHP側でprintで表示させると文字化けしてしまうのですが、これを回避する方法はありますでしょうか?
なおPHPソースはEUC-JPで記述し、HTML出力時にSJISに変換しています。
PHPバージョン4.3.11で、mbstring回りの設定は以下の通りです。
mbstring.detect_order no value
mbstring.encoding_translation On
mbstring.func_overload 0
mbstring.http_input auto
mbstring.http_output SJIS
mbstring.internal_encoding EUC-JP
mbstring.language Japanese
mbstring.script_encoding no value
mbstring.substitute_character no value
<input type=”hidden” value=”あ美乳”>のおまじないを入れる以外に良い方法があったら教えて下さい。
http://jp.php.net/manual/ja/function.header.php
PHP: header - Manual
header関数でContent-type、charsetを明示してはいかがでしょうか?
header(”Content-type: text/html;charset=Shift-JIS”);
http://www.shtml.jp/mojibake/sjis_cgi.html
CGIで特定の文字(表・予・申・能など)が文字化けする
php.iniのmagic_quotes_gpc offとしてみてはいかがでしょうか?
例えば今実際にこちらの環境で化けている「琥珀」は、SJISでは %E0%E6%E0%DF で、EUC-JPでは %E0%E8%E0%E1 です。
%5Cを含まないので異なる問題だと思います。
ともかく、このような問題がある事も覚えておきます。
引き続き回答をお待ちしています。
http://jp.php.net/manual/ja/function.mb-detect-order.php
PHP: mb_detect_order - Manual
header関数は関係なかったようですね。すみませんm(__)m
mb_detect_orderが現在、「no value」となっていますが、「auto」としてみてはいかがですか?
これでも、化けるようでしたら、下記のURLをご覧下さい。
何度もすみません。
http://ns1.php.gr.jp/pipermail/php-users/2005-April/025814.html
[PHP-users 25298] mb_convert_encoding/mb_detect_encoding について
上記URLを見ますと、php-4.3.11では、不具合?らしきものがあるようですが、パッチを適用することにより、改善されています。
パッチを適用されてみてはいかがでしょうか?
設定の変更やパッチの適応は最終手段としておきます。現用系を止める訳にはいかないシステムなので....
2番目のURL、非常に参考になりました!
自分の環境の場合、ブラウザ側でShift-JISでsubmitした文字列がPHPスクリプト側ではEUC-JPで取得できるのですが(色々試した結果確定です)、特定の文字列(琥珀、とか)の場合のみ、EUC-JPに変換されずShift-JISのまたわたってきていると解りました。というか、ブラウザから渡された文字コードがEUC-JPだと誤認しているようです。
....というか、文字コードの範囲を考えると、%E0%E6%E0%DFってShift-JISかEUC-JPか自動判別不可能のような....?
引き続き回答をお待ちしております。
http://php.s3.to/man/function.mb-convert-encoding.html
mb_convert_encoding
受信側でpostで送られてくるときにEUC-JPで送られてきている為で、
$data = mb_convert_encoding($_POST[’data’],”EUC-JP”,”SJIS”);
print $data;
でSJISに変換されて正常に表示できませんでしょうか?
3番目の回答に書きましたが、通常はShift-JISでsubmitされたものがPHPスクリプト側ではEUC-JPに変換されて取れるのですが、特定の文字列の場合だけShift-JISのまま取れている、という状況です。
http://jp.php.net/manual/ja/function.mb-detect-encoding.php
PHP: mb_detect_encoding - Manual
mbstring.detect_order no value
mbstring.http_input auto
原因はこの2点です。
http_inputがautoなんで文字判定に失敗します。
ここを.htaccessでpassにして、
スクリプト内で
mb_detect_order(’ascii, jis, utf-8, sjis-win, eucjp-win’)
を設定します。
(sjisのがeucよりも使われていると判断して優先させる)
mb_internal_encoding()も設定したほうがよいでしょう。
美乳は使わないらしいですが、上記設定にして
<input type=”hidden” name=”c” value=”美乳”>
$charcode = mb_detect_encoding($_POST[’c’]);
この$charcodeを利用してmb_convert_encoding($_POST[’message’], ’変換したいコード’, $charcode);
とすれば”意図的に”name=cのvalueを変更されない限り正常に変換されます。
mbstring.http_outputもpassにするのが個人的には好きです。
文字コードの自動判別をSJIS優先にした場合「EUC-JPで文字コードを投げてくるブラウザはないのか?」という点が気になります。
#Unix、Linux用のブラウザが該当しそうです。
お陰さまで色々情報が集まりました。結局、手元で発生した文字化けの原因は2種類あったようです。
・「琥珀」に関して言えば、Shift-JISの「琥珀」の文字コードである %E0%E6%E0%DF に相当するEUC-JPの文字「琅珎」が存在するため、この文字だけを入力されたらSJISかEUC-JPか判別のしようがない。
・「勇」でも化ける箇所があるのですが、これは文字コードを(正しくはEUC-JPなのに)UTF-8と誤認(?これもUTF-8で相当する字が存在するだけかも)している。
まだどう対処するかは決まっていませんが、決めるのに十分な情報は集まったと思いますので、これで質問を終了します。
皆様ありがとうございました。
駄目でした。
ブラウザはIE6とFireFoxでテストしていますが、header関数の指定がなくてもブラウザ側はHTMLのエンコードをShift-JISと認識しています。
またsubmit後のURLを見る限り、両ブラウザとも入力された漢字をShift-JISの文字コードのままurlencodeして送信しています。
ここからは推測になりますが。
PHP側でprint mb_convert_encoding($_REQUEST[’string’],”SJIS”,”EUC-JP”);等としていて通常は正常に動く所を見ると、PHP側はShift-JISで送信された文字列を、文字コードを「自動判別」した上でEUC-JPに変換し、PHPスクリプトに渡しているようです。
おそらくは自動判別の時に、Shift-JIS以外と判定してバグってるんじゃないかと....
#ブラウザが必ずShift-JISで送ってくるという保障もないので頭が痛いです。