[PHP-dev 1392] mbstring関連での微妙な挙動について
Seiji Masugata
s.masugata @ digicom.dnp.co.jp
2008年 3月 10日 (月) 16:03:50 JST
こんにちわ、桝形です。
mbstring関連で、いくつか微妙な挙動に遭遇したので報告しておきます。
どちらもファイルアップロード絡みです。
--------------------------------------------------------------------
(1)
例えば c:\test\hoge\huga.txt というファイルをアップロードした場合
PHP的に色々と処理を行った結果、最終的には huga.txt と、
ファイル名だけになり、$_FILES 配列の ['name'] 項目に格納されます。
http://jp.php.net/fileupload
この時、アップロードしたファイル名(フルパス)に特定のマルチバイトが
含まれている、かつmbstringの設定状況によっては、hoge\huga.txt と
ファイル名だけではなくて、一部のディレクトリ名も付与された形で
$_FILES 配列の ['name'] 項目に格納されてしまいます(主にIEで発生)。
mbstring.language = Japanese
mbstring.internal_encoding = EUC-JP
mbstring.encoding_translation = On
mbstring.http_input = pass
mbstring.script_encoding = SJIS
ちょっと調べてみたところ、--enable-zend-multibyte を有効にして
この機能を使っている場合、かつ mbstring.http_input が pass 設定
(入力の自動変換を無効)になっていると、このような挙動になるようです。
中途半端な例で恐縮ですが、SJIS のマルチバイト文字列をEUC-JP と
仮定して処理してしまっているようで、この為、正しく処理ができて
いないようです。
/php-src/main/rfc1867.c の中身を確認したところ、文字コード変換を
行う・行わないの判定は php_mb_encoding_translation関数で行って
いるようですが、この関数の中身が、
/* {{{ MBSTRING_API int php_mb_encoding_translation() */
MBSTRING_API int php_mb_encoding_translation(TSRMLS_D)
{
return MBSTRG(encoding_translation);
}
/* }}} */
mbstring.encoding_translationディレクティブしか見ていないようです。
以下のパッチは安直かもしれませんが、期待する結果になりました。
--- php5.2-200803050130,orig/ext/mbstring/mbstring.c 2008-02-17 12:33:27.000000000 +0900
+++ php5.2-200803050130/ext/mbstring/mbstring.c 2008-03-05 15:52:54.000000000 +0900
@@ -4104,7 +4104,11 @@
/* {{{ MBSTRING_API int php_mb_encoding_translation() */
MBSTRING_API int php_mb_encoding_translation(TSRMLS_D)
{
- return MBSTRG(encoding_translation);
+ if( MBSTRG(encoding_translation) && MBSTRG(http_input_list_size) > 0 && MBSTRG(http_input_list)[0] != mbfl_no_encoding_pass ) {
+ return 1;
+ } else {
+ return 0;
+ }
}
/* }}} */
--------------------------------------------------------------------
(2)
http://jp.php.net/mbstring
--------------------------------------------------------------
注意: PHP 4.3.3 以降、HTML フォームの enctype が
multipart/form-data に設定され、かつ、 php.ini において
mbstring.encoding_translation に On が指定されている場合、
POST データの変数とアップロードされたファイルの名前の
文字エンコーディングは、 内部文字エンコーディングに変換
されます。
--------------------------------------------------------------
PHPマニュアルには、このように記載されていますが、5.2.5では
ファイルアップロード時に内部コードに変換されないケースが
あるようです。
mbstring.language = Japanese
mbstring.internal_encoding = EUC-JP
mbstring.encoding_translation = On
mbstring.http_input = SJIS
/php-src/main/rfc1867.c の中身を確認したところ、filter 拡張
モジュールをコンパイル・オプションで有効にしていた場合、
内部コードへ変換を行う関数を経由していないようです。
filter 拡張モジュールをコンパイル・オプションで無効にしていた
場合は期待した結果になります。
この位置で正しいのか若干疑問は残りますが、以下のパッチを
適用したところ、期待する結果になりました。
--- php5.2-200803050130,orig/main/rfc1867.c 2007-12-31 16:33:36.000000000 +0900
+++ php5.2-200803050130/main/rfc1867.c 2008-03-05 15:53:01.000000000 +0900
@@ -961,6 +961,13 @@
php_rfc1867_callback(MULTIPART_EVENT_FORMDATA, &event_formdata, &event_extra_data TSRMLS_CC);
}
+#if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING)
+ if (php_mb_encoding_translation(TSRMLS_C)) {
+ php_mb_gpc_stack_variable(param, value, &val_list, &len_list,
+ &num_vars, &num_vars_max TSRMLS_CC);
+ }
+#endif
+
if (!strcasecmp(param, "MAX_FILE_SIZE")) {
max_file_size = atol(value);
}
--------------------------------------------------------------------
(1)については、差し支えないようであれば、こちらで作業しようと
思いますが、(2)については 残念ながら karmaを持っていません。。。
この為、現在のメンテナにお願いをしないといけません。
ただ、実装が問題ないようであれば、こちらでお願いをしようと思います。
確認して頂けると幸いです。
長文失礼しました。
--
Seiji Masugata <s.masugata @ digicom.dnp.co.jp>
PHP-dev メーリングリストの案内