Определить тип данных из file_get_contents()

Я пишу приложение командной строки в PHP, которое принимает путь к локальному входному файлу в качестве аргумента. Входной файл будет содержать одну из следующих функций:

  • закодированный ассоциативный массив JSON
  • A serialized() версия ассоциативного массива
  • Базовая 64-кодированная версия ассоциативного массива serialized()
  • кодированный закодированный ассоциативный массив JSON с кодировкой Base 64
  • Простой старый ассоциативный массив PHP
  • Мусор

Короче говоря, существует несколько несходных программ, которые я не могу контролировать, которые будут писать в этот файл, единообразным способом, который я могу понять, когда я действительно выясню формат. Как только я выясню, как глотать данные, я могу просто запустить с ним.

Я рассматриваю следующее:

  • Если первый байт файла {, попробуйте json_decode(), посмотрите, не сработает ли он.
  • Если первый байт файла < или $, попробуйте include(), посмотрите, не сработает ли он.
  • если первые три байта файла совпадают с: [0-9], попробуйте unserialize().
  • Если не первые три, попробуйте base64_decode(), посмотрите, не сработает ли он. Если не:
    • Еще раз проверьте первые байты декодированных данных.
    • Если все это терпит неудачу, это мусор.

Это просто кажется довольно дорогостоящим для довольно простой задачи. Могу ли я сделать это лучше? Если да, то как?

Ответ 1

Здесь не так много оптимизировать. Подход магических байтов - это уже путь. Но, конечно, можно избежать фактических функций десериализации. Можно использовать регулярное выражение для каждого из них (что, несмотря на то, что meme часто быстрее, чем PHP, фактически распаковывает вложенный массив).

base64 достаточно легко прощупать.

json можно проверить с помощью регулярного выражения. Самый быстрый способ проверить, является ли строка JSON в PHP? является версией RFC для ее защиты в JS. Но было бы вполне возможно написать полное правило соответствия json (?R).

serialize немного сложнее без правильной функции распаковки. Но с некоторыми эвристиками вы уже можете утверждать, что это сериализуете blob.

php Сценарии массива могут быть исследованы несколько быстрее с помощью token_get_all. Или если формат и данные достаточно ограничены, снова с регулярным выражением.

Более важный вопрос здесь: нужна ли вам надежность - или простота и скорость?

Ответ 2

Для скорости вы можете использовать утилиту file(1) и добавить "магические числа" в /usr/share/file/magic. Он должен быть быстрее, чем чистая альтернатива PHP.

Ответ 3

Вы можете попробовать json_decode() и unserialize(), которые вернут NULL, если они не сработают, затем base64_decode() и запустите это снова. Это не быстро, но это бесконечно меньше подверженности ошибкам, чем ручная обработка их...

Ответ 4

Проблема здесь в том, что, если вы не знаете, что это может быть, вам нужно разработать алгоритм обнаружения. Условные обозначения должны быть установлены с расширением (проверьте расширение, если оно не удается, сообщите, кто бы там ни разместил файл, чтобы разместить правильное расширение), в противном случае вам нужно будет проверить себя. Большинство алгоритмов, которые обнаруживают, какой тип файла действительно использует, используют thisustics для определения его содержимого (exe, jpg и т.д.), Потому что обычно у них есть какая-то подпись, которая идентифицирует их. Поэтому, если вы не представляете, какой контент будет определен, лучше всего искать функции, характерные для этого содержимого. Это иногда означает чтение более чем нескольких байтов.