« Google Mapsを使ってみよう2 | トップページ | XML Libraryを使ってみよう »

2005年11月13日

PHPのShift_JIS文字化け対策1

PHPで開発の経験を積んでいくと必ずと言っていいほど文字化けに悩まされます。
PHPに限ったことじゃないけど、文字化け対策は私達WEB業界の永遠のテーマかなって思ってます^^;
私は文字コードを統一したり、文字コードの変換などある程度ルールを決めてうまく回避してます。
WEBシステム開発において、「Shift_JIS」はかなりの曲者で、私もかなり苦戦してきました。
一番問題になったのが「\」マークが自動でついてくることで、例えばフォームの文字列に「表示」を入力してフォームを送信するとフォームの値が「表\示」となって返ってきます。
この業界で仕事を始めた頃は「Shift_JIS」を使用しないで「EUC-JP」等で統一することでうまく回避してきたのですが、どうしても「Shift_JIS」で開発しなきゃいけない場合もあります。
例えば、携帯サイトを作る場合は古い機種も対象にいれるので「Shift_JIS」での開発が必要になります。
最近の機種だと「Shift_JIS」以外も可能みたいですが、古い機種は「Shift_JIS」しか表示出来ません。
さて、前置きが長くなりましたが「\」マークが自動でついた時にどのような対策案があるのかご紹介します。

Shift_JIS文字化け問題のお話をする前に「"」や「\」等の特殊文字について説明します。

「\」マークはこの業界ではエスケープ文字と言います。
PHPで文字列を変数に格納する際に以下のような記述をします。

$str = "変数に文字列を格納";

「"」を文字列として使用したい場合に「"」の前に「\」を入れることで「"」を文字列として判断してくれます。
$str = "「\"」を変数に格納";

次に「\」を文字列として使用したい場合は以下のように記述します。
$str = "「\\」を変数に格納する";

$strをechoやprint等で表示させると「「\」を変数に格納する」と表示されます。
以上のように「"」や「\」の特殊文字を文字列として使用する場合はエスケープする必要があります。

入力フォームを送信した際に、PHPでは「"」「'」「\」を自動でエスケープしてくれます。
Shift_JISで「\」をコードに変換すると「5C」です。
「表」は「95 5C」、「申」は「90 5C」、「ソ」は「83 5C」となります。
こうやって見ると「\」マークが自動でつくのにはパターンがあるのが分かります。
「5C」を「5C5C」と変換する為、
「表」→「表\」
「申」→「申\」
「ソ」→「ソ\」
となるわけです。

これらの文字化け対策として以下の2つの方法があります。
1.自動エスケープ処理をやめる
2.自動エスケープ処理をした後にアンエスケープする

1の対策案について、PHPの設定ファイル(php.ini)を変更するか、または「.htaccess」でPHPの設定ファイルを強制的に変更します。
PHPの設定ファイルの中に、「magic_quotes_gpc」というのがあります。
これを「On」にすると、「"」「'」「\」等を自動でエスケープしてくれます。
これを「Off」にすることで「\」が自動でつかなくなります。
「.htaccess」での対応方法は「.htaccess」の中に

php_value magic_quotes_gpc Off

と記述します。
「"」や「'」や「\」等をエスケープしなくなるので、セキュリティホールになる可能性があります。
「Off」にした際は、イタズラ防止のプログラムを忘れずに作りましょう。特にMySQL等のデータベースを使用するときには要注意です。

2の対策案について、プログラム上でアンエスケープします。
PHPの「stripslashes」関数を使用します。「html」という名前のフォームが送られてきた場合は以下のように処理します。

$html = stripslashes($_POST['html']);

この対策案については、レンタルサーバーなどで設定ファイルの変更権限がなく「.htaccess」権限もない場合に使えます。

これらをちょっと応用させて、「magic_quotes_gpc」がOnかOffかを判断させてアンエスケープ処理を行なってみます。
追記)magic_quotes_gpcが「On」の場合、ini_get('magic_quotes_gpc')は「1」になります。

if(ini_get('magic_quotes_gpc') == "1") {
  $html = stripslashes($_POST['html']);
}
else {
  $html = $_POST['html'];
}

「ini_get」関数はPHPの設定を取り出す関数です。
上記の例では、「ini_get('magic_quotes_gpc')」が「1」の場合はアンエスケープさせてそれ以外の場合は、エスケープさせないようにしています。

今回は、Shift_JISの自動エンコードの問題についてお話させていただきました。
実務で使う際には、上記の方法だけでは不足だと思います。「"」「'」「\」だけをエスケープさせる処理は必要になると思います。
文字コード対策で何かのやくにたってくれたら幸いですm(_ _)m

PHPのShift_JIS文字化け対策2」を見る

トラックバック

このエントリーのトラックバックURL:
http://www.s-memo.net/mt/mt-tb.cgi/1

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)