CodeIgniterのUploadクラスは画像とその他ファイルを同時に許可できない
全然PHPのネタが無かったので、ちょっとやってみようかと思います。
とある開発でCodeIgniterのUploadクラスを使っていたのですが、
アップロードされたファイルに対して、許可する拡張子を画像+その他拡張子(例えばzipとかtxtとか)に設定すると、
「許可されていない拡張子です」
というエラーがでてアップロードされません。こんなコードで発覚。
CIのバージョンは1.7.1です。
$config['allowed_types'] = ‘gif|jpg|png|zip|txt’;
// その他config設定は省略
$this->load->library(‘upload’, $config);
$this->upload->do_upload();
こう書くと、画像以外のzipファイルをアップロードしたときにはうまくアップロードされません。
でも、$config['allowed_types']の項目は必須設定です。
「う~ん、なんでかなぁ」と思いながらソースを読んでいたら、
system/libraries/Upload.php line:566くらい
// Images get some additional checks
if (in_array($val, $image_types))
{
if (getimagesize($this->file_temp) === FALSE)
{
return FALSE;
}
}
と、こんな記述を発見。ちなみに$image_typesには画像拡張子の配列が、$valにはallowed_typesで設定した拡張子(|で分割されています)
が入っています。
これだと、allowed_typesの中に画像系の拡張子が入っていると全てgetimagesize()が実行されます。
で、画像ファイル以外なら当然FALSEが返ります。その結果、アップロードは失敗。
これだと困るので、以下にように追記したらうまく動きました。
// Images get some additional checks
// 画像系の拡張子で、かつアップロードされたファイルの拡張子の末尾が画像系拡張子であればチェック
if (in_array($val, $image_types) && strpos(substr($this->file_ext, 0), $val) !== FALSE)
{
if (getimagesize($this->file_temp) === FALSE)
{
return FALSE;
}
}
「strpos(substr($this->file_ext, 0), $val) !== FALSE」
とすることで、アップロードされたファイルの拡張子もチェックし、TRUEならgetimagesize()やってくれ、ってことです。
$this->file_extにはドットを含む拡張子の情報が入っているので、substrで1文字目をカットしてます。
セキュリティ的にどうなのかと言われるとアレですが、そもそも画像以外をアップロードさせるアプリケーションはそれだけリスクが高まるので、仕方無いですかね。
私は恒久的に使うのでコアに追記しましたが、疑り深い方はMY_Upload.phpなどでオーバーライドしたほうがいいかもです。

