ExtendedFileManager使用時に読み取り権限のないディレクトリがあるとFatal Errorになる件
とあるシステムのコンテンツ管理画面にWYSIWYGエディタのxinhaを使っており、コンテンツ(PDFやWordファイルなど)のアップロード用にExtendedFileManagerプラグインを有効にしています。
このプラグインで、突然Fatal Errorが出るようになったので調べたところ、コンテンツアップロードディレクトリ内に、とあるコンテンツのバックアップディレクトリがありました。このディレクトリはサーバー管理者が作成したのですが、ディレクトリのパーミッションがApacheから読み取れない権限となっていました。
ExtendedFileManagerは、ある起点ディレクトリ以下のディレクトリツリーを再帰的に読み込んで表示するのですが、その読み込み処理で、上記のような「読み取り権限のない」ディレクトリがあるとFatal Errorになってしまいます。
ディレクトリのパーミッションを変更すれば済む話でもありますが、汎用的なWYSIWYGエディタであるxinha側でこのようなケースが想定されていないのも困るので、ソースを確認してみました。
xinha>plugins>ExtendedFileManager
Fatal Errorになるのは、ExtendedFileManager.phpの123行目でした。
<?php 113 function _dirs($base, $path) 114 { 115 $base = Files::fixPath($base); 116 $dirs = array(); 117 118 if($this->isValidBase() == false) 119 return $dirs; 120 121 $d = @dir($base); 122 123 while (false !== ($entry = $d->read())) 124 { 125 //If it is a directory, and it doesn't start with 126 // a dot, and if is it not the thumbnail directory 127 if(is_dir($base.$entry) 128 && substr($entry,0,1) != '.' 129 && $this->isThumbDir($entry) == false) 130 { 131 $relative = Files::fixPath($path.$entry); 132 $fullpath = Files::fixPath($base.$entry); 133 $dirs[$relative] = $fullpath; 134 $dirs = array_merge($dirs, $this->_dirs($fullpath, $relative)); 135 } 136 } 137 $d->close(); 138 139 Return $dirs; 140 }
この_dirs()メソッドで起点配下のディレクトリ一覧を再帰的に取得しているのですが、「読み取り権限のないディレクトリ」の場合、121行目のdir()関数の戻り値がfalseになるようで、その場合に123行目の$d->read()部分でFatal Errorになってしまいます。
ですので、121行目を次のように変更すればOKです。
<?php if (false === ($d = @dir($base))) { return $dirs; }
dir()のマニュアルページでは・・・
PHPドキュメントのdirのページを見てみると、特に「falseが返ってくる」という記述がありませんでした。
ユーザーが投稿したコメントを見ると、戻り値をifで検証しているものもあるようですが、オフィシャルのサンプルコードが以下のようにfalseを検証しないものとなっており、xinhaのExtendedFileManagerのコードもほぼこれをコピペして使用しているように見えます。
<?php $d = dir("/etc/php5"); echo "Handle: " . $d->handle . "\n"; echo "Path: " . $d->path . "\n"; while (false !== ($entry = $d->read())) { echo $entry."\n"; } $d->close(); ?>
結論:コピペはキケン
ですよね。