[PHP-users 28862] Re: 文字化け

Reiji Matsumoto matsumoto @ spline.oc.to
2006年 3月 28日 (火) 19:01:20 JST


松本です。
> > > php_value mbstring.http_input pass
> > > と設定する場合は
> > > php_value magic_quotes_gpc off
> > > も一緒に設定しなければ駄目。
> > > php_value magic_quotes_gpc on
> > > を利用したければ
> > > php_value mbstring.http_input auto
> > > と設定しなさい。

magic_quotes_gpcの制御は、mbstring.http_inputの制御とまったく
関係なく、そしてmbstring.http_inputの後に処理されるようです。
よって文字コード変換した後、magic_quotes_gpcがクォート対象と
するコードが含まれていればクォートされてしまいます。
すでに「いずれの場合も(他にも理由があって)magic_quotes_gpc
はオフにすべき」という結論が出てますので、あまり関係ないですね。

> この前処理というのは
> ・ini_setで文字コード関係のPHPの設定を行う
> ・magic_quotes_gpcはoff。必要があれば自身でクォートする
> ・入力文字列については必要があれば文字コード変換を行う
> という感じの処理でしょうか?
http_input 等の処理はスクリプト開始前に行われますので、ini_set
で設定するのでは遅いです。よって、php.iniや.htaccessの状態が
どのような場合でも正確に内部エンコーディングに変換した文字列
を得られる事を理想とするなら、ini_setは利用できません。

私としては、
 ・magic_quotes_gpc がオンかも知れないしオフかも知れない
 ・mbstring.encoding_translationはオンかも知れないしオフかも知れない
 ・mbstring.http_input は pass かも知れないし autoかも知れない
 ・どのような文字コードが送信されてくるかは分からないが、一度
   に送信される文字コードはすべて統一されている

というような状態を仮定して、以下のようなコードを前処理に利用
しています。

$key='J'; // 判定用としてGET、POSTする変数
$val='京'; // 判定用文字
$inenc = 'EUCJP'; // 内部エンコーディング
$conv_table = array("EUCJP","SJIS","UTF8");// 調査する文字コード

foreach($conv_table as $conv)
{
  if(mb_convert_encoding($_POST[$key],$inenc,$conv) === $val)
  {
    foreach($_POST as $k => $v)
    {
      if(get_magic_quotes_gpc()) $_POST[$k] = stripslashes($_POST[$k]);
      $_POST[$k] = mb_convert_encoding($v,$inenc,$conv);
    }
    break;
  }
}

実際には配列が入れ子になっている場合やGET変数、COOKIE等の処理も含め
もう少し複雑です。
とても幸いな事に、magic_quotes_gpcの処理はmbstring.encoding_translation
より後に行われるようなので、上記コードで大抵の場合はEUCJPに変換され
るようです。
ただし、いわゆる「はしご高」の問題はまた別問題ですので、この処理以外
に変換テーブルを用意したりしています。
また、当然ながら送信元のhtmlでは、

<input type="hidden" name="J" value="京">

というようなコードが必要になります。

検証は不十分な可能性がありますので、利用する場合は注意して下さい。
特にJISに関してはあまり試した事がないので要注意です。




PHP-users メーリングリストの案内