如何检测文件是否是 PHP 中的图标?

How to detect if a file is a favicon in PHP?

我需要检查上传的文件是否是网站图标类型,我需要以安全的方式进行。

如果我通过输入文件上传网站图标文件并打印 $_FILES 变量,我可以看到该变量具有以下类型值:

image/vnd.microsoft.icon

我知道我可以检查该值是否匹配,但我认为用户可以丢弃它。如果有人能给我一些提示,我将不胜感激

  1. 使用工具将您的 png 转换为 ico 文件。你可以搜索"favicon generator",你可以找到很多在线工具。
  2. 将 ico 地址放在带有 link 标签的 head 中:

    <link rel="shortcut icon" href="http://sstatic.net/Whosebug/img/favicon.ico">
    

您可以使用各种工具:

文件信息

您可以直接从 PHP 使用 FileInfo:

$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo finfo_file($finfo, 'the_file_to_check.ico');
// Should print something like 'image/x-icon'
finfo_close($finfo);

如果您的系统上设置了 FileInfo,这可能是最简单的方法。

ImageMagick

ImageMagick 更进一步,实际解码文件内容,列出嵌入的图像:

$ identify favicon.ico
favicon.ico[0] ICO 16x16 16x16+0+0 32-bit sRGB 15.1KB 0.000u 0:00.000
favicon.ico[1] ICO 32x32 32x32+0+0 32-bit sRGB 15.1KB 0.000u 0:00.000
favicon.ico[2] ICO 48x48 48x48+0+0 32-bit sRGB 15.1KB 0.000u 0:00.000

(本例中从命令行调用)

我不知道 FileInfo 如何处理 ICO 文件,但 ImageMagick 可能更安全,因为它确实必须解码文件的重要部分。

由于 ImageMagick 支持多种格式,因此检查它的输出很重要,而不仅仅是它的 return 代码(它在 JPG、SVG 等格式上也能成功)。

IcoUtils

作为 ImageMagick 的轻量级替代品,IcoUtils 可以做到这一点:

$ icotool -l favicon.ico
--icon --index=1 --width=16 --height=16 --bit-depth=32 --palette-size=0
--icon --index=2 --width=32 --height=32 --bit-depth=32 --palette-size=0
--icon --index=3 --width=48 --height=48 --bit-depth=32 --palette-size=0

$ icotool -l not_a_favicon.svg
favicon.svg: not an icon or cursor file (reserved non-zero)

不幸的是它的 return 代码总是 0,迫使你实际检查它的输出。

它可以安装在 Ubuntu 上:

sudo apt-get install icoutils

如果您想避免使用任何外部工具,https://github.com/lordelph/icofileloader 提供了一种本机 PHP 方法来解析 .ico 文件

$loader = new Elphin\IcoFileLoader\IcoFileService;
try {
    /** @var Elphin\IcoFileLoader\Icon $icon */
    $icon = $loader->fromFile('/path/to/icon.ico');

    //perform further inspection or render the icon as an image here...

} catch (\Exception $e) {
    //not an .ico file
}