WordPress でのアップロードファイル自動リネームは、CAPTCHA生成などで画像表示に失敗するケースもある

カテゴリー: スニペット,

WordPress でアップロードする画像ファイルを自動リネーム

日本語名ファイルでそのままアップロードしたりファイル名規則をいちいち考えたくなかったりという場合に重宝するコードで、私がよく使うのはUNIXタイムにリネームするもの。functions.php やプラグインなどで利用してます。

// 画像ファイルアップロード時にファイル名をUNIXタイムにリネーム
// https://keikenchi.com/how-to-change-file-name-to-time-stamp
function img_name_to_timestamp($filename) {
	$path_info = pathinfo($filename);
	$ext  = empty($path_info['extension']) ? '' : '.' . $path_info['extension'];
	if( $path_info['extension'] == ('jpg' || 'png' || 'gif')){
		$filename = strtolower(time().$ext);
	}
	return $filename;
}
add_filter('sanitize_file_name', 'img_name_to_timestamp', 10);

所有サイトでお試し導入していたのですが、ひとつ問題が出てきました。

CAPTCHA生成などで画像表示に失敗する

セキュリティ系でかなり便利なWordPressプラグイン SiteGuard WP Plugin。ログインやコメント等にCAPTCHAを表示し画像認証を設けることもできます。ひらがなだとかなり海外系スパム・クラックボットに有効です。

このプラグインでCAPTCHA画像生成する際にファイル名が変更されたため、HTML表示時に画像リンクが合わずに表示できなくなりました、これはさすがにログインできません。

これはWordPressでのすべてのファイルアップロード時にファイル名をチェックする sanitize_file_name にフィルターフックしているためです。ファイル名サニタイズが目的の関数。

アップデートを考えると SiteGuard WP Plugin 側、WordPressコア側の両方どちらにも手を入れれず、ちょっと困りました。

SiteGuard WP Plugin プラグインでの応急処置

SiteGuard WP Plugin での生成ファイル名の規則が「1593232498.png」のような、常に12~14桁の数字であることに気づいたので、ファイル名が全部数字ならリネームしないという方法で暫定対処します。うーんこの無理矢理感。

というわけで最初のコードを改変。

// 画像ファイルアップロード時にファイル名をUNIXタイムにリネーム
// https://keikenchi.com/how-to-change-file-name-to-time-stamp
function img_name_to_timestamp($filename) {

    $path_info = pathinfo($filename);
    // wp_die(var_dump($path_info));

    $ext = empty($path_info['extension']) ? '' : '.' . $path_info['extension'];
    if( $path_info['extension'] == ( 'jpg' || 'jpeg' || 'png' || 'gif' )){
        // 文字列型かつ数字のみならリネームしない(SiteGuard WP Plugin のCAPTCHAをスルーさせる)
        if(ctype_digit($path_info['filename'])){
            return $filename;
        } else {
            $filename = strtolower(time().$ext);
        }
    }
    return $filename;
}
add_filter('sanitize_file_name', 'img_name_to_timestamp', 10);

PHPで数字かどうかチェックする方法はいくつかあり、たいてい (int) でキャストすることが多いのですが、今回適切なのは ctype_digit と思われます。

$a = ‘123’ $b = 123; $c = ‘123xx’; のように3パターンある場合、$a だけ TRUE なら良しです。

<?php
$a = '123';
$b = 123;
$c = '123xx';


echo '=== ctype_digit ==='.PHP_EOL;

echo '$a: '. ctype_digit($a).PHP_EOL;
echo '$b: '. ctype_digit($b).PHP_EOL;
echo '$c: '. ctype_digit($c).PHP_EOL;


echo '=== is_numeric ==='.PHP_EOL;

echo '$a: '. is_numeric($a).PHP_EOL;
echo '$b: '. is_numeric($b).PHP_EOL;
echo '$c: '. is_numeric($c).PHP_EOL;


echo '=== is_int ==='.PHP_EOL;

echo '$a: '. is_int($a).PHP_EOL;
echo '$b: '. is_int($b).PHP_EOL;
echo '$c: '. is_int($c).PHP_EOL;


echo '=== preg_match ==='.PHP_EOL;

echo '$a: '. (preg_match('/^[0-9]+$/', $a)).PHP_EOL;
echo '$b: '. (preg_match('/^[0-9]+$/', $b)).PHP_EOL;
echo '$c: '. (preg_match('/^[0-9]+$/', $c)).PHP_EOL;

?>

結果

=== ctype_digit ===
$a: 1
$b: 
$c: 
=== is_numeric ===
$a: 1
$b: 1
$c: 
=== is_int ===
$a: 
$b: 1
$c: 
=== preg_match ===
$a: 1
$b: 1
$c: 0

と、ここまで書いて。本来ならば「メディアライブラリに画像を追加する場合のみ、sanitize_file_name にフックする」という処理が最もスマートなはずです。調べたところ wp_insert_attachment や media_handle_upload などにフックが存在するっぽいんですが、ちょっと力尽きました。

いつか他の問題が出てきたら対処する、ということで今回は逃げます。


関連記事

関連記事はまだありません

スニペット」のBookmark
「スニペット」記事一覧