Windows
0x5C
ダメ文字
5c問題
PHP7.1

Windows版 PHP 7.1 で日本語パス(パス文字列のエンコーディング)が対応されることによる影響

More than 1 year has passed since last update.

現象

#1854 Fixed the UTF-8 and long path support in the streams on Windows. が PHP 7.1.0 Alpha 2 に マージ されました。

  1. 最大パス長が2048バイトになりました。
  2. 今まで、 get_file_contents の引数などのパス文字列のエンコーディングは、日本語版Windowsの場合、 CP932 でしたが、これが、INIディレクティブ(internal_encoding, default_charset, zend.multibyte) に依存するようになりました。(RFC)
  3. コンソールのコードページがやんわり対応されました。

(※ PHP 7.1 UPGRADE NOTES の 12. Windows Support も参照)

この対応により、間接的に日本語パス(0x5c問題)が解決されますが、既存のPHPソースコードにて、パス文字列のエンコーディングを操作していたり、0x5cをエスケープしていた場合は、 個別に修正が必要です。

対策(及び確認項目)

対策方針候補

  1. 設定もアプリケーションも全て UTF-8 にする(推奨)
  2. php.ini の default_charsetCP932 にする。(影響範囲に注意)
  3. 個別に ini_set('default_charset', 'CP932'); (コンソール出力が乱れる可能性あり)
  4. 個別に mb_convert_encoding('日本語.txt', 'UTF-8', 'CP932') (緊急応急処置として)

※ 基本的に 1. で対応(したい)。大量のPHPソースコードを Shift_JIS(CP932) にしていた場合など、 他も検討。

影響のありそうなケース(既存のPHPソースコードのチェック対象)

Case 2 以降の例では、file_get_contents の引数のみですが、 fopen, file などパス文字列に関連する全ての処理がチェック対象です。

Case 1: コンソール出力時に文字コードを変換している場合

<?php
if (PHP_OS === 'WIN32' || PHP_OS === 'WINNT') {
    ob_start(function($buffer) {
      return mb_convert_encoding($buffer, 'CP932', 'UTF-8');
    });
}
echo '日本語';
/* vim:set fenc=utf8 ff=unix: */

ソースコードがUTF-8の場合、 ob_start ごと不要。PHP5も対応しときたい場合は以下

<?php
if (((PHP_OS === 'WIN32') || (PHP_OS === 'WINNT'))
 && (version_compare(PHP_VERSION, '7.1.0') < 0)
) {
    ob_start(function($buffer) {
      return mb_convert_encoding($buffer, 'CP932', 'UTF-8');
    });
}
echo '日本語';
/* vim:set fenc=utf8 ff=unix: */

Case 2: パスの文字列のエンコーディングを変更していた場合。

<?php
echo file_get_contents(mb_convert_encoding('日本語.txt', 'CP932', 'UTF-8'));
/* vim:set fenc=utf8 ff=unix: */

以下のようにエンコーディング変更ロジックを削除。

<?php
echo file_get_contents('日本語.txt');
/* vim:set fenc=utf8 ff=unix: */

Case 3: パスの文字列の 0x5c をエスケープしていた場合。

<?php
echo file_get_contents(mb_convert_encoding('表\.txt', 'CP932', 'UTF-8'));
echo file_get_contents(addcslashes(mb_convert_encoding('表.txt', 'CP932', 'UTF-8'), '\\'));
/* vim:set fenc=utf8 ff=unix: */

このエスケープ処理も削除。

<?php
echo file_get_contents('表.txt');
echo file_get_contents('表.txt');
/* vim:set fenc=utf8 ff=unix: */

関連