PHPにはmime_content_type
、finfo_buffer
といったファイルの種類を検出する関数があります。これらの関数にファイルを渡すとimage/gif、text/plainといった様にファイル形式を文字列で返してくれます。このファイル形式を表す文字列をMIMEタイプと言います。
PHP: mime_content_type – Manual
PHP: finfo_buffer – Manual
PHPがこのMIMEタイプを返す仕組みについて紹介します。
ざっくばらんに言えば以前記事にした際に用いた File Signatures で定義されているファイルの形式のチェックをしています。
File Signatures
【PHP】ファイルの中身からファイル形式を識別する – 株式会社シーポイントラボ | 浜松のシステム・RTK-GNSS開発
File Signatures はファイルの先頭にあるファイル形式ごとに定まったバイト列です。例えば、PNG画像ファイルならば\x89\x50\x4e\x47\x0d\x0a\x1a\x0a
となり、次の画像の様にテキストエディタから見えます。
PHPはこれを元に、ファイルの中身に対応する MIME Content-type を出力します。
PHPの MIME Content-type 関連の処理は次のディレクトリ内に含まれます。
php-src/ext/fileinfo at PHP-8.1 · php/php-src
php-src/ext/fileinfo/libmagic at PHP-8.1 · php/php-src
MIME Content-type 関連の処理は特に libmagic 以下に集中しています。libmagic という名前のディレクトリの中身はライブラリの libmagic の PHP 版です。元々は単純なクローンだった様ですが PHP 内部に組み込まれて年月が経つうちに徐々に変わりました。とはいえ基本はライブラリとしての libmagic なので次の本家と同じ部分も多いです。
ファイルに含まれるバイト列とファイル形式の対応を行ってMIMEタイプを出力するには辞書的なデータベースが必要です。PHP組み込みのデータベースは次に入っています。
php-src/create_data_file.php at PHP-8.1 · php/php-src
php-src/data_file.c at PHP-8.1 · php/php-src
create_data_file.php というスクリプトで PHP に組み込むためのデータベースを作っています。data_file.c の配列を検索すると含まれているバイト列が File Signatures のそれだとわかります(0x89, 0x50, 0x4E, 0x47,
などがヒットします)。
このデータベースは実は外部から与えることができます。これは MIME Content-type を得られる関数であるfinfo_buffer
を使うための関数であるfinfo_open
内で設定できます。
これを用いることで次の様にオリジナルのファイル形式をオリジナルのMIMEタイプとして返すこともできます。
<?php // データベースにオリジナルの File Signatures とMIMEタイプの対応表ファイルを渡す $finfo = finfo_open(magic_database: __DIR__.DIRECTORY_SEPARATOR.'tmp.magic'); // 定義したバイト列に沿うバイト列を渡し、MIMEタイプを返させる $mimeType = finfo_buffer($finfo, "\x11Cplab適当な中身", FILEINFO_MIME_TYPE); // 独自定義のMIMEタイプが返ってくる echo $mimeType."\n"; // app/cplab
# tmp.magic # original file. 0 string \x11Cplab Original File Format !:mime app/cplab