Ответ 1
Магический номер. Если вы можете прочитать первые несколько байтов двоичного файла, вы можете узнать, что это за файл.
Я программирую что-то, что позволяет пользователям хранить документы и изображения на веб-сервере, которые будут храниться и извлекаться позже. Когда пользователи загружают файлы на мой сервер, PHP сообщает мне, какой тип файла он основан на расширении. Тем не менее, я боюсь, что пользователи могут переименовать zip файл как somezipfile.png и сохранить его, тем самым сохраняя zip файл на моем сервере. Есть ли разумный способ открыть загруженный файл и "проверить", чтобы убедиться, что он действительно относится к указанному типу файлов?
Магический номер. Если вы можете прочитать первые несколько байтов двоичного файла, вы можете узнать, что это за файл.
Посмотрите FileInfo Расширение PECL для PHP, которое может выполнять MIME-макеты для вас.
Сорт. Большинство типов файлов имеют некоторые байты, зарезервированные для их маркировки, поэтому вам не нужно полагаться на расширение. Сайт http://wotsit.org - отличный ресурс для поиска этого для определенного типа.
Если вы находитесь в системе unix, я считаю, что команда файла не полагается на расширение, поэтому вы можете отключить его, если вы не хотите писать код проверки байта.
Для PNG (http://www.w3.org/TR/PNG-Rationale.html)
Первые восемь байтов файла PNG всегда содержат следующие значения:
(десятичный) 137 80 78 71 13 10 26 10
(шестнадцатеричный) 89 50 4e 47 0d 0a 1a 0a
(обозначение ASCII C)\211 P N G\r\n\032\n
Многие типы файлов имеют " магические числа" в начале файла для их идентификации. Вы можете прочитать несколько байтов с фронта файл и сравнить их со списком известных магических чисел.
Если вы имеете дело только с изображениями, то getimagesize() должен отличать действительное изображение от поддельного.
$ php -r 'var_dump(getimagesize("b&n.jpg"));'
array(7) {
[0]=>
int(200)
[1]=>
int(200)
[2]=>
int(2)
[3]=>
string(24) "width="200" height="200""
["bits"]=>
int(8)
["channels"]=>
int(3)
["mime"]=>
string(10) "image/jpeg"
}
$ php -r 'var_dump(getimagesize("/etc/passwd"));'
bool(false)
Значение false из getimagesize не является изображением.
В unix-системе захват вывода из команды "файл" должен содержать соответствующую информацию.
Для получения точного ответа о том, как вы могли бы быстро это сделать в PHP, проверьте этот вопрос: Как найти тип файла mime с php?
В качестве побочной заметки я столкнулся с аналогичной проблемой, когда мне приходилось выполнять собственные проверки типов. Интерфейс интерфейса для моего приложения был выполнен во флэш-памяти. Файлы передавались через flash на php script. Когда я пытался выполнить проверку типа MIME с использованием php, возвращаемый тип всегда был application/octetstream, потому что он исходил от флэш-памяти.
Мне пришлось реализовать парадигму типа магических чисел. Я просто создал xml файл, в котором был сохранен тип файла, а также некоторые шаблоны определения, найденные в начале файла. После того, как файл достиг сервера, я сделал некоторый шаблон, соответствующий файлу xml, а затем принял или отклонил файл. Я не заметил никакого реального снижения производительности, которого я ожидал.
Это просто примечание для всех, кто может использовать флеш-память, так как есть передняя часть и пытается ввести проверку файла после его загрузки.
Помимо идентификации типа файла, вы можете захотеть следить за файлами с другими встроенными или добавленными к ним файлами. Это, к сожалению, потребует более глубокого анализа содержимого файла, чем просто использование "магических чисел".
Например, http://quantumrook.wordpress.com/2007/06/06/hide-a-rar-file-in-a-jpg-file/ (этот конкретный тип скрытия данных можно легко обойти, загрузив и сохранив в новый файл фактические данные изображения.. другим будет сложнее.)